diff --git a/src/main/java/com/ai/da/common/config/RedisConfig.java b/src/main/java/com/ai/da/common/config/RedisConfig.java index 78c13d7d..611df6b6 100644 --- a/src/main/java/com/ai/da/common/config/RedisConfig.java +++ b/src/main/java/com/ai/da/common/config/RedisConfig.java @@ -40,6 +40,7 @@ public class RedisConfig { return redisTemplate; } + // todo delete @Bean(name = "redisListTemplate") public RedisTemplate getRedisListTemplate(RedisConnectionFactory factory) { RedisTemplate redisListTemplate = new RedisTemplate<>(); diff --git a/src/main/java/com/ai/da/common/utils/RedisUtil.java b/src/main/java/com/ai/da/common/utils/RedisUtil.java index 1c17bec9..c3e71cb3 100644 --- a/src/main/java/com/ai/da/common/utils/RedisUtil.java +++ b/src/main/java/com/ai/da/common/utils/RedisUtil.java @@ -21,6 +21,7 @@ public class RedisUtil { @Resource private RedisTemplate redisTemplate; + // todo delete @Resource private RedisTemplate>> redisListTemplate; @@ -231,8 +232,11 @@ public class RedisUtil { return redisTemplate.opsForValue().increment(key, 0); } + // todo delete public final static String NO_GRADIENT = "NoGradient"; + public final static String NO_GRADIENT_MASK = "MaskConvert:NoGradient"; public final static String WITH_GRADIENT = "WithGradient"; + public final static String WITH_GRADIENT_MASK = "MaskConvert:WithGradient"; public void addToStringList(String key, List> list){ redisListTemplate.opsForValue().set(key, list); } diff --git a/src/main/java/com/ai/da/controller/DesignDetailController.java b/src/main/java/com/ai/da/controller/DesignDetailController.java index 92e28ecc..d3ab5a0f 100644 --- a/src/main/java/com/ai/da/controller/DesignDetailController.java +++ b/src/main/java/com/ai/da/controller/DesignDetailController.java @@ -81,6 +81,7 @@ public class DesignDetailController { return Response.success(designItemService.editLayersPositionAndScale(positionAndScaleVO)); } + // todo delete @ApiOperation(value = "按是否使用了渐变色对历史like进行分类") @GetMapping("/classificationByGradientColor") public Response classificationByGradientColor(){ @@ -89,18 +90,27 @@ public class DesignDetailController { } @ApiOperation(value = "mask数据兼容") - @PostMapping("/convertWithoutGradient") + @GetMapping("/convertWithoutGradient") public Response convertHistoryMaskWithoutGradient(){ designItemService.convertHistoryMaskWithoutGradient(); return Response.success("success"); } + @ApiOperation(value = "mask数据库路径更新") + @GetMapping("/updateMaskUrl") + public Response updateMaskUrl(){ + designItemService.updateMaskUrl(); + return Response.success("success"); + } + + // todo delete @ApiOperation(value = "获取历史like中包含有渐变色的design") @GetMapping("/getHistoryLikeWithGradient") public Response>> getHistoryLikeWithGradient(){ return Response.success(designItemService.getHistoryLikeWithGradient()); } + // todo delete @ApiOperation(value = "删除没有model的designItem") @GetMapping("/deleteNotFoundModelDesign") public Response deleteNotFoundModelDesign(){ @@ -108,9 +118,11 @@ public class DesignDetailController { return Response.success("success"); } + // todo delete @ApiOperation(value = "单个design 有渐变色的mask替换") @PostMapping("/designSingleWithGradient") - public Response designSingleWithGradient(@Valid @RequestBody DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO) { - return Response.success(designItemService.designSingleIncludeLayers(designSingleIncludeLayersDTO)); + public Response designSingleWithGradient(@Valid @RequestBody DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO) { + designItemService.designSingleWithGradient(designSingleIncludeLayersDTO); + return Response.success("success"); } } diff --git a/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java b/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java index 7343698b..35c79ef2 100644 --- a/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java @@ -14,10 +14,13 @@ import java.util.Map; */ public interface UserLikeMapper extends CommonMapper { + // todo delete List> getHistoryLikeWithoutGradient(); + // todo delete List> getHistoryLikeWithGradient(); + // todo delete List> getHistoryLikeWithoutModel(); } diff --git a/src/main/java/com/ai/da/service/DesignItemService.java b/src/main/java/com/ai/da/service/DesignItemService.java index e7d94d47..b9392bd2 100644 --- a/src/main/java/com/ai/da/service/DesignItemService.java +++ b/src/main/java/com/ai/da/service/DesignItemService.java @@ -61,11 +61,19 @@ public interface DesignItemService extends IService { Long getCountByUserAndTime(String startTime, String endTime, List accountIds); + // todo delete void classificationByGradientColor(); + // todo delete List> getHistoryLikeWithGradient(); void convertHistoryMaskWithoutGradient(); + void updateMaskUrl(); + + // todo delete void deleteNotFoundModelDesign(); + + // todo delete + void designSingleWithGradient(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO); } diff --git a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java index 66361706..de578c4a 100644 --- a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java @@ -23,6 +23,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.collect.Lists; import com.mysql.cj.util.StringUtils; import io.netty.util.internal.StringUtil; @@ -34,12 +36,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.io.File; import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** @@ -924,6 +928,7 @@ public class DesignItemServiceImpl extends ServiceImpl> noGradientList = new ArrayList<>(); @@ -980,8 +985,10 @@ public class DesignItemServiceImpl extends ServiceImpl> getHistoryLikeWithGradient(){ return redisUtil.getFromStringList(RedisUtil.WITH_GRADIENT); } - // todo 1、新增一个字段 用于记录历史like的design中 没有新的mask的design - // 2、获取design detail时,当其design_item_id和design_python_outfit_id在like中时,重新调用design,并更新标志字段 @Resource private UserLikeMapper userLikeMapper; @Override public void convertHistoryMaskWithoutGradient(){ + // 1、获取全部需要转换的designOutfitId + // 1、获取t_user_like表中design_item_id不为-1的所有design_item_id, design_outfit_id + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.ne("design_item_id", -1) + .ne("converted", 1) + .groupBy(Arrays.asList("design_outfit_id"," design_item_id")).select(" design_item_id", "design_outfit_id"); + + List userLikes = userLikeMapper.selectList(queryWrapper); +// List> userLikes = userLikeMapper.selectMaps(queryWrapper); + log.info("userLike 总数 :{}", userLikes.size()); + // 用于存储结果 + List pairs = new ArrayList<>(); + AtomicInteger count = new AtomicInteger(); + + // 2、查询指定designOutfitId对应的mask + userLikes.forEach(item -> { + // 存储数据,按前缀分组 + Map> groupedData = new HashMap<>(); + Long designItemId = item.getDesignItemId(); + Long designOutfitId = item.getDesignOutfitId(); +// Long designItemId = (long)item.get("design_item_id"); +// Long designOutfitId = (long)item.get("design_outfit_id"); + + List designPythonOutfitDetails = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designOutfitId); + List designItemDetails = designItemDetailService.selectByDesignItemId(designItemId); + designItemDetailService.setDesignItemDetailPriority(designItemDetails); + Map designItemPath = designItemDetails.stream() + .collect(Collectors.toMap( + DesignItemDetail::getPriority, // key: category 转为小写 + DesignItemDetail::getPath // value: path 字段 + )); + // 遍历列表,拿出每个种类的前后片 + designPythonOutfitDetails.forEach(designPythonOutfitDetail -> { + String imageCategory = designPythonOutfitDetail.getImageCategory(); + String maskPath = designPythonOutfitDetail.getMaskUrl(); + Integer priority = Math.abs(designPythonOutfitDetail.getPriority()); + + // 提取前缀和后缀 + if (imageCategory.contains("_")) { + String[] parts = imageCategory.split("_"); +// String prefix = parts[0]; + String suffix = parts[1]; + + // 初始化前缀组 + groupedData.putIfAbsent(priority, new HashMap<>()); + groupedData.get(priority).put(suffix, maskPath); + } + }); + + // 查找成对的front和back + for (Map.Entry> entry : groupedData.entrySet()) { + Map suffixes = entry.getValue(); + if (suffixes.containsKey("front") && suffixes.containsKey("back")) { + String frontMask = suffixes.get("front"); + String backMask = suffixes.get("back"); + pairs.add(new String[]{designItemPath.get(entry.getKey()),frontMask, backMask, frontMask}); + } + } + log.info("总数 count + current : {} + {} = {}", count, groupedData.size(), count.get() + groupedData.size()); + count.addAndGet(groupedData.size()); + + }); + + // 将结果写入JSON文件 + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 格式化JSON输出 + + try { + // 写入JSON文件 + objectMapper.writeValue(new File("mask_pairs.json"), pairs); + log.info("待合成mask的数量:{}",pairs.size()); + System.out.println("数据已成功写入mask_pairs.json文件"); + } catch (IOException e) { + e.printStackTrace(); + } + +/* // 查询用户like过的design 且没有使用渐变色的 design_item_id和design_python_outfit_id List> historyLikeWithoutGradient = redisUtil.getFromStringList(RedisUtil.NO_GRADIENT); @@ -1009,6 +1092,7 @@ public class DesignItemServiceImpl extends ServiceImpl> errorConvertedList = new ArrayList<>(); for (int i = 45; i < 50; i++){ List userLikeMap = historyLikeWithoutGradient.get(i); log.info("test 替换mask{}", userLikeMap.toString()); @@ -1025,6 +1109,7 @@ public class DesignItemServiceImpl extends ServiceImpl> errorConverted = redisUtil.getFromStringList(RedisUtil.ERROR_CONVERTED); + errorConverted.addAll(errorConvertedList); + redisUtil.addToStringList(RedisUtil.ERROR_CONVERTED, errorConverted); + }catch (Exception e){ log.error("mask convert error : {}", e.getMessage()); e.printStackTrace(); } long end = System.currentTimeMillis(); - log.info("convert mask 成功 {}条 执行时长:{}毫秒", count, end - start); + log.info("convert mask 成功 {}条 执行时长:{}毫秒", count, end - start);*/ } + @Transactional(rollbackFor = Exception.class) + public void updateMaskUrl(){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.ne("design_item_id", -1) + .ne("converted", 1) + .groupBy(Arrays.asList("design_outfit_id"," design_item_id")).select(" design_item_id", "design_outfit_id"); + + List userLikes = userLikeMapper.selectList(queryWrapper); + log.info("userLike 总数 :{}", userLikes.size()); + ArrayList tDesignPythonOutfitDetails = new ArrayList<>(); + + + // 2、查询指定designOutfitId对应的mask + userLikes.forEach(item -> { + Long designOutfitId = item.getDesignOutfitId(); + + // 存储以front结尾的mask路径 + Map frontMaskMap = new HashMap<>(); + HashMap backMaskIdMap = new HashMap<>(); + List designPythonOutfitDetails = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designOutfitId); + // 遍历列表,拿出每个种类的前后片 + designPythonOutfitDetails.forEach(designPythonOutfitDetail -> { + String imageCategory = designPythonOutfitDetail.getImageCategory(); + String maskUrl = designPythonOutfitDetail.getMaskUrl(); + + // 检查是否以'front'结尾 + if (imageCategory.endsWith("front")) { + String maskPath = maskUrl.replace("aida-clothing", "test" ); + String prefix = imageCategory.substring(0, imageCategory.lastIndexOf("_")); + if (backMaskIdMap.containsKey(prefix)) { + TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); + tDesignPythonOutfitDetail.setMaskUrl(maskPath); + tDesignPythonOutfitDetail.setUpdateDate(LocalDateTime.now()); + tDesignPythonOutfitDetail.setId(backMaskIdMap.get(prefix)); + tDesignPythonOutfitDetails.add(tDesignPythonOutfitDetail); + }else { + frontMaskMap.put(prefix, maskPath); + } + + TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); + tDesignPythonOutfitDetail.setMaskUrl(maskPath); + tDesignPythonOutfitDetail.setUpdateDate(LocalDateTime.now()); + tDesignPythonOutfitDetail.setId(designPythonOutfitDetail.getId()); + tDesignPythonOutfitDetails.add(tDesignPythonOutfitDetail); + } + + if (imageCategory.endsWith("back")) { + String prefix = imageCategory.substring(0, imageCategory.lastIndexOf("_")); + if (frontMaskMap.containsKey(prefix)) { + // 更新back的mask路径为front的mask路径 + String frontMaskPath = frontMaskMap.get(prefix); + + TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); + tDesignPythonOutfitDetail.setMaskUrl(frontMaskPath); + tDesignPythonOutfitDetail.setUpdateDate(LocalDateTime.now()); + tDesignPythonOutfitDetail.setId(designPythonOutfitDetail.getId()); + tDesignPythonOutfitDetails.add(tDesignPythonOutfitDetail); + }else { + backMaskIdMap.put(prefix, designPythonOutfitDetail.getId()); + } + } + }); + }); + + log.info("更新总数:{}", tDesignPythonOutfitDetails.size()); + designPythonOutfitDetailService.updateBatchById(tDesignPythonOutfitDetails); + log.info("更新完成"); + } + + // todo delete private List getUserLikeByDesignItemId(Long designItemId, Long designOutfitId){ QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("design_item_id", designItemId) - .eq("design_outfit_id", designOutfitId); + queryWrapper.eq("design_item_id", designItemId); + if (!Objects.isNull(designOutfitId)){ + queryWrapper.eq("design_outfit_id", designOutfitId); + } return userLikeMapper.selectList(queryWrapper); } + // todo delete public DesignSingleIncludeLayersDTO convertToDesignSingleIncludeLayersDTO(DesignItemDetailVO designItemDetailVO, Long userId){ DesignSingleIncludeLayersDTO resp = new DesignSingleIncludeLayersDTO(); @@ -1216,12 +1378,13 @@ public class DesignItemServiceImpl extends ServiceImpl designSingleItemDTOList) { // 6、删除designPythonOutfitDetail表中原始的图层信息(物理删除) Long designPythonOutfitId = designPythonOutfitService.getByDesignItemId(designItemId).getId(); - designPythonOutfitDetailService.deleteByDesignPythonOutfitIdPhysical(designPythonOutfitId); + designPythonOutfitDetailService.deleteByDesignPythonOutfitIdLogical(designPythonOutfitId); // 7、将新生成的图层信息存入designPythonOutfitDetail表 JSONArray layers = outfit.getJSONArray("layers"); @@ -1233,6 +1396,7 @@ public class DesignItemServiceImpl extends ServiceImpl> historyLikeWithoutModel = userLikeMapper.getHistoryLikeWithoutModel(); @@ -1258,7 +1422,38 @@ public class DesignItemServiceImpl extends ServiceImpl userLikeList = getUserLikeByDesignItemId(designItemId, null); + Long designOutfitId = userLikeList.get(0).getDesignOutfitId(); + // 如果已经替换了新的mask则直接跳过 + if (userLikeList.get(0).getConverted() == 1){ + log.info("designItemId: {}, designOutfitId : {} mask已替换", designItemId, designOutfitId); + return; + } + UserLikeGroup userLikeGroup = userLikeGroupService.getById(userLikeList.get(0).getUserLikeGroupId()); + if (userLikeGroup == null) { + log.error("在t_user_like_group表中找不到id为:{} 的记录", userLikeList.get(0).getUserLikeGroupId()); + return; + } + + // 查询design_item_id和design_python_outfit_id对应的accountId + Long accountId = userLikeGroup.getAccountId(); + + // 2、执行designSingle + designSingleIncludeLayers(designSingleIncludeLayersDTO, accountId); + + // 5、完成转换的mask, 标志字段置为1 + for (UserLike item : userLikeList ) { + UserLike userLike = new UserLike(); + userLike.setId(item.getId()); + userLike.setConverted(1); + + userLikeMapper.updateById(userLike); + } + log.info("designItemId: {}, designOutfitId : {} mask替换完成", designItemId, designOutfitId); }