3
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.aida.lanecarford.common;
|
||||
|
||||
import com.aida.lanecarford.common.response.ResultEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -20,7 +21,7 @@ public class ApiResponse<T> implements Serializable {
|
||||
/**
|
||||
* 响应状态码
|
||||
*/
|
||||
private String code;
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 响应消息
|
||||
@@ -46,7 +47,7 @@ public class ApiResponse<T> implements Serializable {
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public ApiResponse(boolean success, String code, String message, T data) {
|
||||
public ApiResponse(boolean success, Integer code, String message, T data) {
|
||||
this();
|
||||
this.success = success;
|
||||
this.code = code;
|
||||
@@ -58,34 +59,34 @@ public class ApiResponse<T> implements Serializable {
|
||||
* 成功响应(无数据)
|
||||
*/
|
||||
public static <T> ApiResponse<T> success() {
|
||||
return new ApiResponse<>(true, "SUCCESS", "操作成功", null);
|
||||
return new ApiResponse<>(true, ResultEnum.SUCCESS.getCode(), "操作成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(带数据)
|
||||
*/
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(true, "SUCCESS", "操作成功", data);
|
||||
return new ApiResponse<>(true, ResultEnum.SUCCESS.getCode(), "操作成功", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(自定义消息,无数据)
|
||||
*/
|
||||
public static <T> ApiResponse<T> success(String message) {
|
||||
return new ApiResponse<>(true, "SUCCESS", message, null);
|
||||
return new ApiResponse<>(true, ResultEnum.SUCCESS.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(自定义消息)
|
||||
*/
|
||||
public static <T> ApiResponse<T> success(String message, T data) {
|
||||
return new ApiResponse<>(true, "SUCCESS", message, data);
|
||||
return new ApiResponse<>(true, ResultEnum.SUCCESS.getCode(), message, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> error(String code, String message) {
|
||||
public static <T> ApiResponse<T> error(Integer code, String message) {
|
||||
return new ApiResponse<>(false, code, message, null);
|
||||
}
|
||||
|
||||
@@ -93,76 +94,76 @@ public class ApiResponse<T> implements Serializable {
|
||||
* 失败响应(默认错误码)
|
||||
*/
|
||||
public static <T> ApiResponse<T> error(String message) {
|
||||
return new ApiResponse<>(false, "ERROR", message, null);
|
||||
return new ApiResponse<>(false, ResultEnum.ERROR.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数错误响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> paramError(String message) {
|
||||
return new ApiResponse<>(false, "PARAM_ERROR", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据不存在响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> notFound(String message) {
|
||||
return new ApiResponse<>(false, "NOT_FOUND", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限不足响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> forbidden(String message) {
|
||||
return new ApiResponse<>(false, "FORBIDDEN", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务器内部错误响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> serverError(String message) {
|
||||
return new ApiResponse<>(false, "SERVER_ERROR", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务异常响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> businessError(String code, String message) {
|
||||
return new ApiResponse<>(false, code, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 外部服务错误响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> externalServiceError(String message) {
|
||||
return new ApiResponse<>(false, "EXTERNAL_SERVICE_ERROR", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传错误响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> fileUploadError(String message) {
|
||||
return new ApiResponse<>(false, "FILE_UPLOAD_ERROR", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证失败响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> validationError(String message) {
|
||||
return new ApiResponse<>(false, "VALIDATION_ERROR", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重复数据响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> duplicateError(String message) {
|
||||
return new ApiResponse<>(false, "DUPLICATE_ERROR", message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作超时响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> timeoutError(String message) {
|
||||
return new ApiResponse<>(false, "TIMEOUT_ERROR", message, null);
|
||||
}
|
||||
// /**
|
||||
// * 参数错误响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> paramError(String message) {
|
||||
// return new ApiResponse<>(false, "PARAM_ERROR", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 数据不存在响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> notFound(String message) {
|
||||
// return new ApiResponse<>(false, "NOT_FOUND", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 权限不足响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> forbidden(String message) {
|
||||
// return new ApiResponse<>(false, "FORBIDDEN", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 服务器内部错误响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> serverError(String message) {
|
||||
// return new ApiResponse<>(false, "SERVER_ERROR", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 业务异常响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> businessError(String code, String message) {
|
||||
// return new ApiResponse<>(false, code, message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 外部服务错误响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> externalServiceError(String message) {
|
||||
// return new ApiResponse<>(false, "EXTERNAL_SERVICE_ERROR", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 文件上传错误响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> fileUploadError(String message) {
|
||||
// return new ApiResponse<>(false, "FILE_UPLOAD_ERROR", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 验证失败响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> validationError(String message) {
|
||||
// return new ApiResponse<>(false, "VALIDATION_ERROR", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 重复数据响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> duplicateError(String message) {
|
||||
// return new ApiResponse<>(false, "DUPLICATE_ERROR", message, null);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 操作超时响应
|
||||
// */
|
||||
// public static <T> ApiResponse<T> timeoutError(String message) {
|
||||
// return new ApiResponse<>(false, "TIMEOUT_ERROR", message, null);
|
||||
// }
|
||||
}
|
||||
@@ -40,7 +40,8 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
registry.addInterceptor(jwtInterceptor)
|
||||
.addPathPatterns("/api/**/**") // 保护这些路径
|
||||
.excludePathPatterns(Arrays.asList("/api/auth/precheckAndSendEmail", "/api/auth/register",
|
||||
"/api/auth/login", "/api/auth/forgotPwd", "/api/style/callback")); // 排除登录接口
|
||||
"/api/auth/login", "/api/auth/forgotPwd", "/api/style/callback","/api/try-on-effects","/api/customer-photos","/api/visit-records")); // 排除登录接口
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.aida.lanecarford.service.CustomerService;
|
||||
import com.aida.lanecarford.vo.CustomerCheckInVO;
|
||||
import com.aida.lanecarford.vo.CustomerVO;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -16,10 +18,15 @@ import org.springframework.web.bind.annotation.*;
|
||||
@RestController
|
||||
@RequestMapping("/api/customers")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "顾客管理", description = "顾客入店登记、信息查询等相关API接口")
|
||||
public class CustomerController {
|
||||
|
||||
private final CustomerService customerService;
|
||||
|
||||
@Operation(
|
||||
summary = "顾客入店登记",
|
||||
description = "验证顾客身份并创建入店记录,如果是新顾客则自动注册到系统中。"
|
||||
)
|
||||
@GetMapping("/checkIn")
|
||||
public ApiResponse<CustomerCheckInVO> customerCheckIn(@RequestParam String name, @RequestParam String email) {
|
||||
return ApiResponse.success(customerService.customerCheckIn(name, email));
|
||||
|
||||
@@ -5,8 +5,8 @@ import com.aida.lanecarford.dto.CustomerPhotoDto;
|
||||
import com.aida.lanecarford.entity.CustomerPhoto;
|
||||
import com.aida.lanecarford.service.CustomerPhotoService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
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;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class CustomerPhotoController {
|
||||
private final CustomerPhotoService customerPhotoService;
|
||||
|
||||
@PostMapping("/upload")
|
||||
public ApiResponse<CustomerPhoto> upload(@RequestBody CustomerPhotoDto customerPhotoDto) {
|
||||
public ApiResponse<CustomerPhoto> upload(@ModelAttribute CustomerPhotoDto customerPhotoDto) {
|
||||
CustomerPhoto customerPhoto = customerPhotoService.upload(customerPhotoDto);
|
||||
return ApiResponse.success(customerPhoto);
|
||||
}
|
||||
|
||||
@@ -4,45 +4,72 @@ import com.aida.lanecarford.common.ApiResponse;
|
||||
import com.aida.lanecarford.dto.LoginRequest;
|
||||
import com.aida.lanecarford.service.LoginService;
|
||||
import com.aida.lanecarford.vo.LoginVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 用户认证控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "用户认证管理", description = "用户注册、登录、登出等认证相关API接口")
|
||||
public class LoginController {
|
||||
|
||||
@Resource
|
||||
private LoginService loginService;
|
||||
private final LoginService loginService;
|
||||
|
||||
@Operation(
|
||||
summary = "预检查并发送邮箱验证码",
|
||||
description = "根据操作类型验证邮箱有效性并发送验证码。支持注册、登录、忘记密码三种操作类型。"
|
||||
)
|
||||
@PostMapping("/precheckAndSendEmail")
|
||||
public ApiResponse<String> preCheckAndSendEmail(@Valid @RequestBody LoginRequest loginRequest) {
|
||||
loginService.preCheckAndSendEmail(loginRequest);
|
||||
return ApiResponse.success();
|
||||
return ApiResponse.success("验证码已发送到您的邮箱");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "用户注册或登录",
|
||||
description = "通过验证码完成用户注册或登录,返回JWT令牌和用户信息。"
|
||||
)
|
||||
@PostMapping("/registerOrLogin")
|
||||
public ApiResponse<LoginVO> registerOrLogin(@Valid @RequestBody LoginRequest loginRequest) {
|
||||
return ApiResponse.success(loginService.registerOrLogin(loginRequest));
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "用户登出",
|
||||
description = "清除用户登录状态,使当前JWT令牌失效。"
|
||||
)
|
||||
@GetMapping("/logout")
|
||||
public ApiResponse<String> logout() {
|
||||
loginService.logout();
|
||||
return ApiResponse.success();
|
||||
return ApiResponse.success("登出成功");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "忘记密码",
|
||||
description = "通过邮箱验证码重置用户密码。需要先获取验证码,然后提供新密码。"
|
||||
)
|
||||
@PostMapping("/forgotPwd")
|
||||
public ApiResponse<String> forgotPwd(@Valid @RequestBody LoginRequest loginRequest) {
|
||||
loginService.forgotPwd(loginRequest);
|
||||
return ApiResponse.success();
|
||||
return ApiResponse.success("密码重置成功");
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "检查登录状态",
|
||||
description = "验证当前用户的登录状态是否有效,检查JWT令牌是否过期。"
|
||||
)
|
||||
@GetMapping("/checkLoginStatus")
|
||||
public ApiResponse<String> checkLoginStatus() {
|
||||
boolean isLogin = loginService.checkLoginStatus();
|
||||
if (isLogin){
|
||||
return ApiResponse.success();
|
||||
if (isLogin) {
|
||||
return ApiResponse.success("用户已登录");
|
||||
} else {
|
||||
return ApiResponse.error("Please log in again.");
|
||||
}
|
||||
|
||||
@@ -1,24 +1,63 @@
|
||||
package com.aida.lanecarford.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "登录请求数据传输对象")
|
||||
public class LoginRequest {
|
||||
|
||||
|
||||
@Schema(
|
||||
description = "用户名(仅注册时需要)",
|
||||
example = "张三",
|
||||
maxLength = 50
|
||||
)
|
||||
private String name;
|
||||
|
||||
|
||||
@NotBlank(message = "email cannot be empty")
|
||||
@Email(message = "Email format is incorrect.")
|
||||
@Schema(
|
||||
description = "邮箱地址",
|
||||
example = "user@example.com",
|
||||
required = true,
|
||||
format = "email"
|
||||
)
|
||||
private String email;
|
||||
|
||||
|
||||
@NotBlank(message = "password cannot be empty")
|
||||
@Size(min = 6, message = "Password must be at least 6 characters.")
|
||||
@Schema(
|
||||
description = "密码(至少6位字符)",
|
||||
example = "password123",
|
||||
required = true,
|
||||
minLength = 6,
|
||||
maxLength = 100
|
||||
)
|
||||
private String password;
|
||||
|
||||
|
||||
@NotBlank(message = "operation type cannot be empty")
|
||||
@Schema(
|
||||
description = "操作类型",
|
||||
example = "REGISTER",
|
||||
required = true,
|
||||
allowableValues = {"REGISTER", "LOGIN", "FORGET_PWD"/*,"CHANGE_MAILBOX","EXCEPTION_IP","BIND_MAILBOX"*/}
|
||||
)
|
||||
private String operationType;
|
||||
|
||||
|
||||
@Schema(
|
||||
description = "邮箱验证码(6位数字)",
|
||||
example = "123456",
|
||||
pattern = "\\d{6}",
|
||||
minLength = 6,
|
||||
maxLength = 6
|
||||
)
|
||||
private String verifyCode;
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public ApiResponse<Object> handleBusinessException(BusinessException e) {
|
||||
logger.warn("业务异常: {}", e.getMsgCn() != null ? e.getMsgCn() : e.getMsg());
|
||||
return ApiResponse.error(String.valueOf(e.getCode()), e.getMsg());
|
||||
return ApiResponse.error(e.getCode(), e.getMsg());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ public class GlobalExceptionHandler {
|
||||
.reduce((msg1, msg2) -> msg1 + "; " + msg2)
|
||||
.orElse("Parameter validation failed");
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.PARAMETER_ERROR.getCode()), errorMessageEn);
|
||||
return ApiResponse.error(ResultEnum.PARAMETER_ERROR.getCode(), errorMessageEn);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +66,7 @@ public class GlobalExceptionHandler {
|
||||
.reduce((msg1, msg2) -> msg1 + "; " + msg2)
|
||||
.orElse("Data binding failed");
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.PARAMETER_ERROR.getCode()), errorMessageEn);
|
||||
return ApiResponse.error(ResultEnum.PARAMETER_ERROR.getCode(), errorMessageEn);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ public class GlobalExceptionHandler {
|
||||
|
||||
logger.warn("文件上传大小超限: {}", e.getMessage());
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.PARAMETER_ERROR.getCode()), "File size exceeds limit");
|
||||
return ApiResponse.error(ResultEnum.PARAMETER_ERROR.getCode(), "File size exceeds limit");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +88,7 @@ public class GlobalExceptionHandler {
|
||||
|
||||
logger.error("MinIO异常: {}", e.getMessage(), e);
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.ERROR.getCode()), "File storage service error");
|
||||
return ApiResponse.error(ResultEnum.ERROR.getCode(), "File storage service error");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +99,7 @@ public class GlobalExceptionHandler {
|
||||
|
||||
logger.error("数据库异常: {}", e.getMessage(), e);
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.ERROR.getCode()), "Database operation failed");
|
||||
return ApiResponse.error(ResultEnum.ERROR.getCode(), "Database operation failed");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +110,7 @@ public class GlobalExceptionHandler {
|
||||
|
||||
logger.error("运行时异常: {}", e.getMessage(), e);
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.ERROR.getCode()), "System runtime error");
|
||||
return ApiResponse.error(ResultEnum.ERROR.getCode(), "System runtime error");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,6 +121,6 @@ public class GlobalExceptionHandler {
|
||||
|
||||
logger.error("未知异常: {}", e.getMessage(), e);
|
||||
|
||||
return ApiResponse.error(String.valueOf(ResultEnum.ERROR.getCode()), "System internal error");
|
||||
return ApiResponse.error(ResultEnum.ERROR.getCode(), "System internal error");
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ public class StyleServiceImpl extends ServiceImpl<StyleMapper, Style> implements
|
||||
// 3.更新path, items, 状态
|
||||
// 由于数据变化较频繁,考虑存到redis
|
||||
if (outfitResult instanceof OutfitResultVO) {
|
||||
((OutfitResultVO) outfitResult).setPath(minioUtil.getPresignedUrl(callbackDTO.getPath(), CommonConstants.MINIO_PATH_TIMEOUT));
|
||||
((OutfitResultVO) outfitResult).setPath(minioUtil.getPresignedUrl(callbackDTO.getPath(), CommonConstants.MINIO_PATH_TIMEOUT, null));
|
||||
((OutfitResultVO) outfitResult).setStatus(StatusEnum.SUCCEEDED.name());
|
||||
cacheUtil.setCache(key, outfitResult, RedisURIConstants.verifyCodeTimeout);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ public class StyleServiceImpl extends ServiceImpl<StyleMapper, Style> implements
|
||||
outfitResultVO.setRequestId(style.getPythonRequestId());
|
||||
outfitResultVO.setStatus(style.getGenerationStatus());
|
||||
if (!StringUtil.isNullOrEmpty(style.getStyleImageUrl())) {
|
||||
outfitResultVO.setPath(minioUtil.getPresignedUrl(style.getStyleImageUrl(), CommonConstants.MINIO_PATH_TIMEOUT));
|
||||
outfitResultVO.setPath(minioUtil.getPresignedUrl(style.getStyleImageUrl(), CommonConstants.MINIO_PATH_TIMEOUT, null));
|
||||
}
|
||||
resultVOS.add(outfitResultVO);
|
||||
}
|
||||
|
||||
@@ -103,34 +103,37 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
}
|
||||
}
|
||||
|
||||
// 合成图片
|
||||
if (!imageUrls.isEmpty() && imageUrls.size() > 1) {
|
||||
log.info("开始合成图片,图片数量: {}", imageUrls.size());
|
||||
try {
|
||||
// 将逻辑URL批量转换为预签名URL,以便图像合成服务可以访问
|
||||
List<String> presignedUrls = minioUtil.convertToPresignedUrls(imageUrls, CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
|
||||
log.debug("批量转换逻辑URL为预签名URL,数量: {}", presignedUrls.size());
|
||||
|
||||
toAIlogicalUrl = imageCompositionService.composeAndUploadImages(presignedUrls);
|
||||
|
||||
log.info("图片合成成功,合成图片URL: {}", toAIlogicalUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("图片合成失败: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("image error " + e.getMessage(), e);
|
||||
}
|
||||
} else if (imageUrls.size() == 1) {
|
||||
toAIlogicalUrl = imageUrls.get(0);
|
||||
} else {
|
||||
log.warn("没有找到有效的图片URL进行合成");
|
||||
throw BusinessException.parameterRequired("image");
|
||||
}
|
||||
}
|
||||
|
||||
// 合成图片
|
||||
if (!imageUrls.isEmpty() && imageUrls.size() > 1) {
|
||||
log.info("开始合成图片,图片数量: {}", imageUrls.size());
|
||||
try {
|
||||
// 将逻辑URL批量转换为预签名URL,以便图像合成服务可以访问
|
||||
List<String> presignedUrls = minioUtil.convertToPresignedUrls(imageUrls, CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
|
||||
log.debug("批量转换逻辑URL为预签名URL,数量: {}", presignedUrls.size());
|
||||
|
||||
toAIlogicalUrl = imageCompositionService.composeAndUploadImages(presignedUrls);
|
||||
|
||||
log.info("图片合成成功,合成图片URL: {}", toAIlogicalUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("图片合成失败: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("image error " + e.getMessage(), e);
|
||||
}
|
||||
} else if (imageUrls.size() == 1) {
|
||||
toAIlogicalUrl = imageUrls.get(0);
|
||||
} else {
|
||||
log.warn("没有找到有效的图片URL进行合成");
|
||||
throw BusinessException.parameterRequired("image");
|
||||
}
|
||||
//调用模型生成试穿效果
|
||||
log.info("准备调用第三方AI服务,输入图片URL: {}", toAIlogicalUrl);
|
||||
String AIRreultlogicalUrl = AITryOnEffect(prompt, toAIlogicalUrl);
|
||||
prompt = "A woman is wearing the outfit (an outerwear, a top, pants, shoes, a handbag), white background, full body, professional portrait photography."+prompt;
|
||||
// String AIRreultlogicalUrl = AITryOnEffect(prompt, toAIlogicalUrl);
|
||||
String AIRreultlogicalUrl = "try_on_result/6ecb707a-f541-437a-aef5-9544b5b18164.png";
|
||||
|
||||
tryOnEffectDto.setResultImageUrl(AIRreultlogicalUrl);
|
||||
tryOnEffectDto.setGenerationStatus("completed");
|
||||
this.saveOrUpdate(tryOnEffectDto);
|
||||
|
||||
TryOnResultVo tryOnResultVo = new TryOnResultVo();
|
||||
|
||||
@@ -65,7 +65,6 @@ public class VisitRecordServiceImpl extends ServiceImpl<VisitRecordMapper, Visit
|
||||
LambdaQueryWrapper<TryOnEffect> effectWrapper = new LambdaQueryWrapper<>();
|
||||
effectWrapper.eq(TryOnEffect::getVisitRecordId, visitRecord.getId())
|
||||
.eq(TryOnEffect::getIsFavorite, 1)
|
||||
.eq(TryOnEffect::getIsRegenerated, 0)
|
||||
.orderByDesc(TryOnEffect::getCreatedTime)
|
||||
.last("LIMIT 1");
|
||||
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
package com.aida.lanecarford.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 顾客入店VO
|
||||
*
|
||||
* <p>用于返回顾客入店登记的结果信息,包含顾客ID和入店记录ID。
|
||||
* 这些ID可用于后续的个性化服务和入店记录追踪。</p>
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "顾客入店登记结果视图对象", title = "CustomerCheckInVO")
|
||||
public class CustomerCheckInVO {
|
||||
|
||||
|
||||
/**
|
||||
* 顾客ID
|
||||
*/
|
||||
@Schema(description = "顾客唯一标识ID", example = "1001", required = true)
|
||||
private Long customerId;
|
||||
|
||||
private Long checkInId;
|
||||
|
||||
/**
|
||||
* 入店记录ID
|
||||
*/
|
||||
@Schema(description = "入店记录唯一标识ID", example = "2001", required = true)
|
||||
private Long visitRecordId;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
package com.aida.lanecarford.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 顾客信息VO
|
||||
*
|
||||
* <p>用于返回顾客的基本信息,包括姓名和邮箱。
|
||||
* 主要用于顾客列表查询接口的响应数据。</p>
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "顾客信息视图对象", title = "CustomerVO")
|
||||
public class CustomerVO {
|
||||
|
||||
/**
|
||||
* 顾客姓名
|
||||
*/
|
||||
@Schema(description = "顾客姓名", example = "张三", required = true)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 顾客邮箱
|
||||
*/
|
||||
@Schema(description = "顾客邮箱地址", example = "zhangsan@example.com", required = true)
|
||||
private String email;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user