Compare commits
17 Commits
dev/dev-xp
...
3df8767c47
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3df8767c47 | ||
|
|
3352bc82d9 | ||
|
|
23cb45062f | ||
| 3561cd098a | |||
|
|
dba7f09cd9 | ||
| dbf6c45ec8 | |||
|
|
adde1b007e | ||
|
|
9fb7f3128b | ||
|
|
e285b252df | ||
|
|
61faf40ca4 | ||
|
|
002e39a99f | ||
|
|
e08517cdcc | ||
|
|
8fb082d5bc | ||
|
|
e665b50bb4 | ||
| 71343010d5 | |||
| 5a4201595b | |||
| 8d48ba94f5 |
@@ -10,5 +10,9 @@ public class CommonConstants {
|
||||
|
||||
public static final int CONN_TIMEOUT = 30000; // (milliseconds)
|
||||
|
||||
public static final String OUTFIT = "Outfit";
|
||||
public static final String TRYON = "Try-on";
|
||||
public static final String GENAI = "Gen-AI";
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -78,4 +78,28 @@ public class StyleController {
|
||||
return ApiResponse.success(styleService.getOutfitResult(requestIDs));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置喜欢的风格
|
||||
*/
|
||||
@Operation(summary = "设置喜欢的outfit", description = "将指定风格设置为收藏")
|
||||
@PostMapping("/set-favorite/{styleId}")
|
||||
public ApiResponse<Void> setFavoriteStyle(
|
||||
@Parameter(description = "风格ID", required = true)
|
||||
@PathVariable Long styleId) {
|
||||
styleService.setFavoriteStyle(styleId);
|
||||
return ApiResponse.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消喜欢的风格
|
||||
*/
|
||||
@Operation(summary = "取消喜欢的outfit", description = "取消指定风格的收藏")
|
||||
@PostMapping("/cancel-favorite/{styleId}")
|
||||
public ApiResponse<Void> cancelFavoriteStyle(
|
||||
@Parameter(description = "风格ID", required = true)
|
||||
@PathVariable Long styleId) {
|
||||
styleService.cancelFavoriteStyle(styleId);
|
||||
return ApiResponse.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
package com.aida.lanecarford.controller;
|
||||
|
||||
import com.aida.lanecarford.common.ApiResponse;
|
||||
import com.aida.lanecarford.common.constant.CommonConstants;
|
||||
import com.aida.lanecarford.dto.HistoricalDTO;
|
||||
import com.aida.lanecarford.entity.Suggestion;
|
||||
import com.aida.lanecarford.entity.TryOnEffect;
|
||||
import com.aida.lanecarford.service.TryOnEffectService;
|
||||
import com.aida.lanecarford.vo.TryOnResultVo;
|
||||
import com.aida.lanecarford.vo.BaseVO;
|
||||
import com.aida.lanecarford.vo.OutfitHisVO;
|
||||
import com.aida.lanecarford.vo.TryOnResultVO;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -11,6 +17,7 @@ import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -29,29 +36,25 @@ public class TryOnEffectController {
|
||||
|
||||
@Operation(summary = "生成试穿效果", description = "根据服装,模特照片生成试穿效果,其中styleId是必选,当二次生成时,要带上相关参数,比如顾客照片")
|
||||
@PostMapping("/generate")
|
||||
public ApiResponse<TryOnResultVo> generateTryOnEffect(
|
||||
public ApiResponse<TryOnResultVO> generateTryOnEffect(
|
||||
@Parameter(description = "试穿效果请求参数", required = true)
|
||||
@Valid @RequestBody TryOnEffect tryOnEffectDto) {
|
||||
TryOnResultVo tryOnResultVo = tryOnEffectService.generateTryOnEffect(tryOnEffectDto);
|
||||
TryOnResultVO tryOnResultVo = tryOnEffectService.generateTryOnEffect(tryOnEffectDto);
|
||||
return ApiResponse.success(tryOnResultVo);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取收藏的试穿效果", description = "对应library页面点击details后的显示,参数为进店记录id")
|
||||
@GetMapping("/favorites/{visitRecordId}")
|
||||
public ApiResponse<List<TryOnResultVo>> getFavoriteTryOnEffects(
|
||||
@Parameter(description = "进店记录ID", required = true)
|
||||
@PathVariable Long visitRecordId) {
|
||||
List<TryOnResultVo> tryOnResultVos = tryOnEffectService.getFavoriteTryOnEffects(visitRecordId);
|
||||
@Operation(summary = "获取历史生成记录", description = "根据type,进店记录id,是否收藏来决定返回的数据")
|
||||
@GetMapping("/getHistoricals")
|
||||
public ApiResponse<List<? extends BaseVO>> getHistoricals(
|
||||
@Parameter(description = "服装ID", required = true)
|
||||
@RequestBody HistoricalDTO historicalDTO) {
|
||||
if (CommonConstants.OUTFIT.equals(historicalDTO.getType())){
|
||||
List<OutfitHisVO> outfitHisVOS = tryOnEffectService.getOutfitHistoricals(historicalDTO);
|
||||
return ApiResponse.success(outfitHisVOS);
|
||||
}else {
|
||||
List<TryOnResultVO> tryOnResultVos = tryOnEffectService.getTryOnHistoricals(historicalDTO);
|
||||
return ApiResponse.success(tryOnResultVos);
|
||||
}
|
||||
|
||||
@GetMapping("/style/{styleId}")
|
||||
@Operation(summary = "获取某套服装的所有生成结果", description = "对应customize your look页面点击finish后的显示")
|
||||
public ApiResponse<List<TryOnResultVo>> getTryOnEffectsByStyleId(
|
||||
@Parameter(description = "服装ID", required = true)
|
||||
@PathVariable Long styleId) {
|
||||
List<TryOnResultVo> tryOnResultVos = tryOnEffectService.getTryOnEffectsByStyleId(styleId);
|
||||
return ApiResponse.success(tryOnResultVos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,4 +80,39 @@ public class TryOnEffectController {
|
||||
tryOnEffectService.cancelFavoriteTryOnEffect(tryOnId);
|
||||
return ApiResponse.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 为生成结果添加意见和建议
|
||||
*/
|
||||
@Operation(summary = "为生成结果添加意见和建议", description = "为指定试穿效果添加意见和建议")
|
||||
@PostMapping("/add-comment")
|
||||
public ApiResponse<Void> addComment(@RequestBody Suggestion suggestion) {
|
||||
tryOnEffectService.addComment(suggestion);
|
||||
return ApiResponse.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页默认图换脸演示
|
||||
*/
|
||||
@Operation(summary = "首页点击换脸", description = "传入上传顾客照片后得到的ID")
|
||||
@PostMapping("/reFace")
|
||||
public ApiResponse<String> reFace(@Nullable @RequestParam Long customerPhotoId,
|
||||
@Nullable @RequestParam String prompt,
|
||||
@Nullable @RequestParam String tryonUrl) {
|
||||
if (customerPhotoId == null&& StringUtil.isNullOrEmpty(prompt)&& StringUtil.isNullOrEmpty(tryonUrl)){
|
||||
return ApiResponse.error("system error:Parameter null");
|
||||
}
|
||||
String result = "";
|
||||
if (StringUtil.isNullOrEmpty(prompt)){
|
||||
//换脸
|
||||
result = tryOnEffectService.reFace(customerPhotoId);
|
||||
}else {
|
||||
if (StringUtil.isNullOrEmpty(tryonUrl)){
|
||||
return ApiResponse.error("system error:Parameter null");
|
||||
}
|
||||
//根据提示词修改图像
|
||||
result = tryOnEffectService.generateUrl(prompt,tryonUrl);
|
||||
}
|
||||
return ApiResponse.success("操作成功",result);
|
||||
}
|
||||
}
|
||||
17
src/main/java/com/aida/lanecarford/dto/HistoricalDTO.java
Normal file
17
src/main/java/com/aida/lanecarford/dto/HistoricalDTO.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.aida.lanecarford.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class HistoricalDTO {
|
||||
@Schema(description = "进店记录ID",example = "1")
|
||||
private Long visitRecordId;
|
||||
|
||||
@Schema(description = "类型",example = "Outfit , Try-on , Gen-AI")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "是否是收藏",example = "true")
|
||||
private Boolean isLibrary;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.aida.lanecarford.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -76,4 +77,11 @@ public class Style extends BaseEntity {
|
||||
private String errorMessage;
|
||||
|
||||
// 注意:createdTime、updatedTime 字段已在 BaseEntity 中定义
|
||||
|
||||
/**
|
||||
* 是否喜欢(0-否,1-是)
|
||||
*/
|
||||
@Schema(description = "是否喜欢(0-否,1-是)", example = "1", required = false)
|
||||
@TableField("is_favorite")
|
||||
private Integer isFavorite;
|
||||
}
|
||||
53
src/main/java/com/aida/lanecarford/entity/Suggestion.java
Normal file
53
src/main/java/com/aida/lanecarford/entity/Suggestion.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.aida.lanecarford.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 意见建议实体类
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @since 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("suggestions")
|
||||
public class Suggestion extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 顾客ID
|
||||
*/
|
||||
@Schema(description = "顾客ID", example = "1", required = true)
|
||||
@TableField("customer_id")
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 进店记录ID
|
||||
*/
|
||||
@Schema(description = "进店记录ID", example = "1", required = true)
|
||||
@TableField("visit_record_id")
|
||||
private Long visitRecordId;
|
||||
|
||||
/**
|
||||
* 试穿效果ID
|
||||
*/
|
||||
@Schema(description = "试穿效果ID", example = "1", required = true)
|
||||
@TableField("try_on_effects_id")
|
||||
private Long tryOnEffectsId;
|
||||
|
||||
/**
|
||||
* 意见建议内容
|
||||
*/
|
||||
@Schema(description = "意见建议内容", example = "这件衣服颜色不太合适,建议换成浅色系", required = true)
|
||||
@TableField("suggestion")
|
||||
private String suggestion;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.aida.lanecarford.mapper;
|
||||
|
||||
import com.aida.lanecarford.entity.Suggestion;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 意见建议Mapper接口
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @since 2024-01-01
|
||||
*/
|
||||
@Mapper
|
||||
public interface SuggestionMapper extends BaseMapper<Suggestion> {
|
||||
|
||||
}
|
||||
@@ -19,4 +19,16 @@ public interface StyleService extends IService<Style> {
|
||||
|
||||
List<OutfitResultVO> getOutfitResult(List<String> requestIDs);
|
||||
|
||||
/**
|
||||
* 设置风格为收藏
|
||||
* @param styleId 风格ID
|
||||
*/
|
||||
void setFavoriteStyle(Long styleId);
|
||||
|
||||
/**
|
||||
* 取消风格的收藏
|
||||
* @param styleId 风格ID
|
||||
*/
|
||||
void cancelFavoriteStyle(Long styleId);
|
||||
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.aida.lanecarford.service;
|
||||
|
||||
import com.aida.lanecarford.dto.HistoricalDTO;
|
||||
import com.aida.lanecarford.entity.Suggestion;
|
||||
import com.aida.lanecarford.entity.TryOnEffect;
|
||||
import com.aida.lanecarford.vo.TryOnResultVo;
|
||||
import com.aida.lanecarford.vo.OutfitHisVO;
|
||||
import com.aida.lanecarford.vo.TryOnResultVO;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@@ -15,9 +18,9 @@ import java.util.List;
|
||||
*/
|
||||
public interface TryOnEffectService extends IService<TryOnEffect> {
|
||||
|
||||
TryOnResultVo generateTryOnEffect(@Valid TryOnEffect tryOnEffectDto);
|
||||
TryOnResultVO generateTryOnEffect(@Valid TryOnEffect tryOnEffectDto);
|
||||
|
||||
List<TryOnResultVo> getFavoriteTryOnEffects(Long visitRecordId);
|
||||
List<TryOnResultVO> getFavoriteTryOnEffects(Long visitRecordId);
|
||||
|
||||
/**
|
||||
* 设置试穿效果为收藏
|
||||
@@ -31,5 +34,20 @@ public interface TryOnEffectService extends IService<TryOnEffect> {
|
||||
*/
|
||||
void cancelFavoriteTryOnEffect(Long tryOnId);
|
||||
|
||||
List<TryOnResultVo> getTryOnEffectsByStyleId(Long styleId);
|
||||
List<TryOnResultVO> getTryOnEffectsByStyleId(Long styleId);
|
||||
|
||||
/**
|
||||
* 添加意见建议
|
||||
* @param suggestion 意见建议实体
|
||||
* @return 是否添加成功
|
||||
*/
|
||||
boolean addComment(Suggestion suggestion);
|
||||
|
||||
String reFace(Long customerPhotoId);
|
||||
|
||||
String generateUrl(String prompt, String tryonUrl);
|
||||
|
||||
List<TryOnResultVO> getTryOnHistoricals(HistoricalDTO historicalDTO);
|
||||
|
||||
List<OutfitHisVO> getOutfitHistoricals(HistoricalDTO historicalDTO);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.aida.lanecarford.common.constant.CommonConstants;
|
||||
import com.aida.lanecarford.common.constant.RedisURIConstants;
|
||||
import com.aida.lanecarford.common.enums.StatusEnum;
|
||||
import com.aida.lanecarford.common.enums.StylistPathEnum;
|
||||
import com.aida.lanecarford.common.response.ResultEnum;
|
||||
import com.aida.lanecarford.dto.OutfitCallbackDTO;
|
||||
import com.aida.lanecarford.dto.RequestOutfitDTO;
|
||||
import com.aida.lanecarford.entity.OutfitRequest;
|
||||
@@ -206,4 +207,38 @@ public class StyleServiceImpl extends ServiceImpl<StyleMapper, Style> implements
|
||||
return resultVOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavoriteStyle(Long styleId) {
|
||||
if (styleId == null) {
|
||||
throw new BusinessException("Style ID is required", "风格ID不能为空", ResultEnum.PARAMETER_ERROR.getCode());
|
||||
}
|
||||
|
||||
Style style = this.getById(styleId);
|
||||
if (style == null) {
|
||||
throw new BusinessException("Style not found", "风格不存在", ResultEnum.FAIL.getCode());
|
||||
}
|
||||
|
||||
// 设置为收藏
|
||||
style.setIsFavorite(1);
|
||||
this.updateById(style);
|
||||
log.info("风格ID: {} 已设置为收藏", styleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelFavoriteStyle(Long styleId) {
|
||||
if (styleId == null) {
|
||||
throw new BusinessException("Style ID is required", "风格ID不能为空", ResultEnum.PARAMETER_ERROR.getCode());
|
||||
}
|
||||
|
||||
Style style = this.getById(styleId);
|
||||
if (style == null) {
|
||||
throw new BusinessException("Style not found", "风格不存在", ResultEnum.FAIL.getCode());
|
||||
}
|
||||
|
||||
// 取消收藏
|
||||
style.setIsFavorite(0);
|
||||
this.updateById(style);
|
||||
log.info("风格ID: {} 已取消收藏", styleId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,15 +6,19 @@ import com.aida.lanecarford.config.MinioConfig;
|
||||
import com.aida.lanecarford.config.FaceSwapConfig;
|
||||
import com.aida.lanecarford.common.response.ResultEnum;
|
||||
import com.aida.lanecarford.common.constant.MinioFileConstants;
|
||||
import com.aida.lanecarford.dto.HistoricalDTO;
|
||||
import com.aida.lanecarford.entity.*;
|
||||
import com.aida.lanecarford.exception.BusinessException;
|
||||
import com.aida.lanecarford.mapper.CustomerMapper;
|
||||
import com.aida.lanecarford.mapper.OutfitRequestMapper;
|
||||
import com.aida.lanecarford.mapper.SuggestionMapper;
|
||||
import com.aida.lanecarford.mapper.TryOnEffectMapper;
|
||||
import com.aida.lanecarford.service.*;
|
||||
import com.aida.lanecarford.entity.Suggestion;
|
||||
import com.aida.lanecarford.util.MinioUtil;
|
||||
import com.aida.lanecarford.util.StringListConverter;
|
||||
import com.aida.lanecarford.vo.TryOnResultVo;
|
||||
import com.aida.lanecarford.vo.OutfitHisVO;
|
||||
import com.aida.lanecarford.vo.TryOnResultVO;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
@@ -53,10 +57,11 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
private final MinioUtil minioUtil;
|
||||
private final MinioConfig minioConfig;
|
||||
private final FaceSwapConfig faceSwapConfig;
|
||||
private final SuggestionMapper suggestionMapper;
|
||||
private final OutfitRequestMapper outfitRequestMapper;
|
||||
|
||||
@Override
|
||||
public TryOnResultVo generateTryOnEffect(TryOnEffect tryOnEffectDto) {
|
||||
public TryOnResultVO generateTryOnEffect(TryOnEffect tryOnEffectDto) {
|
||||
Integer isRegenerated = tryOnEffectDto.getIsRegenerated();
|
||||
String toAIlogicalUrl = null;
|
||||
String prompt = null;
|
||||
@@ -115,7 +120,7 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
prompt = "A full-body, photorealistic professional studio shot of a **young " + outfitRequest.getGender() + "**, mid-20s, with **clear facial features and a confident expression**. The model is centered in the frame.They are **standing in a direct, static, full-view pose** on a **clean, light white backdrop** **The entire figure, from head to toe, should be in frame and occupy approximately 80% of the vertical space.**.\n" +
|
||||
prompt = "A full-body, photorealistic professional studio shot of a **young " + outfitRequest.getGender() + "**, mid-20s, with **clear facial features and a confident expression**. The model is centered in the frame.They are **standing in a direct, static, full-view pose** on a **clean, pure white background** **The entire figure, from head to toe, should be in frame and occupy approximately 80% of the vertical space.**.\n" +
|
||||
"\n" +
|
||||
"**CRITICAL COMPOSITION INSTRUCTION:**\n" +
|
||||
"Generate a single, seamless image of the model with a complete and fully visible head,**wearing ALL distinct items("+sb.toString()+")** from the uploaded image. **ALL items MUST be visible and correctly worn in the final outfit.**" +
|
||||
@@ -137,8 +142,8 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
tryOnEffectDto.setGenerationStatus("completed");
|
||||
this.saveOrUpdate(tryOnEffectDto);
|
||||
|
||||
TryOnResultVo tryOnResultVo = new TryOnResultVo();
|
||||
tryOnResultVo.setTryOnId(tryOnEffectDto.getId());
|
||||
TryOnResultVO tryOnResultVo = new TryOnResultVO();
|
||||
tryOnResultVo.setId(tryOnEffectDto.getId());
|
||||
|
||||
tryOnResultVo.setTryOnUrl(minioUtil.convertToPresignedUrl(aiRreultlogicalUrl, CommonConstants.MINIO_PATH_TIMEOUT));
|
||||
|
||||
@@ -147,15 +152,15 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
|
||||
//library页面点击details后的显示
|
||||
@Override
|
||||
public List<TryOnResultVo> getFavoriteTryOnEffects(Long visitRecordId) {
|
||||
public List<TryOnResultVO> getFavoriteTryOnEffects(Long visitRecordId) {
|
||||
List<TryOnEffect> tryOnEffects = this.list(new LambdaQueryWrapper<TryOnEffect>()
|
||||
.eq(TryOnEffect::getVisitRecordId, visitRecordId)
|
||||
.eq(TryOnEffect::getIsFavorite, 1)
|
||||
.orderByAsc(TryOnEffect::getCreatedTime));
|
||||
List<TryOnResultVo> tryOnResultVos = new ArrayList<>();
|
||||
.orderByDesc(TryOnEffect::getCreatedTime));
|
||||
List<TryOnResultVO> tryOnResultVos = new ArrayList<>();
|
||||
for (TryOnEffect tryOnEffect : tryOnEffects) {
|
||||
TryOnResultVo tryOnResultVo = new TryOnResultVo();
|
||||
tryOnResultVo.setTryOnId(tryOnEffect.getId());
|
||||
TryOnResultVO tryOnResultVo = new TryOnResultVO();
|
||||
tryOnResultVo.setId(tryOnEffect.getId());
|
||||
// 使用新的API获取预签名URL,数据库存储的是逻辑URL
|
||||
tryOnResultVo.setTryOnUrl(minioUtil.convertToPresignedUrl(
|
||||
tryOnEffect.getResultImageUrl(),
|
||||
@@ -179,16 +184,155 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
return tryOnResultVos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加意见建议
|
||||
* @param suggestion 意见建议实体
|
||||
* @return 是否添加成功
|
||||
*/
|
||||
@Override
|
||||
public boolean addComment(Suggestion suggestion) {
|
||||
try {
|
||||
// 保存意见建议
|
||||
int result = suggestionMapper.insert(suggestion);
|
||||
|
||||
if (result > 0) {
|
||||
log.info("意见建议添加成功 - id: {}", suggestion.getId());
|
||||
return true;
|
||||
} else {
|
||||
log.error("意见建议添加失败");
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("添加意见建议时发生异常: {}", e.getMessage(), e);
|
||||
throw new BusinessException("Add suggestion failed", "添加意见建议失败", ResultEnum.ERROR.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String reFace(Long customerPhotoId) {
|
||||
|
||||
List<String> imageUrls = new ArrayList<>();
|
||||
//默认展示图片
|
||||
imageUrls.add("lanecarford/try_on_result/default.jpg");
|
||||
|
||||
if (customerPhotoId != null) {
|
||||
//根据id查到对应customerurl
|
||||
CustomerPhoto customerPhoto = customerPhotoService.getById(customerPhotoId);
|
||||
String customerPhotoUrl = customerPhoto.getPhotoUrl();
|
||||
if (customerPhotoUrl != null && !customerPhotoUrl.trim().isEmpty()) {
|
||||
imageUrls.add(customerPhotoUrl);
|
||||
}
|
||||
}
|
||||
String aiRreultlogicalUrl = callFaceSwapAPI(imageUrls);
|
||||
String presignedUrl = minioUtil.getPresignedUrl(aiRreultlogicalUrl, CommonConstants.MINIO_PATH_TIMEOUT);
|
||||
return presignedUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateUrl(String prompt, String tryonUrl) {
|
||||
int startIndex = tryonUrl.indexOf("lanecarford");
|
||||
String aiRreultlogicalUrl = "";
|
||||
if (startIndex != -1) {
|
||||
// 支持jpg和png格式的图片识别
|
||||
int jpgEndIndex = tryonUrl.indexOf(".jpg");
|
||||
int pngEndIndex = tryonUrl.indexOf(".png");
|
||||
|
||||
int endIndex = -1;
|
||||
|
||||
if (jpgEndIndex != -1 && (pngEndIndex == -1 || jpgEndIndex < pngEndIndex)) {
|
||||
// 找到jpg格式
|
||||
endIndex = jpgEndIndex + ".jpg".length();
|
||||
} else if (pngEndIndex != -1 && (jpgEndIndex == -1 || pngEndIndex < jpgEndIndex)) {
|
||||
// 找到png格式
|
||||
endIndex = pngEndIndex + ".png".length();
|
||||
}
|
||||
|
||||
if (endIndex != -1) {
|
||||
String resultString = tryonUrl.substring(startIndex, endIndex);
|
||||
aiRreultlogicalUrl = AITryOnEffect(prompt, Arrays.asList(resultString));
|
||||
} else {
|
||||
log.error("未找到jpg或png格式的图片,无法识别图片类型");
|
||||
}
|
||||
}
|
||||
return minioUtil.convertToPresignedUrl(aiRreultlogicalUrl, CommonConstants.MINIO_PATH_TIMEOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TryOnResultVO> getTryOnHistoricals(HistoricalDTO historicalDTO) {
|
||||
LambdaQueryWrapper<TryOnEffect> tryOnEffectLambdaQueryWrapper = new LambdaQueryWrapper<TryOnEffect>()
|
||||
.orderByDesc(TryOnEffect::getCreatedTime);
|
||||
if (historicalDTO.getVisitRecordId() != null){
|
||||
tryOnEffectLambdaQueryWrapper.eq(TryOnEffect::getVisitRecordId, historicalDTO.getVisitRecordId());
|
||||
}
|
||||
if (historicalDTO.getIsLibrary() != null||historicalDTO.getIsLibrary()){
|
||||
tryOnEffectLambdaQueryWrapper.eq(TryOnEffect::getIsFavorite,1);
|
||||
}
|
||||
if (CommonConstants.TRYON.equals(historicalDTO.getType())){
|
||||
tryOnEffectLambdaQueryWrapper.eq(TryOnEffect::getIsRegenerated, 0);
|
||||
}else if (CommonConstants.GENAI.equals(historicalDTO.getType())){
|
||||
tryOnEffectLambdaQueryWrapper.eq(TryOnEffect::getIsRegenerated, 1);
|
||||
}
|
||||
List<TryOnEffect> tryOnEffects = this.list(tryOnEffectLambdaQueryWrapper);
|
||||
List<TryOnResultVO> tryOnResultVos = new ArrayList<>();
|
||||
for (TryOnEffect tryOnEffect : tryOnEffects) {
|
||||
TryOnResultVO tryOnResultVo = new TryOnResultVO();
|
||||
tryOnResultVo.setId(tryOnEffect.getId());
|
||||
tryOnResultVo.setTryOnUrl(minioUtil.convertToPresignedUrl(
|
||||
tryOnEffect.getResultImageUrl(),
|
||||
CommonConstants.MINIO_PATH_TIMEOUT
|
||||
));
|
||||
// 如果是原始效果,则获取对应的style图片
|
||||
if (tryOnEffect.getIsRegenerated() == 0) {
|
||||
LambdaQueryWrapper<Style> styleLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
styleLambdaQueryWrapper.eq(Style::getId, tryOnEffect.getStyleId()).select(Style::getStyleImageUrl);
|
||||
Style style = styleService.getOne(styleLambdaQueryWrapper);
|
||||
tryOnResultVo.setStyleUrl(minioUtil.convertToPresignedUrl(
|
||||
style.getStyleImageUrl(),
|
||||
CommonConstants.MINIO_PATH_TIMEOUT
|
||||
));
|
||||
}
|
||||
|
||||
tryOnResultVo.setIsRegenerated(tryOnEffect.getIsRegenerated());
|
||||
tryOnResultVo.setIsFavorite(tryOnEffect.getIsFavorite());
|
||||
tryOnResultVos.add(tryOnResultVo);
|
||||
}
|
||||
return tryOnResultVos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutfitHisVO> getOutfitHistoricals(HistoricalDTO historicalDTO) {
|
||||
LambdaQueryWrapper<Style> styleLambdaQueryWrapper = new LambdaQueryWrapper<Style>().orderByDesc(Style::getCreatedTime);
|
||||
if (historicalDTO.getVisitRecordId() != null){
|
||||
styleLambdaQueryWrapper.eq(Style::getVisitRecordId, historicalDTO.getVisitRecordId());
|
||||
}
|
||||
if (historicalDTO.getIsLibrary() != null||historicalDTO.getIsLibrary()){
|
||||
styleLambdaQueryWrapper.eq(Style::getIsFavorite, 1);
|
||||
}
|
||||
List<Style> styles = styleService.list(styleLambdaQueryWrapper);
|
||||
List<OutfitHisVO> outfitHisVos = new ArrayList<>();
|
||||
for (Style style : styles) {
|
||||
OutfitHisVO outfitHisVo = new OutfitHisVO();
|
||||
outfitHisVo.setId(style.getId());
|
||||
outfitHisVo.setUrl(minioUtil.convertToPresignedUrl(
|
||||
style.getStyleImageUrl(),
|
||||
CommonConstants.MINIO_PATH_TIMEOUT
|
||||
));
|
||||
outfitHisVo.setIsFavorite(style.getIsFavorite());
|
||||
outfitHisVos.add(outfitHisVo);
|
||||
}
|
||||
return outfitHisVos;
|
||||
}
|
||||
|
||||
//目前用于customize your look页面点击finish后的显示
|
||||
@Override
|
||||
public List<TryOnResultVo> getTryOnEffectsByStyleId(Long styleId) {
|
||||
public List<TryOnResultVO> getTryOnEffectsByStyleId(Long styleId) {
|
||||
List<TryOnEffect> tryOnEffects = this.list(new LambdaQueryWrapper<TryOnEffect>()
|
||||
.eq(TryOnEffect::getStyleId, styleId)
|
||||
.orderByAsc(TryOnEffect::getCreatedTime));
|
||||
List<TryOnResultVo> tryOnResultVos = new ArrayList<>();
|
||||
.orderByDesc(TryOnEffect::getCreatedTime));
|
||||
List<TryOnResultVO> tryOnResultVos = new ArrayList<>();
|
||||
for (TryOnEffect tryOnEffect : tryOnEffects) {
|
||||
TryOnResultVo tryOnResultVo = new TryOnResultVo();
|
||||
tryOnResultVo.setTryOnId(tryOnEffect.getId());
|
||||
TryOnResultVO tryOnResultVo = new TryOnResultVO();
|
||||
tryOnResultVo.setId(tryOnEffect.getId());
|
||||
// 使用新的API获取预签名URL,数据库存储的是逻辑URL
|
||||
tryOnResultVo.setTryOnUrl(minioUtil.convertToPresignedUrl(
|
||||
tryOnEffect.getResultImageUrl(),
|
||||
@@ -326,7 +470,7 @@ public class TryOnEffectServiceImpl extends ServiceImpl<TryOnEffectMapper, TryOn
|
||||
return processGoogleAPIResponse(response);
|
||||
} catch (Exception e) {
|
||||
log.error("调用Google API失败: {}", e.getMessage(), e);
|
||||
throw new BusinessException("Google API call failed", "Google API调用失败", ResultEnum.ERROR.getCode());
|
||||
throw new BusinessException("Generation timed out. Please try again later.", "生成超时,请稍后再试", ResultEnum.ERROR.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
src/main/java/com/aida/lanecarford/vo/BaseVO.java
Normal file
15
src/main/java/com/aida/lanecarford/vo/BaseVO.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.aida.lanecarford.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class BaseVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 10007L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
}
|
||||
11
src/main/java/com/aida/lanecarford/vo/OutfitHisVO.java
Normal file
11
src/main/java/com/aida/lanecarford/vo/OutfitHisVO.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.aida.lanecarford.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class OutfitHisVO extends BaseVO {
|
||||
|
||||
private String url;
|
||||
|
||||
private Integer isFavorite;
|
||||
}
|
||||
@@ -3,9 +3,7 @@ package com.aida.lanecarford.vo;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TryOnResultVo {
|
||||
|
||||
private Long tryOnId;
|
||||
public class TryOnResultVO extends BaseVO {
|
||||
|
||||
private String tryOnUrl;
|
||||
|
||||
@@ -71,6 +71,7 @@ CREATE TABLE `styles` (
|
||||
`style_image_url` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '风格图片URL',
|
||||
`python_request_id` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Python请求ID',
|
||||
`generation_status` tinyint DEFAULT '0' COMMENT '生成状态(0-处理中,1-已完成,2-失败)',
|
||||
`is_favorite` tinyint DEFAULT '0' COMMENT '是否喜欢(0-否,1-是)',
|
||||
`items` json DEFAULT NULL COMMENT '单品唯一标识',
|
||||
`error_message` text COLLATE utf8mb4_unicode_ci COMMENT '错误信息',
|
||||
`created_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
@@ -166,4 +167,19 @@ CREATE TABLE `outfit_request` (
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='穿搭请求表';
|
||||
|
||||
-- 9. 意见建议表
|
||||
CREATE TABLE `suggestions` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '意见建议ID',
|
||||
`customer_id` bigint NOT NULL COMMENT '顾客ID',
|
||||
`visit_record_id` bigint NOT NULL COMMENT '进店记录ID',
|
||||
`try_on_effects_id` bigint NOT NULL COMMENT '试穿效果ID',
|
||||
`suggestion` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '意见建议内容',
|
||||
`created_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` tinyint DEFAULT '0' COMMENT '逻辑删除标志(0-未删除,1-已删除)',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='意见建议表';
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user