mirror of
https://github.com/PlayEdu/PlayEdu
synced 2025-06-29 08:55:23 +08:00
commit
19235003d9
@ -1,4 +1,4 @@
|
|||||||
FROM openjdk:17 as builder
|
FROM eclipse-temurin:17 as builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ COPY . /app
|
|||||||
|
|
||||||
RUN /app/docker-build.sh
|
RUN /app/docker-build.sh
|
||||||
|
|
||||||
FROM openjdk:17
|
FROM eclipse-temurin:17
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
12
pom.xml
12
pom.xml
@ -75,13 +75,6 @@
|
|||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--图形验证码依赖 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.penggle</groupId>
|
|
||||||
<artifactId>kaptcha</artifactId>
|
|
||||||
<version>2.3.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
@ -139,6 +132,11 @@
|
|||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
<version>5.8.16</version>
|
<version>5.8.16</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-captcha</artifactId>
|
||||||
|
<version>5.8.16</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
|
@ -154,6 +154,15 @@ public class AppConfigCheck implements ApplicationRunner {
|
|||||||
setKeyValue("1");
|
setKeyValue("1");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new AppConfig() {
|
||||||
|
{
|
||||||
|
setName("禁止拖拽播放");
|
||||||
|
setSort(60);
|
||||||
|
setFieldType(BackendConstant.APP_CONFIG_FIELD_TYPE_SWITCH);
|
||||||
|
setKeyName("player.disabled_drag");
|
||||||
|
setKeyValue("0");
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
put(
|
put(
|
||||||
"学员配置",
|
"学员配置",
|
||||||
@ -168,6 +177,55 @@ public class AppConfigCheck implements ApplicationRunner {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
put(
|
||||||
|
"MinIO",
|
||||||
|
new AppConfig[] {
|
||||||
|
new AppConfig() {
|
||||||
|
{
|
||||||
|
setName("AccessKey");
|
||||||
|
setSort(10);
|
||||||
|
setFieldType(BackendConstant.APP_CONFIG_FIELD_TYPE_TEXT);
|
||||||
|
setKeyName(CConfig.MINIO_ACCESS_KEY);
|
||||||
|
setKeyValue("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AppConfig() {
|
||||||
|
{
|
||||||
|
setName("SecretKey");
|
||||||
|
setSort(20);
|
||||||
|
setFieldType(BackendConstant.APP_CONFIG_FIELD_TYPE_TEXT);
|
||||||
|
setKeyName(CConfig.MINIO_SECRET_KEY);
|
||||||
|
setKeyValue("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AppConfig() {
|
||||||
|
{
|
||||||
|
setName("Bucket");
|
||||||
|
setSort(30);
|
||||||
|
setFieldType(BackendConstant.APP_CONFIG_FIELD_TYPE_TEXT);
|
||||||
|
setKeyName(CConfig.MINIO_BUCKET);
|
||||||
|
setKeyValue("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AppConfig() {
|
||||||
|
{
|
||||||
|
setName("Endpoint");
|
||||||
|
setSort(40);
|
||||||
|
setFieldType(BackendConstant.APP_CONFIG_FIELD_TYPE_TEXT);
|
||||||
|
setKeyName(CConfig.MINIO_ENDPOINT);
|
||||||
|
setKeyValue("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AppConfig() {
|
||||||
|
{
|
||||||
|
setName("Domain");
|
||||||
|
setSort(50);
|
||||||
|
setFieldType(BackendConstant.APP_CONFIG_FIELD_TYPE_TEXT);
|
||||||
|
setKeyName(CConfig.MINIO_DOMAIN);
|
||||||
|
setKeyValue("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package xyz.playedu.api.config;
|
|
||||||
|
|
||||||
import static com.google.code.kaptcha.Constants.*;
|
|
||||||
|
|
||||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
|
||||||
import com.google.code.kaptcha.util.Config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class KaptchaConfig {
|
|
||||||
|
|
||||||
@Bean(name = "captchaProducer")
|
|
||||||
public DefaultKaptcha getKaptchaBean() {
|
|
||||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
|
||||||
Properties properties = new Properties();
|
|
||||||
// 是否边框
|
|
||||||
properties.setProperty(KAPTCHA_BORDER, "no");
|
|
||||||
// 字符颜色
|
|
||||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "red");
|
|
||||||
// 干扰线颜色
|
|
||||||
properties.setProperty(KAPTCHA_NOISE_COLOR, "red");
|
|
||||||
// 字符间距
|
|
||||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "5");
|
|
||||||
// 图片宽度
|
|
||||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "120");
|
|
||||||
// 图片高度
|
|
||||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "50");
|
|
||||||
// 字符大小
|
|
||||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "40");
|
|
||||||
// 字符长度
|
|
||||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
|
|
||||||
// 字体样式
|
|
||||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
|
||||||
|
|
||||||
defaultKaptcha.setConfig(new Config(properties));
|
|
||||||
|
|
||||||
return defaultKaptcha;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package xyz.playedu.api.config;
|
|
||||||
|
|
||||||
import io.minio.MinioAsyncClient;
|
|
||||||
import io.minio.MinioClient;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import xyz.playedu.api.vendor.PlayEduMinioClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/2/28 16:38
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Configuration
|
|
||||||
public class MinioConfig {
|
|
||||||
|
|
||||||
@Value("${minio.domain}")
|
|
||||||
private String domain;
|
|
||||||
|
|
||||||
@Value("${minio.bucket}")
|
|
||||||
private String bucket;
|
|
||||||
|
|
||||||
@Value("${minio.access-key}")
|
|
||||||
private String accessKey;
|
|
||||||
|
|
||||||
@Value("${minio.secret-key}")
|
|
||||||
private String secretKey;
|
|
||||||
|
|
||||||
@Value("${minio.end-point}")
|
|
||||||
private String endPoint;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MinioClient getMinioClient() {
|
|
||||||
return MinioClient.builder()
|
|
||||||
.endpoint(this.endPoint)
|
|
||||||
.credentials(this.accessKey, this.secretKey)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PlayEduMinioClient getPlayEduMinioClient() {
|
|
||||||
MinioAsyncClient client =
|
|
||||||
PlayEduMinioClient.builder()
|
|
||||||
.endpoint(this.endPoint)
|
|
||||||
.credentials(this.accessKey, this.secretKey)
|
|
||||||
.build();
|
|
||||||
return new PlayEduMinioClient(client);
|
|
||||||
}
|
|
||||||
}
|
|
@ -29,4 +29,10 @@ public class CConfig {
|
|||||||
public static final String SYSTEM_H5_URL = "system.h5_url";
|
public static final String SYSTEM_H5_URL = "system.h5_url";
|
||||||
|
|
||||||
public static final String MEMBER_DEFAULT_AVATAR = "member.default_avatar";
|
public static final String MEMBER_DEFAULT_AVATAR = "member.default_avatar";
|
||||||
|
|
||||||
|
public static final String MINIO_ACCESS_KEY = "minio.access_key";
|
||||||
|
public static final String MINIO_SECRET_KEY = "minio.secret_key";
|
||||||
|
public static final String MINIO_BUCKET = "minio.bucket";
|
||||||
|
public static final String MINIO_ENDPOINT = "minio.endpoint";
|
||||||
|
public static final String MINIO_DOMAIN = "minio.domain";
|
||||||
}
|
}
|
||||||
|
@ -37,11 +37,11 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class ExceptionController {
|
public class ExceptionController {
|
||||||
|
|
||||||
// @ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
// public JsonResponse exceptionHandler(Exception e) {
|
public JsonResponse exceptionHandler(Exception e) {
|
||||||
// log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
// return JsonResponse.error("系统错误", 500);
|
return JsonResponse.error("系统错误", 500);
|
||||||
// }
|
}
|
||||||
|
|
||||||
@ExceptionHandler(ServiceException.class)
|
@ExceptionHandler(ServiceException.class)
|
||||||
public JsonResponse serviceExceptionHandler(ServiceException e) {
|
public JsonResponse serviceExceptionHandler(ServiceException e) {
|
||||||
|
@ -36,11 +36,6 @@ import xyz.playedu.api.util.HelperUtil;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/2/28 16:26
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequestMapping("/backend/v1/upload")
|
@RequestMapping("/backend/v1/upload")
|
||||||
|
@ -61,6 +61,7 @@ public class SystemController {
|
|||||||
data.put("player-bullet-secret-text", configs.get("player.bullet_secret_text"));
|
data.put("player-bullet-secret-text", configs.get("player.bullet_secret_text"));
|
||||||
data.put("player-bullet-secret-color", configs.get("player.bullet_secret_color"));
|
data.put("player-bullet-secret-color", configs.get("player.bullet_secret_color"));
|
||||||
data.put("player-bullet-secret-opacity", configs.get("player.bullet_secret_opacity"));
|
data.put("player-bullet-secret-opacity", configs.get("player.bullet_secret_opacity"));
|
||||||
|
data.put("player-disabled-drag", configs.get("player.disabled_drag"));
|
||||||
|
|
||||||
return JsonResponse.data(data);
|
return JsonResponse.data(data);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import org.springframework.context.event.EventListener;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import xyz.playedu.api.event.UserDestroyEvent;
|
import xyz.playedu.api.event.UserDestroyEvent;
|
||||||
import xyz.playedu.api.service.UserService;
|
import xyz.playedu.api.service.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author 杭州白书科技有限公司
|
* @Author 杭州白书科技有限公司
|
||||||
@ -35,8 +35,23 @@ public class UserDestroyListener {
|
|||||||
|
|
||||||
@Autowired private UserService userService;
|
@Autowired private UserService userService;
|
||||||
|
|
||||||
|
@Autowired private UserCourseHourRecordService userCourseHourRecordService;
|
||||||
|
|
||||||
|
@Autowired private UserCourseRecordService userCourseRecordService;
|
||||||
|
|
||||||
|
@Autowired private UserLearnDurationRecordService userLearnDurationRecordService;
|
||||||
|
|
||||||
|
@Autowired private UserLearnDurationStatsService userLearnDurationStatsService;
|
||||||
|
|
||||||
|
@Autowired private UserLoginRecordService userLoginRecordService;
|
||||||
|
|
||||||
@EventListener
|
@EventListener
|
||||||
public void updateLoginInfo(UserDestroyEvent event) {
|
public void remoteRelation(UserDestroyEvent event) {
|
||||||
userService.removeRelateDepartmentsByUserId(event.getUserId());
|
userService.removeRelateDepartmentsByUserId(event.getUserId());
|
||||||
|
userCourseHourRecordService.remove(event.getUserId());
|
||||||
|
userCourseRecordService.destroy(event.getUserId());
|
||||||
|
userLearnDurationRecordService.remove(event.getUserId());
|
||||||
|
userLearnDurationStatsService.remove(event.getUserId());
|
||||||
|
userLoginRecordService.remove(event.getUserId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,12 @@ package xyz.playedu.api.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
import xyz.playedu.api.domain.AppConfig;
|
import xyz.playedu.api.domain.AppConfig;
|
||||||
|
import xyz.playedu.api.types.config.MinioConfig;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author tengteng
|
|
||||||
* @description 针对表【app_config】的数据库操作Service
|
|
||||||
* @createDate 2023-03-09 11:13:33
|
|
||||||
*/
|
|
||||||
public interface AppConfigService extends IService<AppConfig> {
|
public interface AppConfigService extends IService<AppConfig> {
|
||||||
|
|
||||||
Map<String, Long> allKeys();
|
Map<String, Long> allKeys();
|
||||||
@ -37,4 +33,6 @@ public interface AppConfigService extends IService<AppConfig> {
|
|||||||
void saveFromMap(HashMap<String, String> data);
|
void saveFromMap(HashMap<String, String> data);
|
||||||
|
|
||||||
Map<String, String> keyValues();
|
Map<String, String> keyValues();
|
||||||
|
|
||||||
|
MinioConfig getMinioConfig();
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,8 @@ public interface UserCourseHourRecordService extends IService<UserCourseHourReco
|
|||||||
|
|
||||||
void remove(Integer userId, Integer courseId);
|
void remove(Integer userId, Integer courseId);
|
||||||
|
|
||||||
|
void remove(Integer userId);
|
||||||
|
|
||||||
void remove(Integer userId, Integer courseId, Integer hourId);
|
void remove(Integer userId, Integer courseId, Integer hourId);
|
||||||
|
|
||||||
List<UserCourseHourRecordCourseCountMapper> getUserCourseHourCount(
|
List<UserCourseHourRecordCourseCountMapper> getUserCourseHourCount(
|
||||||
|
@ -45,6 +45,8 @@ public interface UserCourseRecordService extends IService<UserCourseRecord> {
|
|||||||
|
|
||||||
void destroy(Integer userId, Integer courseId);
|
void destroy(Integer userId, Integer courseId);
|
||||||
|
|
||||||
|
void destroy(Integer userId);
|
||||||
|
|
||||||
void removeByCourseId(Integer courseId);
|
void removeByCourseId(Integer courseId);
|
||||||
|
|
||||||
List<UserCourseRecord> chunks(List<Integer> ids, List<String> fields);
|
List<UserCourseRecord> chunks(List<Integer> ids, List<String> fields);
|
||||||
|
@ -26,4 +26,6 @@ import xyz.playedu.api.domain.UserLearnDurationRecord;
|
|||||||
*/
|
*/
|
||||||
public interface UserLearnDurationRecordService extends IService<UserLearnDurationRecord> {
|
public interface UserLearnDurationRecordService extends IService<UserLearnDurationRecord> {
|
||||||
void store(Integer userId, Integer courseId, Integer hourId, Long startTime, Long endTime);
|
void store(Integer userId, Integer courseId, Integer hourId, Long startTime, Long endTime);
|
||||||
|
|
||||||
|
void remove(Integer userId);
|
||||||
}
|
}
|
||||||
|
@ -40,4 +40,6 @@ public interface UserLearnDurationStatsService extends IService<UserLearnDuratio
|
|||||||
Long userDuration(Integer userId);
|
Long userDuration(Integer userId);
|
||||||
|
|
||||||
List<UserLearnDurationStats> dateBetween(Integer userId, String startAt, String endAt);
|
List<UserLearnDurationStats> dateBetween(Integer userId, String startAt, String endAt);
|
||||||
|
|
||||||
|
void remove(Integer userId);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ public interface UserLoginRecordService extends IService<UserLoginRecord> {
|
|||||||
String browserVersion,
|
String browserVersion,
|
||||||
String os);
|
String os);
|
||||||
|
|
||||||
void saveIpArea(Integer id, String area);
|
|
||||||
|
|
||||||
void logout(Integer userid, String jti);
|
void logout(Integer userid, String jti);
|
||||||
|
|
||||||
|
void remove(Integer userId);
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,11 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import xyz.playedu.api.constant.CConfig;
|
||||||
import xyz.playedu.api.domain.AppConfig;
|
import xyz.playedu.api.domain.AppConfig;
|
||||||
import xyz.playedu.api.mapper.AppConfigMapper;
|
import xyz.playedu.api.mapper.AppConfigMapper;
|
||||||
import xyz.playedu.api.service.AppConfigService;
|
import xyz.playedu.api.service.AppConfigService;
|
||||||
|
import xyz.playedu.api.types.config.MinioConfig;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -89,4 +91,16 @@ public class AppConfigServiceImpl extends ServiceImpl<AppConfigMapper, AppConfig
|
|||||||
return list(query().getWrapper().eq("is_hidden", 0)).stream()
|
return list(query().getWrapper().eq("is_hidden", 0)).stream()
|
||||||
.collect(Collectors.toMap(AppConfig::getKeyName, AppConfig::getKeyValue));
|
.collect(Collectors.toMap(AppConfig::getKeyName, AppConfig::getKeyValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MinioConfig getMinioConfig() {
|
||||||
|
MinioConfig minioConfig = new MinioConfig();
|
||||||
|
Map<String, String> config = keyValues();
|
||||||
|
minioConfig.setAccessKey(config.get(CConfig.MINIO_ACCESS_KEY));
|
||||||
|
minioConfig.setSecretKey(config.get(CConfig.MINIO_SECRET_KEY));
|
||||||
|
minioConfig.setBucket(config.get(CConfig.MINIO_BUCKET));
|
||||||
|
minioConfig.setEndpoint(config.get(CConfig.MINIO_ENDPOINT));
|
||||||
|
minioConfig.setDomain(config.get(CConfig.MINIO_DOMAIN));
|
||||||
|
return minioConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,27 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package xyz.playedu.api.service.impl;
|
package xyz.playedu.api.service.impl;
|
||||||
|
|
||||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
import cn.hutool.captcha.CaptchaUtil;
|
||||||
|
import cn.hutool.captcha.LineCaptcha;
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.FastByteArrayOutputStream;
|
|
||||||
|
|
||||||
import xyz.playedu.api.service.ImageCaptchaService;
|
import xyz.playedu.api.service.ImageCaptchaService;
|
||||||
import xyz.playedu.api.types.ImageCaptchaResult;
|
import xyz.playedu.api.types.ImageCaptchaResult;
|
||||||
import xyz.playedu.api.util.Base64Util;
|
|
||||||
import xyz.playedu.api.util.HelperUtil;
|
import xyz.playedu.api.util.HelperUtil;
|
||||||
import xyz.playedu.api.util.RedisUtil;
|
import xyz.playedu.api.util.RedisUtil;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class ImageCaptchaServiceImpl implements ImageCaptchaService {
|
public class ImageCaptchaServiceImpl implements ImageCaptchaService {
|
||||||
@ -46,29 +38,21 @@ public class ImageCaptchaServiceImpl implements ImageCaptchaService {
|
|||||||
@Value("${playedu.captcha.expire}")
|
@Value("${playedu.captcha.expire}")
|
||||||
private Long ConfigExpire;
|
private Long ConfigExpire;
|
||||||
|
|
||||||
@Resource private DefaultKaptcha defaultKaptcha;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageCaptchaResult generate() throws IOException {
|
public ImageCaptchaResult generate() {
|
||||||
ImageCaptchaResult imageCaptcha = new ImageCaptchaResult();
|
ImageCaptchaResult imageCaptcha = new ImageCaptchaResult();
|
||||||
BufferedImage image;
|
|
||||||
|
// 生成验证码
|
||||||
|
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(240, 100, 4, 1);
|
||||||
|
|
||||||
// 图形验证码的key[api是无状态的需要key来锁定验证码的值]
|
// 图形验证码的key[api是无状态的需要key来锁定验证码的值]
|
||||||
String randomKey = HelperUtil.randomString(16);
|
String randomKey = HelperUtil.randomString(16);
|
||||||
imageCaptcha.setKey(randomKey);
|
imageCaptcha.setKey(randomKey);
|
||||||
|
imageCaptcha.setCode(lineCaptcha.getCode());
|
||||||
// 生成验证码
|
imageCaptcha.setImage("data:image/png;base64," + lineCaptcha.getImageBase64());
|
||||||
imageCaptcha.setCode(defaultKaptcha.createText());
|
|
||||||
image = defaultKaptcha.createImage(imageCaptcha.getCode());
|
|
||||||
|
|
||||||
// 写入到redis中
|
// 写入到redis中
|
||||||
RedisUtil.set(getCacheKey(randomKey), imageCaptcha.getCode(), ConfigExpire);
|
RedisUtil.set(getCacheKey(imageCaptcha.getKey()), imageCaptcha.getCode(), ConfigExpire);
|
||||||
|
|
||||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
|
||||||
ImageIO.write(image, "png", os);
|
|
||||||
|
|
||||||
String base64 = "data:image/png;base64," + Base64Util.encode(os.toByteArray());
|
|
||||||
imageCaptcha.setImage(base64);
|
|
||||||
|
|
||||||
return imageCaptcha;
|
return imageCaptcha;
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package xyz.playedu.api.service.impl;
|
package xyz.playedu.api.service.impl;
|
||||||
|
|
||||||
import io.minio.GetPresignedObjectUrlArgs;
|
import io.minio.*;
|
||||||
import io.minio.MinioClient;
|
|
||||||
import io.minio.PutObjectArgs;
|
|
||||||
import io.minio.RemoveObjectArgs;
|
|
||||||
import io.minio.http.Method;
|
import io.minio.http.Method;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@ -27,8 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import xyz.playedu.api.config.MinioConfig;
|
import xyz.playedu.api.exception.ServiceException;
|
||||||
|
import xyz.playedu.api.service.AppConfigService;
|
||||||
import xyz.playedu.api.service.MinioService;
|
import xyz.playedu.api.service.MinioService;
|
||||||
|
import xyz.playedu.api.types.config.MinioConfig;
|
||||||
import xyz.playedu.api.vendor.PlayEduMinioClient;
|
import xyz.playedu.api.vendor.PlayEduMinioClient;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -36,70 +35,111 @@ import java.io.InputStream;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/3/7 13:29
|
|
||||||
*/
|
|
||||||
@Service
|
@Service
|
||||||
public class MinioServiceImpl implements MinioService {
|
public class MinioServiceImpl implements MinioService {
|
||||||
|
|
||||||
@Autowired private MinioConfig c;
|
private MinioConfig minioConfig = null;
|
||||||
|
|
||||||
@Autowired private MinioClient client;
|
@Autowired private AppConfigService appConfigService;
|
||||||
|
|
||||||
@Autowired private PlayEduMinioClient playEduMinioClient;
|
@SneakyThrows
|
||||||
|
private MinioConfig getMinioConfig() {
|
||||||
|
if (minioConfig == null) {
|
||||||
|
minioConfig = appConfigService.getMinioConfig();
|
||||||
|
if (minioConfig.getAccessKey().isBlank()
|
||||||
|
|| minioConfig.getSecretKey().isBlank()
|
||||||
|
|| minioConfig.getBucket().isBlank()
|
||||||
|
|| minioConfig.getDomain().isBlank()
|
||||||
|
|| minioConfig.getEndpoint().isBlank()) {
|
||||||
|
throw new ServiceException("MinIO服务未配置");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minioConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String bucket() {
|
||||||
|
return getMinioConfig().getBucket();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinioClient getMinioClient() {
|
||||||
|
MinioConfig c = getMinioConfig();
|
||||||
|
|
||||||
|
return MinioClient.builder()
|
||||||
|
.endpoint(c.getEndpoint())
|
||||||
|
.credentials(c.getAccessKey(), c.getSecretKey())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayEduMinioClient getPlayEduMinioClient() {
|
||||||
|
MinioConfig c = getMinioConfig();
|
||||||
|
|
||||||
|
MinioAsyncClient client =
|
||||||
|
PlayEduMinioClient.builder()
|
||||||
|
.endpoint(c.getEndpoint())
|
||||||
|
.credentials(c.getAccessKey(), c.getSecretKey())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return new PlayEduMinioClient(client);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String url(String path) {
|
public String url(String path) {
|
||||||
return c.getDomain() + c.getBucket() + "/" + path;
|
MinioConfig c = getMinioConfig();
|
||||||
|
|
||||||
|
return c.getDomain()
|
||||||
|
+ (c.getDomain().endsWith("/") ? "" : "/")
|
||||||
|
+ c.getBucket()
|
||||||
|
+ "/"
|
||||||
|
+ path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String saveFile(MultipartFile file, String savePath, String contentType) {
|
public String saveFile(MultipartFile file, String savePath, String contentType) {
|
||||||
PutObjectArgs objectArgs =
|
PutObjectArgs objectArgs =
|
||||||
PutObjectArgs.builder().bucket(c.getBucket()).object(savePath).stream(
|
PutObjectArgs.builder().bucket(bucket()).object(savePath).stream(
|
||||||
file.getInputStream(), file.getSize(), -1)
|
file.getInputStream(), file.getSize(), -1)
|
||||||
.contentType(contentType)
|
.contentType(contentType)
|
||||||
.build();
|
.build();
|
||||||
client.putObject(objectArgs);
|
getMinioClient().putObject(objectArgs);
|
||||||
|
|
||||||
return url(savePath);
|
return url(savePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String uploadId(String path) {
|
public String uploadId(String path) {
|
||||||
return playEduMinioClient.uploadId(c.getBucket(), path);
|
return getPlayEduMinioClient().uploadId(bucket(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String chunkPreSignUrl(String filename, String partNumber, String uploadId) {
|
public String chunkPreSignUrl(String filename, String partNumber, String uploadId) {
|
||||||
Map<String, String> extraQueryParams = new HashMap<>();
|
Map<String, String> extraQueryParams = new HashMap<>();
|
||||||
extraQueryParams.put("partNumber", partNumber + "");
|
extraQueryParams.put("partNumber", partNumber);
|
||||||
extraQueryParams.put("uploadId", uploadId);
|
extraQueryParams.put("uploadId", uploadId);
|
||||||
|
|
||||||
return client.getPresignedObjectUrl(
|
return getMinioClient()
|
||||||
GetPresignedObjectUrlArgs.builder()
|
.getPresignedObjectUrl(
|
||||||
.bucket(c.getBucket())
|
GetPresignedObjectUrlArgs.builder()
|
||||||
.object(filename)
|
.bucket(bucket())
|
||||||
.method(Method.PUT)
|
.object(filename)
|
||||||
.expiry(60 * 60 * 24)
|
.method(Method.PUT)
|
||||||
.extraQueryParams(extraQueryParams)
|
.expiry(60 * 60 * 24)
|
||||||
.build());
|
.extraQueryParams(extraQueryParams)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String merge(String filename, String uploadId) {
|
public String merge(String filename, String uploadId) {
|
||||||
playEduMinioClient.merge(c.getBucket(), filename, uploadId);
|
getPlayEduMinioClient().merge(bucket(), filename, uploadId);
|
||||||
return url(filename);
|
return url(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void removeByPath(String path) {
|
public void removeByPath(String path) {
|
||||||
client.removeObject(RemoveObjectArgs.builder().bucket(c.getBucket()).object(path).build());
|
getMinioClient()
|
||||||
|
.removeObject(RemoveObjectArgs.builder().bucket(bucket()).object(path).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,12 +148,12 @@ public class MinioServiceImpl implements MinioService {
|
|||||||
InputStream inputStream = new ByteArrayInputStream(file);
|
InputStream inputStream = new ByteArrayInputStream(file);
|
||||||
|
|
||||||
PutObjectArgs objectArgs =
|
PutObjectArgs objectArgs =
|
||||||
PutObjectArgs.builder().bucket(c.getBucket()).object(savePath).stream(
|
PutObjectArgs.builder().bucket(bucket()).object(savePath).stream(
|
||||||
inputStream, file.length, -1)
|
inputStream, file.length, -1)
|
||||||
.contentType(contentType)
|
.contentType(contentType)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.putObject(objectArgs);
|
getMinioClient().putObject(objectArgs);
|
||||||
|
|
||||||
return url(savePath);
|
return url(savePath);
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,11 @@ public class UserCourseHourRecordServiceImpl
|
|||||||
remove(query().getWrapper().eq("user_id", userId).eq("course_id", courseId));
|
remove(query().getWrapper().eq("user_id", userId).eq("course_id", courseId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Integer userId) {
|
||||||
|
remove(query().getWrapper().eq("user_id", userId));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaginationResult<UserCourseHourRecord> paginate(
|
public PaginationResult<UserCourseHourRecord> paginate(
|
||||||
int page, int size, UserCourseHourRecordPaginateFilter filter) {
|
int page, int size, UserCourseHourRecordPaginateFilter filter) {
|
||||||
|
@ -138,6 +138,11 @@ public class UserCourseRecordServiceImpl
|
|||||||
remove(query().getWrapper().in("user_id", userId).eq("course_id", courseId));
|
remove(query().getWrapper().in("user_id", userId).eq("course_id", courseId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy(Integer userId) {
|
||||||
|
remove(query().getWrapper().in("user_id", userId));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decrease(Integer userId, Integer courseId, int count) {
|
public void decrease(Integer userId, Integer courseId, int count) {
|
||||||
UserCourseRecord record = find(userId, courseId);
|
UserCourseRecord record = find(userId, courseId);
|
||||||
|
@ -57,4 +57,9 @@ public class UserLearnDurationRecordServiceImpl
|
|||||||
|
|
||||||
save(record);
|
save(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Integer userId) {
|
||||||
|
remove(query().getWrapper().eq("user_id", userId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,4 +114,9 @@ public class UserLearnDurationStatsServiceImpl
|
|||||||
return list(
|
return list(
|
||||||
query().getWrapper().eq("user_id", userId).between("created_date", startAt, endAt));
|
query().getWrapper().eq("user_id", userId).between("created_date", startAt, endAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Integer userId) {
|
||||||
|
remove(query().getWrapper().eq("user_id", userId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,14 +54,6 @@ public class UserLoginRecordServiceImpl extends ServiceImpl<UserLoginRecordMappe
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveIpArea(Integer id, String area) {
|
|
||||||
UserLoginRecord record = new UserLoginRecord();
|
|
||||||
record.setId(id);
|
|
||||||
record.setIpArea(area);
|
|
||||||
updateById(record);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void logout(Integer userid, String jti) {
|
public void logout(Integer userid, String jti) {
|
||||||
UserLoginRecord record =
|
UserLoginRecord record =
|
||||||
@ -79,4 +71,9 @@ public class UserLoginRecordServiceImpl extends ServiceImpl<UserLoginRecordMappe
|
|||||||
|
|
||||||
updateById(newRecord);
|
updateById(newRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Integer userId) {
|
||||||
|
remove(query().getWrapper().eq("user_id", userId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
27
src/main/java/xyz/playedu/api/types/config/MinioConfig.java
Normal file
27
src/main/java/xyz/playedu/api/types/config/MinioConfig.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.types.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MinioConfig {
|
||||||
|
private String accessKey;
|
||||||
|
private String secretKey;
|
||||||
|
private String bucket;
|
||||||
|
private String endpoint;
|
||||||
|
private String domain;
|
||||||
|
}
|
@ -47,14 +47,6 @@ spring:
|
|||||||
await-termination: true
|
await-termination: true
|
||||||
thread-name-prefix: "playedu-default-thread"
|
thread-name-prefix: "playedu-default-thread"
|
||||||
|
|
||||||
# Minio
|
|
||||||
minio:
|
|
||||||
access-key: ""
|
|
||||||
secret-key: ""
|
|
||||||
end-point: ""
|
|
||||||
bucket: ""
|
|
||||||
domain: ""
|
|
||||||
|
|
||||||
mybatis:
|
mybatis:
|
||||||
mapper-locations: classpath:mapper/*.xml
|
mapper-locations: classpath:mapper/*.xml
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user