新增答辩用后台管理系统
This commit is contained in:
+4
@@ -40,6 +40,10 @@ public interface GroupCourseDao extends R2dbcRepository<GroupCourseEntity, Long>
|
||||
@Query("UPDATE group_course SET deleted_at = :deletedAt WHERE id = :id")
|
||||
Mono<Integer> softDelete(Long id, LocalDateTime deletedAt);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE group_course SET deleted_at = NULL, status = '1', updated_at = :updatedAt WHERE id = :id AND deleted_at IS NOT NULL")
|
||||
Mono<Integer> restoreCourse(Long id, LocalDateTime updatedAt);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE group_course SET status = '2', updated_at = :updatedAt WHERE status = '0' AND end_time <= NOW() AND deleted_at IS NULL")
|
||||
Mono<Integer> completeExpiredCourses(LocalDateTime updatedAt);
|
||||
|
||||
+4
@@ -29,4 +29,8 @@ public interface GroupCourseTypeDao extends R2dbcRepository<GroupCourseTypeEntit
|
||||
@Modifying
|
||||
@Query("UPDATE group_course_type SET deleted_at = :deletedAt WHERE id = :id")
|
||||
Mono<Integer> softDelete(Long id, LocalDateTime deletedAt);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE group_course_type SET type_name = :typeName, base_difficulty = :baseDifficulty, description = :description, category = :category, updated_at = :updatedAt WHERE id = :id AND deleted_at IS NULL")
|
||||
Mono<Integer> updateFields(Long id, String typeName, Integer baseDifficulty, String description, String category, LocalDateTime updatedAt);
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
package cn.novalon.gym.manage.groupcourse.handler;
|
||||
|
||||
import cn.novalon.gym.manage.groupcourse.util.OSSUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.multipart.FilePart;
|
||||
import org.springframework.http.codec.multipart.Part;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 通用文件上传处理器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@Tag(name = "文件上传", description = "通用文件上传到阿里云OSS")
|
||||
public class CommonUploadHandler {
|
||||
|
||||
@Operation(summary = "上传图片文件", description = "上传图片到阿里云OSS,返回ossKey和预签名URL")
|
||||
public Mono<ServerResponse> uploadImage(ServerRequest request) {
|
||||
return request.multipartData()
|
||||
.flatMap(multiValueMap -> {
|
||||
List<Part> fileParts = multiValueMap.get("file");
|
||||
if (fileParts == null || fileParts.isEmpty()) {
|
||||
return ServerResponse.badRequest()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of("code", 400, "message", "未选择文件"));
|
||||
}
|
||||
|
||||
Part part = fileParts.get(0);
|
||||
if (!(part instanceof FilePart filePart)) {
|
||||
return ServerResponse.badRequest()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of("code", 400, "message", "文件格式不正确"));
|
||||
}
|
||||
|
||||
String originalFilename = filePart.filename();
|
||||
String ext = "";
|
||||
int dotIndex = originalFilename.lastIndexOf('.');
|
||||
if (dotIndex > 0) {
|
||||
ext = originalFilename.substring(dotIndex);
|
||||
}
|
||||
String newFileName = UUID.randomUUID().toString().replace("-", "") + ext;
|
||||
|
||||
Path tempFile = null;
|
||||
try {
|
||||
tempFile = Files.createTempFile("upload-", newFileName);
|
||||
} catch (Exception e) {
|
||||
return Mono.error(new RuntimeException("创建临时文件失败", e));
|
||||
}
|
||||
Path finalTempFile = tempFile;
|
||||
|
||||
return filePart.transferTo(finalTempFile)
|
||||
.then(Mono.defer(() -> {
|
||||
try {
|
||||
String ossKey;
|
||||
try (InputStream inputStream = Files.newInputStream(finalTempFile)) {
|
||||
ossKey = OSSUtil.uploadCoverToOSS(inputStream, newFileName);
|
||||
}
|
||||
String presignedUrl = OSSUtil.generatePresignedUrl(ossKey);
|
||||
return ServerResponse.ok()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of(
|
||||
"code", 200,
|
||||
"message", "上传成功",
|
||||
"data", Map.of(
|
||||
"ossKey", ossKey,
|
||||
"presignedUrl", presignedUrl,
|
||||
"fileName", originalFilename
|
||||
)
|
||||
));
|
||||
} catch (Exception e) {
|
||||
return ServerResponse.status(500)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of("code", 500, "message", "上传失败: " + e.getMessage()));
|
||||
} finally {
|
||||
try {
|
||||
Files.deleteIfExists(finalTempFile);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "获取OSS预签名URL", description = "根据ossKey生成临时访问URL,有效期5分钟")
|
||||
public Mono<ServerResponse> presignUrl(ServerRequest request) {
|
||||
String ossKey = request.queryParam("key").orElse(null);
|
||||
if (ossKey == null || ossKey.isBlank()) {
|
||||
return ServerResponse.badRequest()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of("code", 400, "message", "参数 key 不能为空"));
|
||||
}
|
||||
|
||||
try {
|
||||
String presignedUrl = OSSUtil.generatePresignedUrl(ossKey);
|
||||
return ServerResponse.ok()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of(
|
||||
"code", 200,
|
||||
"data", Map.of("presignedUrl", presignedUrl)
|
||||
));
|
||||
} catch (Exception e) {
|
||||
return ServerResponse.status(500)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Map.of("code", 500, "message", "生成预签名URL失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-5
@@ -146,18 +146,25 @@ public class CourseLabelHandler {
|
||||
|
||||
return request.bodyToMono(Map.class)
|
||||
.flatMap(body -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Integer> labelIdsInt = (List<Integer>) body.get("labelIds");
|
||||
Object labelIdsObj = body.get("labelIds");
|
||||
|
||||
if (labelIdsInt == null || labelIdsInt.isEmpty()) {
|
||||
if (!(labelIdsObj instanceof List)) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "labelIds不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
List<Long> labelIds = labelIdsInt.stream()
|
||||
.map(Integer::longValue)
|
||||
List<?> rawList = (List<?>) labelIdsObj;
|
||||
if (rawList.isEmpty()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "labelIds不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
List<Long> labelIds = rawList.stream()
|
||||
.map(id -> Long.valueOf(String.valueOf(id)))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
return courseLabelService.addLabelsToType(typeId, labelIds)
|
||||
|
||||
+115
-32
@@ -7,10 +7,13 @@ import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseDetail;
|
||||
import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto;
|
||||
import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService;
|
||||
import cn.novalon.gym.manage.sys.core.service.ISysUserService;
|
||||
import cn.novalon.gym.manage.sys.util.AuthUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Validator;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
@@ -26,15 +29,21 @@ public class GroupCourseHandler {
|
||||
private final Validator validator;
|
||||
private final RedisUtil redisUtil;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ISysUserService sysUserService;
|
||||
private final AuthUtil authUtil;
|
||||
|
||||
public GroupCourseHandler(IGroupCourseService groupCourseService,
|
||||
Validator validator,
|
||||
RedisUtil redisUtil,
|
||||
ObjectMapper objectMapper){
|
||||
ObjectMapper objectMapper,
|
||||
ISysUserService sysUserService,
|
||||
AuthUtil authUtil){
|
||||
this.groupCourseService = groupCourseService;
|
||||
this.validator = validator;
|
||||
this.redisUtil = redisUtil;
|
||||
this.objectMapper = objectMapper;
|
||||
this.sysUserService = sysUserService;
|
||||
this.authUtil = authUtil;
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所有团课", description = "获取系统中所有团课列表")
|
||||
@@ -114,25 +123,43 @@ public class GroupCourseHandler {
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "更新团课", description = "更新指定团课信息")
|
||||
@Operation(summary = "更新团课", description = "更新指定团课信息,需验证管理员密码")
|
||||
public Mono<ServerResponse> updateGroupCourse(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
|
||||
return request.bodyToMono(GroupCourse.class)
|
||||
.flatMap(groupCourse -> {
|
||||
return groupCourseService.update(id, groupCourse)
|
||||
.flatMap(course -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课更新成功");
|
||||
response.put("data", course);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return request.bodyToMono(GroupCourse.class)
|
||||
.flatMap(groupCourse -> {
|
||||
return groupCourseService.update(id, groupCourse)
|
||||
.flatMap(course -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课更新成功");
|
||||
response.put("data", course);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -197,22 +224,78 @@ public class GroupCourseHandler {
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "删除团课", description = "删除指定团课(软删除)")
|
||||
@Operation(summary = "删除团课", description = "删除指定团课(软删除),需验证管理员密码")
|
||||
public Mono<ServerResponse> deleteGroupCourse(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
|
||||
return groupCourseService.delete(id)
|
||||
.then(Mono.defer(() -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课删除成功");
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
}))
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return groupCourseService.delete(id)
|
||||
.then(Mono.defer(() -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课删除成功");
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
}))
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "恢复已删除团课", description = "将已删除的团课恢复为已取消状态,需验证管理员密码")
|
||||
public Mono<ServerResponse> restoreGroupCourse(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return groupCourseService.restore(id)
|
||||
.flatMap(course -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课恢复成功");
|
||||
response.put("data", course);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+103
-42
@@ -2,8 +2,11 @@ package cn.novalon.gym.manage.groupcourse.handler;
|
||||
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseRecommend;
|
||||
import cn.novalon.gym.manage.groupcourse.service.IGroupCourseRecommendService;
|
||||
import cn.novalon.gym.manage.sys.core.service.ISysUserService;
|
||||
import cn.novalon.gym.manage.sys.util.AuthUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
@@ -17,9 +20,15 @@ import java.util.Map;
|
||||
public class GroupCourseRecommendHandler {
|
||||
|
||||
private final IGroupCourseRecommendService recommendService;
|
||||
private final ISysUserService sysUserService;
|
||||
private final AuthUtil authUtil;
|
||||
|
||||
public GroupCourseRecommendHandler(IGroupCourseRecommendService recommendService) {
|
||||
public GroupCourseRecommendHandler(IGroupCourseRecommendService recommendService,
|
||||
ISysUserService sysUserService,
|
||||
AuthUtil authUtil) {
|
||||
this.recommendService = recommendService;
|
||||
this.sysUserService = sysUserService;
|
||||
this.authUtil = authUtil;
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所有团课推荐", description = "获取系统中所有团课推荐列表,支持按优先级排序")
|
||||
@@ -80,20 +89,73 @@ public class GroupCourseRecommendHandler {
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "更新团课推荐", description = "更新指定团课推荐信息")
|
||||
@Operation(summary = "更新团课推荐", description = "更新指定团课推荐信息,需验证管理员密码")
|
||||
public Mono<ServerResponse> updateRecommendation(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
return request.bodyToMono(GroupCourseRecommend.class)
|
||||
.flatMap(recommend -> {
|
||||
return recommendService.update(id, recommend)
|
||||
.flatMap(r -> {
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return request.bodyToMono(GroupCourseRecommend.class)
|
||||
.flatMap(recommend -> recommendService.update(id, recommend)
|
||||
.flatMap(r -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课推荐更新成功");
|
||||
response.put("data", r);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "删除团课推荐", description = "删除指定团课推荐(软删除),需验证管理员密码")
|
||||
public Mono<ServerResponse> deleteRecommendation(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return recommendService.delete(id)
|
||||
.then(Mono.defer(() -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课推荐更新成功");
|
||||
response.put("data", r);
|
||||
response.put("message", "团课推荐删除成功");
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
}))
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
@@ -103,25 +165,6 @@ public class GroupCourseRecommendHandler {
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "删除团课推荐", description = "删除指定团课推荐(软删除)")
|
||||
public Mono<ServerResponse> deleteRecommendation(ServerRequest request) {
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
|
||||
return recommendService.delete(id)
|
||||
.then(Mono.defer(() -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课推荐删除成功");
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
}))
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "启用团课推荐", description = "启用指定团课推荐")
|
||||
public Mono<ServerResponse> enableRecommendation(ServerRequest request) {
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
@@ -142,23 +185,41 @@ public class GroupCourseRecommendHandler {
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "禁用团课推荐", description = "禁用指定团课推荐")
|
||||
@Operation(summary = "禁用团课推荐", description = "禁用指定团课推荐,需验证管理员密码")
|
||||
public Mono<ServerResponse> disableRecommendation(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
return recommendService.disable(id)
|
||||
.flatMap(r -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课推荐禁用成功");
|
||||
response.put("data", r);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return recommendService.disable(id)
|
||||
.flatMap(r -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课推荐禁用成功");
|
||||
response.put("data", r);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
+76
-31
@@ -2,8 +2,11 @@ package cn.novalon.gym.manage.groupcourse.handler;
|
||||
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseType;
|
||||
import cn.novalon.gym.manage.groupcourse.service.IGroupCourseTypeService;
|
||||
import cn.novalon.gym.manage.sys.core.service.ISysUserService;
|
||||
import cn.novalon.gym.manage.sys.util.AuthUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
@@ -17,9 +20,15 @@ import java.util.Map;
|
||||
public class GroupCourseTypeHandler {
|
||||
|
||||
private final IGroupCourseTypeService groupCourseTypeService;
|
||||
private final ISysUserService sysUserService;
|
||||
private final AuthUtil authUtil;
|
||||
|
||||
public GroupCourseTypeHandler(IGroupCourseTypeService groupCourseTypeService) {
|
||||
public GroupCourseTypeHandler(IGroupCourseTypeService groupCourseTypeService,
|
||||
ISysUserService sysUserService,
|
||||
AuthUtil authUtil) {
|
||||
this.groupCourseTypeService = groupCourseTypeService;
|
||||
this.sysUserService = sysUserService;
|
||||
this.authUtil = authUtil;
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所有团课类型", description = "获取系统中所有团课类型列表")
|
||||
@@ -92,21 +101,76 @@ public class GroupCourseTypeHandler {
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "更新团课类型", description = "更新指定团课类型信息")
|
||||
@Operation(summary = "更新团课类型", description = "更新指定团课类型信息,需验证管理员密码")
|
||||
public Mono<ServerResponse> updateGroupCourseType(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
|
||||
return request.bodyToMono(GroupCourseType.class)
|
||||
.flatMap(groupCourseType -> {
|
||||
groupCourseType.setId(id);
|
||||
return groupCourseTypeService.update(id, groupCourseType)
|
||||
.flatMap(type -> {
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return request.bodyToMono(GroupCourseType.class)
|
||||
.flatMap(groupCourseType -> {
|
||||
groupCourseType.setId(id);
|
||||
return groupCourseTypeService.update(id, groupCourseType)
|
||||
.flatMap(type -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课类型更新成功");
|
||||
response.put("data", type);
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "删除团课类型", description = "删除指定团课类型(软删除),需验证管理员密码,且该类型不能被任何团课引用")
|
||||
public Mono<ServerResponse> deleteGroupCourseType(ServerRequest request) {
|
||||
Long adminId = authUtil.getMemberIdOrThrow(request);
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
String adminPassword = request.queryParam("adminPassword").orElse(null);
|
||||
|
||||
if (adminPassword == null || adminPassword.isBlank()) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码不能为空");
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return sysUserService.verifyPassword(adminId, adminPassword)
|
||||
.flatMap(valid -> {
|
||||
if (!valid) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "管理员密码错误");
|
||||
return ServerResponse.status(HttpStatus.FORBIDDEN).bodyValue(error);
|
||||
}
|
||||
return groupCourseTypeService.delete(id)
|
||||
.then(Mono.defer(() -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课类型更新成功");
|
||||
response.put("data", type);
|
||||
response.put("message", "团课类型删除成功");
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
})
|
||||
}))
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
@@ -115,23 +179,4 @@ public class GroupCourseTypeHandler {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "删除团课类型", description = "删除指定团课类型(软删除)")
|
||||
public Mono<ServerResponse> deleteGroupCourseType(ServerRequest request) {
|
||||
Long id = Long.valueOf(request.pathVariable("id"));
|
||||
|
||||
return groupCourseTypeService.delete(id)
|
||||
.then(Mono.defer(() -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "团课类型删除成功");
|
||||
return ServerResponse.ok().bodyValue(response);
|
||||
}))
|
||||
.onErrorResume(error -> {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("message", error.getMessage());
|
||||
return ServerResponse.badRequest().bodyValue(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -27,6 +27,8 @@ public interface IGroupCourseRepository {
|
||||
|
||||
Mono<Void> deleteById(Long id);
|
||||
|
||||
Mono<GroupCourse> restoreById(Long id);
|
||||
|
||||
Mono<GroupCourse> updateCurrentMembers(Long id, Integer delta);
|
||||
|
||||
Flux<GroupCourse> findByCourseType(Long courseType);
|
||||
|
||||
+11
@@ -169,6 +169,17 @@ public class GroupCourseRepository implements IGroupCourseRepository {
|
||||
.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GroupCourse> restoreById(Long id) {
|
||||
return groupCourseDao.restoreCourse(id, LocalDateTime.now())
|
||||
.flatMap(updated -> {
|
||||
if (updated > 0) {
|
||||
return findByIdAndDeletedAtIsNull(id);
|
||||
}
|
||||
return Mono.error(new RuntimeException("团课恢复失败,可能该课程未被删除"));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GroupCourse> updateCurrentMembers(Long id, Integer delta) {
|
||||
return groupCourseDao.updateCurrentMembers(id, delta, LocalDateTime.now())
|
||||
|
||||
+14
-15
@@ -105,21 +105,20 @@ public class GroupCourseTypeRepository implements IGroupCourseTypeRepository {
|
||||
return groupCourseTypeDao.findByIdIsAndDeletedAtIsNull(groupCourseType.getId())
|
||||
.switchIfEmpty(Mono.error(new RuntimeException("团课类型不存在")))
|
||||
.flatMap(existing -> {
|
||||
existing.markNotNew();
|
||||
if (groupCourseType.getTypeName() != null) {
|
||||
existing.setTypeName(groupCourseType.getTypeName());
|
||||
}
|
||||
if (groupCourseType.getBaseDifficulty() != null) {
|
||||
existing.setBaseDifficulty(groupCourseType.getBaseDifficulty());
|
||||
}
|
||||
if (groupCourseType.getDescription() != null) {
|
||||
existing.setDescription(groupCourseType.getDescription());
|
||||
}
|
||||
if (groupCourseType.getCategory() != null) {
|
||||
existing.setCategory(groupCourseType.getCategory());
|
||||
}
|
||||
existing.setUpdatedAt(LocalDateTime.now());
|
||||
return groupCourseTypeDao.save(existing);
|
||||
String typeName = groupCourseType.getTypeName() != null
|
||||
? groupCourseType.getTypeName() : existing.getTypeName();
|
||||
Integer baseDifficulty = groupCourseType.getBaseDifficulty() != null
|
||||
? groupCourseType.getBaseDifficulty() : existing.getBaseDifficulty();
|
||||
String description = groupCourseType.getDescription() != null
|
||||
? groupCourseType.getDescription() : existing.getDescription();
|
||||
String category = groupCourseType.getCategory() != null
|
||||
? groupCourseType.getCategory() : existing.getCategory();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
return groupCourseTypeDao.updateFields(
|
||||
groupCourseType.getId(), typeName, baseDifficulty,
|
||||
description, category, now)
|
||||
.then(groupCourseTypeDao.findByIdIsAndDeletedAtIsNull(groupCourseType.getId()));
|
||||
})
|
||||
.map(converter::toGroupCourseType);
|
||||
}
|
||||
|
||||
+2
@@ -26,6 +26,8 @@ public interface IGroupCourseService {
|
||||
Mono<GroupCourse> signIn(Long courseId, Long memberId);
|
||||
|
||||
Mono<Void> delete(Long id);
|
||||
|
||||
Mono<GroupCourse> restore(Long id);
|
||||
|
||||
Mono<PageResponse<GroupCourse>> searchGroupCourses(GroupCourseQueryDto query);
|
||||
}
|
||||
|
||||
+13
-5
@@ -536,14 +536,14 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
|
||||
@Override
|
||||
public Mono<Void> delete(Long id) {
|
||||
// 先查询课程状态,只有已取消的课程才能删除
|
||||
// 已取消或已结束的课程才能删除
|
||||
return groupCourseRepository.findByIdAndDeletedAtIsNull(id)
|
||||
.switchIfEmpty(Mono.error(new RuntimeException("团课不存在")))
|
||||
.flatMap(course -> {
|
||||
// 检查课程状态是否为已取消(状态码1)
|
||||
if (course.getStatus() == null || !course.getStatus().equals(CourseStatus.CANCELLED.getValue())) {
|
||||
return Mono.error(new RuntimeException("只有已取消的课程才能删除,当前状态: " +
|
||||
(course.getStatus() != null ? course.getStatus() : "未知")));
|
||||
Long status = course.getStatus();
|
||||
if (status == null || (!status.equals(CourseStatus.CANCELLED.getValue()) && !status.equals(CourseStatus.ENDED.getValue()))) {
|
||||
return Mono.error(new RuntimeException("只有已取消或已结束的课程才能删除,当前状态: " +
|
||||
(status != null ? status : "未知")));
|
||||
}
|
||||
|
||||
// 删除课程
|
||||
@@ -554,6 +554,14 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GroupCourse> restore(Long id) {
|
||||
return groupCourseRepository.restoreById(id)
|
||||
.doOnSuccess(course -> logger.info("团课恢复成功 - id={}", id))
|
||||
.flatMap(course -> clearCache().thenReturn(course))
|
||||
.doOnError(error -> logger.error("团课恢复失败 - id={}, error: {}", id, error.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<PageResponse<GroupCourse>> searchGroupCourses(GroupCourseQueryDto query) {
|
||||
logger.info("多条件查询团课 - courseName={}, courseType={}, startDate={}, endDate={}, timePeriod={}, priceSort={}, remainingMost={}",
|
||||
|
||||
+13
-5
@@ -1,6 +1,7 @@
|
||||
package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseType;
|
||||
import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository;
|
||||
import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseTypeRepository;
|
||||
import cn.novalon.gym.manage.groupcourse.service.IGroupCourseTypeService;
|
||||
import org.slf4j.Logger;
|
||||
@@ -9,18 +10,18 @@ import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
public class GroupCourseTypeService implements IGroupCourseTypeService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GroupCourseTypeService.class);
|
||||
|
||||
private final IGroupCourseTypeRepository groupCourseTypeRepository;
|
||||
private final IGroupCourseRepository groupCourseRepository;
|
||||
|
||||
public GroupCourseTypeService(IGroupCourseTypeRepository groupCourseTypeRepository) {
|
||||
public GroupCourseTypeService(IGroupCourseTypeRepository groupCourseTypeRepository,
|
||||
IGroupCourseRepository groupCourseRepository) {
|
||||
this.groupCourseTypeRepository = groupCourseTypeRepository;
|
||||
this.groupCourseRepository = groupCourseRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,7 +72,14 @@ public class GroupCourseTypeService implements IGroupCourseTypeService {
|
||||
|
||||
@Override
|
||||
public Mono<Void> delete(Long id) {
|
||||
return groupCourseTypeRepository.deleteById(id)
|
||||
return groupCourseRepository.findByCourseType(id)
|
||||
.hasElements()
|
||||
.flatMap(hasCourses -> {
|
||||
if (hasCourses) {
|
||||
return Mono.<Void>error(new RuntimeException("该类型下存在关联团课,无法删除"));
|
||||
}
|
||||
return groupCourseTypeRepository.deleteById(id);
|
||||
})
|
||||
.doOnSuccess(v -> logger.info("团课类型删除成功 - id={}", id))
|
||||
.doOnError(error -> logger.error("团课类型删除失败 - id={}, error: {}", id, error.getMessage()));
|
||||
}
|
||||
|
||||
+94
-29
@@ -1,14 +1,19 @@
|
||||
package cn.novalon.gym.manage.groupcourse.util;
|
||||
|
||||
import com.aliyun.oss.HttpMethod;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
|
||||
import com.aliyun.oss.model.PutObjectRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 阿里云OSS工具类
|
||||
@@ -19,8 +24,8 @@ public class OSSUtil {
|
||||
|
||||
// OSS配置信息
|
||||
private static final String ENDPOINT = "oss-cn-beijing.aliyuncs.com";
|
||||
private static final String ACCESS_KEY_ID = "LTAI5t9TFh9Vayeahz45kZjg";
|
||||
private static final String ACCESS_KEY_SECRET = "zD6NlCeH5UhjBs4vnQVqn8Ksi3CaZz";
|
||||
private static final String ACCESS_KEY_ID = "LTAI5t9wHCiH68Xjxg64Xx4Y";
|
||||
private static final String ACCESS_KEY_SECRET = "isAfz1IFGAnV13LOIrVg19aPhY8aRq";
|
||||
private static final String BUCKET_NAME = "ycc-filesaver";
|
||||
|
||||
// OSS访问地址前缀
|
||||
@@ -28,36 +33,31 @@ public class OSSUtil {
|
||||
|
||||
// 文件存储目录
|
||||
private static final String QRCODE_DIR = "qrcode/";
|
||||
private static final String COVER_DIR = "cover/";
|
||||
|
||||
// 预签名URL有效期(秒)
|
||||
private static final long PRESIGN_EXPIRE_SECONDS = 300;
|
||||
|
||||
/**
|
||||
* 上传文件到阿里云OSS
|
||||
* 上传文件到阿里云OSS(文件默认继承Bucket权限,不设置ACL)
|
||||
*
|
||||
* @param localFilePath 本地文件路径
|
||||
* @param fileName 文件名(不含路径)
|
||||
* @return OSS访问地址
|
||||
* @return OSS object key(不含域名前缀)
|
||||
*/
|
||||
public static String uploadToOSS(String localFilePath, String fileName) {
|
||||
OSS ossClient = null;
|
||||
try {
|
||||
// 创建OSS客户端
|
||||
ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||
|
||||
// 构建OSS文件路径:qrcode/2026/06/18/xxx.png
|
||||
String datePath = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||
String ossFilePath = QRCODE_DIR + datePath + "/" + fileName;
|
||||
|
||||
// 创建上传请求
|
||||
PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, ossFilePath, new File(localFilePath));
|
||||
|
||||
// 上传文件
|
||||
ossClient.putObject(putObjectRequest);
|
||||
|
||||
// 构建访问地址
|
||||
String accessUrl = OSS_URL_PREFIX + ossFilePath;
|
||||
|
||||
logger.info("文件上传到OSS成功: localPath={}, ossUrl={}", localFilePath, accessUrl);
|
||||
|
||||
return accessUrl;
|
||||
logger.info("文件上传到OSS成功: localPath={}, ossKey={}", localFilePath, ossFilePath);
|
||||
return ossFilePath;
|
||||
} catch (Exception e) {
|
||||
logger.error("文件上传到OSS失败 - localPath: {}, error: {}", localFilePath, e.getMessage(), e);
|
||||
throw new RuntimeException("文件上传到OSS失败: " + e.getMessage(), e);
|
||||
@@ -69,34 +69,25 @@ public class OSSUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到阿里云OSS(自定义存储路径)
|
||||
* 上传文件到阿里云OSS(自定义存储路径,文件默认继承Bucket权限)
|
||||
*
|
||||
* @param localFilePath 本地文件路径
|
||||
* @param ossDirectory OSS存储目录
|
||||
* @param fileName 文件名(不含路径)
|
||||
* @return OSS访问地址
|
||||
* @return OSS object key(不含域名前缀)
|
||||
*/
|
||||
public static String uploadToOSS(String localFilePath, String ossDirectory, String fileName) {
|
||||
OSS ossClient = null;
|
||||
try {
|
||||
// 创建OSS客户端
|
||||
ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||
|
||||
// 构建OSS文件路径
|
||||
String ossFilePath = ossDirectory + fileName;
|
||||
|
||||
// 创建上传请求
|
||||
PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, ossFilePath, new File(localFilePath));
|
||||
|
||||
// 上传文件
|
||||
ossClient.putObject(putObjectRequest);
|
||||
|
||||
// 构建访问地址
|
||||
String accessUrl = OSS_URL_PREFIX + ossFilePath;
|
||||
|
||||
logger.info("文件上传到OSS成功: localPath={}, ossUrl={}", localFilePath, accessUrl);
|
||||
|
||||
return accessUrl;
|
||||
logger.info("文件上传到OSS成功: localPath={}, ossKey={}", localFilePath, ossFilePath);
|
||||
return ossFilePath;
|
||||
} catch (Exception e) {
|
||||
logger.error("文件上传到OSS失败 - localPath: {}, error: {}", localFilePath, e.getMessage(), e);
|
||||
throw new RuntimeException("文件上传到OSS失败: " + e.getMessage(), e);
|
||||
@@ -106,4 +97,78 @@ public class OSSUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传封面图到阿里云OSS(使用InputStream,文件默认继承Bucket权限)
|
||||
*
|
||||
* @param inputStream 文件输入流
|
||||
* @param fileName 文件名(不含路径)
|
||||
* @return OSS object key(不含域名前缀)
|
||||
*/
|
||||
public static String uploadCoverToOSS(InputStream inputStream, String fileName) {
|
||||
OSS ossClient = null;
|
||||
try {
|
||||
ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||
|
||||
String datePath = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||
String ossFilePath = COVER_DIR + datePath + "/" + fileName;
|
||||
|
||||
ossClient.putObject(BUCKET_NAME, ossFilePath, inputStream);
|
||||
|
||||
logger.info("封面上传到OSS成功: fileName={}, ossKey={}", fileName, ossFilePath);
|
||||
return ossFilePath;
|
||||
} catch (Exception e) {
|
||||
logger.error("封面上传到OSS失败 - fileName: {}, error: {}", fileName, e.getMessage(), e);
|
||||
throw new RuntimeException("封面上传到OSS失败: " + e.getMessage(), e);
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成OSS对象预签名URL(临时访问链接)
|
||||
*
|
||||
* @param ossKey OSS对象Key(不含域名前缀)
|
||||
* @return 预签名URL
|
||||
*/
|
||||
public static String generatePresignedUrl(String ossKey) {
|
||||
return generatePresignedUrl(ossKey, PRESIGN_EXPIRE_SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成OSS对象预签名URL(可指定有效期)
|
||||
*
|
||||
* @param ossKey OSS对象Key(不含域名前缀)
|
||||
* @param expireSeconds 有效期(秒)
|
||||
* @return 预签名URL
|
||||
*/
|
||||
public static String generatePresignedUrl(String ossKey, long expireSeconds) {
|
||||
OSS ossClient = null;
|
||||
try {
|
||||
ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||
|
||||
Date expiration = new Date(System.currentTimeMillis() + expireSeconds * 1000);
|
||||
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(BUCKET_NAME, ossKey, HttpMethod.GET);
|
||||
request.setExpiration(expiration);
|
||||
|
||||
URL signedUrl = ossClient.generatePresignedUrl(request);
|
||||
return signedUrl.toString();
|
||||
} catch (Exception e) {
|
||||
logger.error("生成预签名URL失败 - ossKey: {}, error: {}", ossKey, e.getMessage(), e);
|
||||
throw new RuntimeException("生成预签名URL失败: " + e.getMessage(), e);
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据OSS Key拼接公开访问URL(仅当Bucket为公共读时有效)
|
||||
*/
|
||||
public static String getPublicUrl(String ossKey) {
|
||||
return OSS_URL_PREFIX + ossKey;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user