diff --git a/pom.xml b/pom.xml
index 98f4870..4a0ea15 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,12 @@
spring-boot-starter-security
+
+
+ io.minio
+ minio
+ 8.0.3
+
diff --git a/src/main/java/com/aida/lanecarford/common/response/ResultEnum.java b/src/main/java/com/aida/lanecarford/common/response/ResultEnum.java
new file mode 100644
index 0000000..d1df838
--- /dev/null
+++ b/src/main/java/com/aida/lanecarford/common/response/ResultEnum.java
@@ -0,0 +1,67 @@
+package com.aida.lanecarford.common.response;
+
+/**
+ * @ClassName ResultEnum
+ * @Description 响应结果枚举
+ * @Author dwjian
+ * @Date 2019/9/8 21:58
+ */
+public enum ResultEnum {
+
+ SUCCESS(true, 0, "SUCCESS", "操作成功"),
+ FAIL(false, -1, "FAIL", "操作失败"),
+ ERROR(false, -1, "System error", "系统错误"),
+ PARAMETER_ERROR(false, -2, "Parameter error", "参数错误"),
+
+ NO_LOGIN(false, -100, "User not logged in", "用户未登录"),
+ NO_PERMISSION(false, -200, "No permission", "无权限访问"),
+ ACCOUNT_LOCK(false, -300, "Account locked", "账户已锁定"),
+
+ PROMPT(false, 1, "Prompt", "提示"),
+ WARNING(false, 2, "Warning", "警告"),
+
+ ;
+ private int code;
+ private String msg; // 英文消息,返回给前端
+ private String msgCn; // 中文消息,用于日志
+ private boolean isOK;
+
+ ResultEnum(boolean isOK, int code, String msg, String msgCn) {
+ this.isOK = isOK;
+ this.code = code;
+ this.msg = msg;
+ this.msgCn = msgCn;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public String getMsgCn() {
+ return msgCn;
+ }
+
+ public void setMsgCn(String msgCn) {
+ this.msgCn = msgCn;
+ }
+
+ public boolean isOK() {
+ return isOK;
+ }
+
+ public void setOK(boolean OK) {
+ isOK = OK;
+ }
+}
diff --git a/src/main/java/com/aida/lanecarford/controller/TryOnEffectController.java b/src/main/java/com/aida/lanecarford/controller/TryOnEffectController.java
index 128a9be..049c878 100644
--- a/src/main/java/com/aida/lanecarford/controller/TryOnEffectController.java
+++ b/src/main/java/com/aida/lanecarford/controller/TryOnEffectController.java
@@ -1,7 +1,15 @@
package com.aida.lanecarford.controller;
+import com.aida.lanecarford.common.ApiResponse;
+import com.aida.lanecarford.entity.TryOnEffect;
import com.aida.lanecarford.service.TryOnEffectService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -14,8 +22,18 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/try-on-effects")
@RequiredArgsConstructor
+@Tag(name = "试穿效果管理", description = "试穿效果生成和管理相关API")
public class TryOnEffectController {
private final TryOnEffectService tryOnEffectService;
+ @Operation(summary = "生成试穿效果", description = "根据顾客照片和模特照片生成试穿效果")
+ @PostMapping("/generate")
+ public ApiResponse generateTryOnEffect(
+ @Parameter(description = "试穿效果请求参数", required = true)
+ @Valid @RequestBody TryOnEffect tryOnEffectDto) {
+ String taskId = tryOnEffectService.generateTryOnEffect(tryOnEffectDto);
+ return ApiResponse.success(taskId);
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/com/aida/lanecarford/entity/CustomerPhoto.java b/src/main/java/com/aida/lanecarford/entity/CustomerPhoto.java
index e2a0799..d25620b 100644
--- a/src/main/java/com/aida/lanecarford/entity/CustomerPhoto.java
+++ b/src/main/java/com/aida/lanecarford/entity/CustomerPhoto.java
@@ -64,4 +64,10 @@ public class CustomerPhoto {
*/
@TableField(value = "created_time", fill = FieldFill.INSERT)
private LocalDateTime createdTime;
+
+ /**
+ * 更新时间
+ */
+ @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updatedTime;
}
\ No newline at end of file
diff --git a/src/main/java/com/aida/lanecarford/entity/Style.java b/src/main/java/com/aida/lanecarford/entity/Style.java
index 00d5f8b..e57f640 100644
--- a/src/main/java/com/aida/lanecarford/entity/Style.java
+++ b/src/main/java/com/aida/lanecarford/entity/Style.java
@@ -60,10 +60,10 @@ public class Style {
private String pythonRequestId;
/**
- * 生成状态(0-处理中,1-已完成,2-失败)
+ * 生成状态(pending-等待中,processing-处理中,completed-已完成,failed-失败)
*/
@TableField("generation_status")
- private Integer generationStatus;
+ private String generationStatus;
/**
* 错误信息
diff --git a/src/main/java/com/aida/lanecarford/entity/TryOnEffect.java b/src/main/java/com/aida/lanecarford/entity/TryOnEffect.java
index 5909738..77c4d53 100644
--- a/src/main/java/com/aida/lanecarford/entity/TryOnEffect.java
+++ b/src/main/java/com/aida/lanecarford/entity/TryOnEffect.java
@@ -41,6 +41,12 @@ public class TryOnEffect {
@TableField("visit_record_id")
private Long visitRecordId;
+ /**
+ * 风格ID
+ */
+ @TableField("style_id")
+ private Long styleId;
+
/**
* 顾客照片ID
*/
@@ -53,12 +59,6 @@ public class TryOnEffect {
@TableField("model_photo_id")
private Long modelPhotoId;
- /**
- * 试穿效果图URL
- */
- @TableField("try_on_image_url")
- private String tryOnImageUrl;
-
/**
* 提示词
*/
@@ -66,16 +66,34 @@ public class TryOnEffect {
private String prompt;
/**
- * Python请求ID
+ * 原试穿效果ID,当is_regenerated为1时才会有值
*/
- @TableField("python_request_id")
- private String pythonRequestId;
+ @TableField("original_try_on_id")
+ private Long originalTryOnId;
/**
- * 生成状态(0-处理中,1-已完成,2-失败)
+ * 是否由生成结果重新生成(0-否,1-是)
+ */
+ @TableField("is_regenerated")
+ private Integer isRegenerated;
+
+ /**
+ * 试穿结果图片URL
+ */
+ @TableField("result_image_url")
+ private String resultImageUrl;
+
+ /**
+ * 请求ID
+ */
+ @TableField("request_id")
+ private String requestId;
+
+ /**
+ * 生成状态(pending-等待中,processing-处理中,completed-已完成,failed-失败)
*/
@TableField("generation_status")
- private Integer generationStatus;
+ private String generationStatus;
/**
* 错误信息
@@ -84,17 +102,11 @@ public class TryOnEffect {
private String errorMessage;
/**
- * 是否收藏(0-否,1-是)
+ * 是否喜欢的最终造型(0-否,1-是)
*/
@TableField("is_favorite")
private Integer isFavorite;
- /**
- * 原始试穿效果ID(用于重新生成)
- */
- @TableField("original_try_on_id")
- private Long originalTryOnId;
-
/**
* 创建时间
*/
diff --git a/src/main/java/com/aida/lanecarford/exception/BusinessException.java b/src/main/java/com/aida/lanecarford/exception/BusinessException.java
index e39b7f8..31f1508 100644
--- a/src/main/java/com/aida/lanecarford/exception/BusinessException.java
+++ b/src/main/java/com/aida/lanecarford/exception/BusinessException.java
@@ -1,121 +1,126 @@
package com.aida.lanecarford.exception;
+import com.aida.lanecarford.common.response.ResultEnum;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
/**
* 业务异常类
*
* @author AI Assistant
* @since 2024-01-01
*/
+@Data
+@Slf4j
public class BusinessException extends RuntimeException {
- private String code;
- private String message;
+ private Integer code;
+ private String msg; // 英文消息,返回给前端
+ private String msgCn; // 中文消息,用于日志
- public BusinessException(String code, String message) {
- super(message);
+ public BusinessException(String msg) {
+ this.code = ResultEnum.FAIL.getCode();
+ this.msg = msg;
+ this.msgCn = msg;
+ }
+
+ public BusinessException(String msg, Integer code) {
this.code = code;
- this.message = message;
+ this.msg = msg;
+ this.msgCn = msg;
}
- public BusinessException(String message) {
- super(message);
- this.code = "BUSINESS_ERROR";
- this.message = message;
- }
-
- public BusinessException(String code, String message, Throwable cause) {
- super(message, cause);
+ public BusinessException(String msg, String msgCn, Integer code) {
this.code = code;
- this.message = message;
+ this.msg = msg;
+ this.msgCn = msgCn;
}
- public String getCode() {
- return code;
+ public BusinessException(ResultEnum resultEnum) {
+ this.code = resultEnum.getCode();
+ this.msg = resultEnum.getMsg();
+ this.msgCn = resultEnum.getMsgCn();
}
- public void setCode(String code) {
- this.code = code;
+ public BusinessException(ResultEnum resultEnum, String customMessage, String customMessageCn) {
+ this.code = resultEnum.getCode();
+ this.msg = customMessage;
+ this.msgCn = customMessageCn;
}
- @Override
- public String getMessage() {
- return message;
+ /**
+ * 创建原始试穿ID必填异常
+ */
+ public static BusinessException originalTryOnIdRequired() {
+ return new BusinessException(ResultEnum.PARAMETER_ERROR, "Original try-on ID is required", "原始试穿ID不能为空");
}
- public void setMessage(String message) {
- this.message = message;
+ /**
+ * 创建风格ID必填异常
+ */
+ public static BusinessException styleIdRequired() {
+ return new BusinessException(ResultEnum.PARAMETER_ERROR, "Style ID is required", "风格ID不能为空");
}
- // 常用的业务异常静态方法
- public static BusinessException customerNotFound() {
- return new BusinessException("CUSTOMER_NOT_FOUND", "客户不存在");
+ /**
+ * 创建通用参数为空异常
+ */
+ public static BusinessException parameterRequired(String parameterName) {
+ return new BusinessException(ResultEnum.PARAMETER_ERROR,
+ parameterName + " is required",
+ parameterName + "不能为空");
}
- public static BusinessException styleOutfitNotFound() {
- return new BusinessException("STYLE_OUTFIT_NOT_FOUND", "风格搭配不存在");
- }
-
- public static BusinessException modelPhotoNotFound() {
- return new BusinessException("MODEL_PHOTO_NOT_FOUND", "模特照片不存在");
- }
-
- public static BusinessException virtualTryOnNotFound() {
- return new BusinessException("VIRTUAL_TRYON_NOT_FOUND", "虚拟试穿记录不存在");
- }
-
- public static BusinessException favoriteNotFound() {
- return new BusinessException("FAVORITE_NOT_FOUND", "收藏记录不存在");
- }
-
- public static BusinessException fileUploadFailed() {
- return new BusinessException("FILE_UPLOAD_FAILED", "文件上传失败");
- }
-
- public static BusinessException invalidFileFormat() {
- return new BusinessException("INVALID_FILE_FORMAT", "文件格式不支持");
- }
-
- public static BusinessException fileSizeExceeded() {
- return new BusinessException("FILE_SIZE_EXCEEDED", "文件大小超过限制");
- }
-
- public static BusinessException emailAlreadyExists() {
- return new BusinessException("EMAIL_ALREADY_EXISTS", "邮箱已存在");
- }
-
- public static BusinessException phoneAlreadyExists() {
- return new BusinessException("PHONE_ALREADY_EXISTS", "手机号已存在");
- }
-
- public static BusinessException invalidCredentials() {
- return new BusinessException("INVALID_CREDENTIALS", "用户名或密码错误");
+ /**
+ * 创建资源不存在异常
+ */
+ public static BusinessException resourceNotFound(String resourceName) {
+ return new BusinessException(ResultEnum.FAIL,
+ resourceName + " not found",
+ resourceName + "不存在");
}
+ /**
+ * 创建权限不足异常
+ */
public static BusinessException accessDenied() {
- return new BusinessException("ACCESS_DENIED", "访问被拒绝");
+ return new BusinessException(ResultEnum.NO_PERMISSION);
}
- public static BusinessException operationFailed() {
- return new BusinessException("OPERATION_FAILED", "操作失败");
+ /**
+ * 创建操作失败异常
+ */
+ public static BusinessException operationFailed(String operation) {
+ return new BusinessException(ResultEnum.ERROR,
+ operation + " operation failed",
+ operation + "操作失败");
}
- public static BusinessException dataNotFound() {
- return new BusinessException("DATA_NOT_FOUND", "数据不存在");
+ /**
+ * 创建用户未登录异常
+ */
+ public static BusinessException notLogin() {
+ return new BusinessException(ResultEnum.NO_LOGIN);
}
- public static BusinessException duplicateData() {
- return new BusinessException("DUPLICATE_DATA", "数据重复");
+ /**
+ * 创建账户锁定异常
+ */
+ public static BusinessException accountLocked() {
+ return new BusinessException(ResultEnum.ACCOUNT_LOCK);
}
- public static BusinessException invalidParameter(String paramName) {
- return new BusinessException("INVALID_PARAMETER", "参数 " + paramName + " 无效");
+ /**
+ * 创建提示异常
+ */
+ public static BusinessException prompt(String message, String messageCn) {
+ return new BusinessException(ResultEnum.PROMPT, message, messageCn);
}
- public static BusinessException serviceUnavailable() {
- return new BusinessException("SERVICE_UNAVAILABLE", "服务暂时不可用");
- }
-
- public static BusinessException externalServiceError() {
- return new BusinessException("EXTERNAL_SERVICE_ERROR", "外部服务调用失败");
+ /**
+ * 创建警告异常
+ */
+ public static BusinessException warning(String message, String messageCn) {
+ return new BusinessException(ResultEnum.WARNING, message, messageCn);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/aida/lanecarford/exception/GlobalExceptionHandler.java b/src/main/java/com/aida/lanecarford/exception/GlobalExceptionHandler.java
index f403b64..171c980 100644
--- a/src/main/java/com/aida/lanecarford/exception/GlobalExceptionHandler.java
+++ b/src/main/java/com/aida/lanecarford/exception/GlobalExceptionHandler.java
@@ -1,37 +1,23 @@
package com.aida.lanecarford.exception;
+import com.aida.lanecarford.common.ApiResponse;
+import com.aida.lanecarford.common.response.ResultEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.dao.DataAccessException;
-import org.springframework.dao.DataIntegrityViolationException;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
-import org.springframework.web.HttpMediaTypeNotSupportedException;
-import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
-import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
-import org.springframework.web.servlet.NoHandlerFoundException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ConstraintViolationException;
import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
import java.util.stream.Collectors;
/**
* 全局异常处理器
* 统一处理应用程序中的各种异常,提供一致的错误响应格式
- *
+ *
* @author AI Assistant
* @since 2024-01-01
*/
@@ -39,246 +25,102 @@ import java.util.stream.Collectors;
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
-
- // 错误代码常量
- private static final String BUSINESS_ERROR = "BUSINESS_ERROR";
- private static final String VALIDATION_ERROR = "VALIDATION_ERROR";
- private static final String BIND_ERROR = "BIND_ERROR";
- private static final String FILE_SIZE_EXCEEDED = "FILE_SIZE_EXCEEDED";
- private static final String ILLEGAL_ARGUMENT = "ILLEGAL_ARGUMENT";
- private static final String NULL_POINTER = "NULL_POINTER";
- private static final String RUNTIME_ERROR = "RUNTIME_ERROR";
- private static final String UNKNOWN_ERROR = "UNKNOWN_ERROR";
- private static final String DATABASE_ERROR = "DATABASE_ERROR";
- private static final String METHOD_NOT_ALLOWED = "METHOD_NOT_ALLOWED";
- private static final String NOT_FOUND = "NOT_FOUND";
- private static final String MEDIA_TYPE_NOT_SUPPORTED = "MEDIA_TYPE_NOT_SUPPORTED";
- private static final String MESSAGE_NOT_READABLE = "MESSAGE_NOT_READABLE";
- private static final String MISSING_PARAMETER = "MISSING_PARAMETER";
- private static final String TYPE_MISMATCH = "TYPE_MISMATCH";
- private static final String CONSTRAINT_VIOLATION = "CONSTRAINT_VIOLATION";
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
- public ResponseEntity