diff --git a/src/main/java/com/ai/da/controller/DesignDetailController.java b/src/main/java/com/ai/da/controller/DesignDetailController.java index c2368a0c..1e06e825 100644 --- a/src/main/java/com/ai/da/controller/DesignDetailController.java +++ b/src/main/java/com/ai/da/controller/DesignDetailController.java @@ -5,6 +5,7 @@ import com.ai.da.model.dto.*; import com.ai.da.model.vo.*; import com.ai.da.service.DesignItemService; import com.ai.da.service.DesignService; +import com.ai.da.service.UserLikeService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -14,6 +15,8 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; import java.io.IOException; +import java.util.List; +import java.util.Map; @Api(tags = "design Detail模块") @@ -77,4 +80,19 @@ public class DesignDetailController { public Response editPositionAndScale(@Valid @RequestBody EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException { return Response.success(designItemService.editLayersPositionAndScale(positionAndScaleVO)); } + + @ApiOperation(value = "mask数据兼容") + @PostMapping("/convertWithoutGradient") + public Response convertHistoryMaskWithoutGradient(){ + designItemService.convertHistoryMaskWithoutGradient(); + return Response.success("success"); + } + + @Resource + private UserLikeService userLikeService; + @ApiOperation(value = "获取历史like中包含有渐变色的design") + @PostMapping("/getHistoryLikeWithGradient") + public Response>> getHistoryLikeWithGradient(){ + return Response.success(userLikeService.getHistoryLikeWithGradient()); + } } 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 1d5e4761..5632606a 100644 --- a/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java @@ -3,6 +3,9 @@ package com.ai.da.mapper.primary; import com.ai.da.common.config.mybatis.plus.CommonMapper; import com.ai.da.mapper.primary.entity.UserLike; +import java.util.List; +import java.util.Map; + /** * Mapper 接口 * @@ -11,4 +14,8 @@ import com.ai.da.mapper.primary.entity.UserLike; */ public interface UserLikeMapper extends CommonMapper { + List> getHistoryLikeWithoutGradient(); + + List> getHistoryLikeWithGradient(); + } diff --git a/src/main/java/com/ai/da/mapper/primary/entity/UserLike.java b/src/main/java/com/ai/da/mapper/primary/entity/UserLike.java index 61a4deee..c14e7ff6 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/UserLike.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/UserLike.java @@ -59,4 +59,9 @@ public class UserLike implements Serializable { * 更新时间 */ private Date updateDate; + + /** + * design对应的mask是否已替换为最新的 + */ + private Integer converted; } diff --git a/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java b/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java index ea6925b1..c3ffd2e7 100644 --- a/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java +++ b/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java @@ -59,4 +59,10 @@ public class DesignSingleItemDTO implements Serializable { @ApiModelProperty("衣服上的装饰") private DesignSinglePrintDTO trims; + @ApiModelProperty("标注后的mask 的base64") + private String maskUrl; + + @ApiModelProperty("mask 的minio地址") + private String maskMinioUrl; + } diff --git a/src/main/java/com/ai/da/python/PythonService.java b/src/main/java/com/ai/da/python/PythonService.java index edb5c573..f7929504 100644 --- a/src/main/java/com/ai/da/python/PythonService.java +++ b/src/main/java/com/ai/da/python/PythonService.java @@ -2662,7 +2662,8 @@ public class PythonService { designSingleItem.getScale(), designSingleItem.getPriority(), minioPath, - gradientString)); + gradientString, + designSingleItem.getMaskUrl())); }); @@ -2684,7 +2685,7 @@ public class PythonService { DesignPythonItemPrint printOverall = new DesignPythonItemPrint(); printToPython.setSingle(printSingle); printToPython.setOverall(printOverall); - if (printObject.isEmpty()){ + if (Objects.isNull(printObject) || printObject.isEmpty()){ return printToPython; } diff --git a/src/main/java/com/ai/da/python/vo/DesignPythonItem.java b/src/main/java/com/ai/da/python/vo/DesignPythonItem.java index aad33618..92e3892b 100644 --- a/src/main/java/com/ai/da/python/vo/DesignPythonItem.java +++ b/src/main/java/com/ai/da/python/vo/DesignPythonItem.java @@ -82,6 +82,10 @@ public class DesignPythonItem { * 图层优先级 */ private Integer priority; + /** + * 标注过的mask + */ + private String seg_mask_url; public static List OUTWEAR_DRESS_BLOUSE = Arrays.asList(CollectionLevel2TypeEnum.OUTWEAR.getRealName(), CollectionLevel2TypeEnum.DRESS.getRealName(), CollectionLevel2TypeEnum.BLOUSE.getRealName()); @@ -134,6 +138,24 @@ public class DesignPythonItem { this.gradientString = gradientString; } + public DesignPythonItem(String type, String path, String color, PrintToPython print, Long businessId, + Long image_id, List offset, Float[] resize_scale, Integer priority, String gradient, + String gradientString, String seg_mask_url) { + this.type = type; + this.path = path; + this.color = color; + this.print = print; +// this.icon = icon; + this.businessId = businessId; + this.image_id = image_id; + this.offset = offset; + this.resize_scale = resize_scale; + this.priority = priority; + this.gradient = gradient; + this.gradientString = gradientString; + this.seg_mask_url = seg_mask_url; + } + public DesignPythonItem(String type, String path, String color, PrintToPython print, String icon, Long businessId, Long image_id) { this.type = type; this.path = path; diff --git a/src/main/java/com/ai/da/service/DesignItemService.java b/src/main/java/com/ai/da/service/DesignItemService.java index 788fd5b1..5a0935f6 100644 --- a/src/main/java/com/ai/da/service/DesignItemService.java +++ b/src/main/java/com/ai/da/service/DesignItemService.java @@ -60,4 +60,6 @@ public interface DesignItemService extends IService { List selectDesignIdById(List designItemIdList); Long getCountByUserAndTime(String startTime, String endTime, List accountIds); + + void convertHistoryMaskWithoutGradient(); } diff --git a/src/main/java/com/ai/da/service/UserLikeService.java b/src/main/java/com/ai/da/service/UserLikeService.java index b04d64da..0be8c536 100644 --- a/src/main/java/com/ai/da/service/UserLikeService.java +++ b/src/main/java/com/ai/da/service/UserLikeService.java @@ -5,6 +5,7 @@ import com.ai.da.model.vo.UserLikeVO; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; +import java.util.Map; /** * 服务类 @@ -25,4 +26,6 @@ public interface UserLikeService extends IService { void updateDate(Long designItemId,String timeZone); List getUserLikeList(Long id); + + List> getHistoryLikeWithGradient(); } 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 52d589d9..99f0b6be 100644 --- a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java @@ -10,6 +10,7 @@ import com.ai.da.common.enums.SingleOverallEnum; import com.ai.da.common.enums.SysFileLevel2TypeEnum; import com.ai.da.common.utils.*; import com.ai.da.mapper.primary.DesignItemMapper; +import com.ai.da.mapper.primary.UserLikeMapper; import com.ai.da.mapper.primary.entity.*; import com.ai.da.model.dto.*; import com.ai.da.model.enums.ModelType; @@ -82,6 +83,9 @@ public class DesignItemServiceImpl extends ServiceImpl " + JSONObject.toJSONString(clone)); @@ -488,6 +497,9 @@ public class DesignItemServiceImpl extends ServiceImpl { + // 如果sketch截图不为空,则将该截图上传,并替换path + if (!StringUtil.isNullOrEmpty(item.getMaskUrl())){ + // 由于前端不好处理这块,所以,当mask没有做任何修改的时候,仍然会传原始mask的minio地址 + if (!item.getMaskUrl().startsWith("data:image") && item.getMaskUrl().startsWith("https://")){ + // 当没有修改mask时,还是用之前的mask地址 + item.setMaskUrl(item.getMaskMinioUrl()); + }else { + // 将原图地址作为修改后的图片地址,放在不同的桶 + String path = minioUtil.base64UploadToPath(item.getMaskUrl(), clothingBucket, "labelingMask/" + UUID.randomUUID()); + if (StringUtil.isNullOrEmpty(path)){ + log.error("标注的mask图片上传失败"); + throw new BusinessException("image.modify.failed"); + } + item.setMaskUrl(path); + } + } + }); + } + @Override public Map setTypeAndUndividedLayer(JSONArray layers){ HashMap categoryAndLayer = new HashMap<>(); @@ -875,4 +908,229 @@ public class DesignItemServiceImpl extends ServiceImpl> historyLikeWithoutGradient = userLikeMapper.getHistoryLikeWithoutGradient(); + log.info("historyLikeWithoutGradient total count : {}", historyLikeWithoutGradient.size()); + // 遍历list + // 先试一下,刷新10条,需要花费的时间 + + /*Map userLikeMap = historyLikeWithoutGradient.get(0); + log.info("test 替换mask" + userLikeMap.toString()); + + // 查每个design_item_id和design_python_outfit_id的detail + DesignItemDetailVO detail = designService.detail(userLikeMap.get("design_outfit_id"), userLikeMap.get("design_item_id")); + Long accountId = userLikeMap.get("account_id"); + // 组装参数 + DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO = convertToDesignSingleIncludeLayersDTO(detail, accountId); + if (Objects.isNull(designSingleIncludeLayersDTO)){ + throw new BusinessException("cannot find model"); + } + // 调用design single + designSingleIncludeLayers(designSingleIncludeLayersDTO, accountId); + + // 标志字段置为1 + UserLike userLike = new UserLike(); + userLike.setId(userLikeMap.get("id")); + userLike.setConverted(1); + + userLikeMapper.updateById(userLike);*/ + long start = System.currentTimeMillis(); + for (int i = 0; i < 10; i++){ + try { + Map userLikeMap = historyLikeWithoutGradient.get(0); + log.info("test 替换mask" + userLikeMap.toString()); + Long designItemId = userLikeMap.get("design_item_id"); + Long designOutfitId = userLikeMap.get("design_outfit_id"); + + // 查每个design_item_id和design_python_outfit_id的detail + DesignItemDetailVO detail = designService.detail(designOutfitId, designItemId); + Long accountId = userLikeMap.get("account_id"); + // 组装参数 + DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO = convertToDesignSingleIncludeLayersDTO(detail, accountId); + if (Objects.isNull(designSingleIncludeLayersDTO)){ + throw new BusinessException("cannot find model. designItemId: " + designItemId + "designOutfitId : " + designOutfitId ); + } + // 调用design single + designSingleIncludeLayers(designSingleIncludeLayersDTO, accountId); + + // 标志字段置为1 + UserLike userLike = new UserLike(); + userLike.setId(userLikeMap.get("id")); + userLike.setConverted(1); + + userLikeMapper.updateById(userLike); + }catch (BusinessException e){ + log.error("mask convert error : {}", e.getMessage()); + } + } + long end = System.currentTimeMillis(); + + log.info("convert mask ,10条 执行时长:" + (end - start) + "毫秒"); + + + } + + + public DesignSingleIncludeLayersDTO convertToDesignSingleIncludeLayersDTO(DesignItemDetailVO designItemDetailVO, Long userId){ + DesignSingleIncludeLayersDTO resp = new DesignSingleIncludeLayersDTO(); + + Long designItemId = designItemDetailVO.getDesignItemId(); + String gender ; + String modelPath = designItemDetailVO.getOthers().get(0).getMinIOPath(); + List modelSysFile = sysFileService.getByUrlList(Collections.singletonList(modelPath)); + if (modelSysFile.isEmpty()){ + log.error("cannot find model 【{}】 in t_sys_file ", modelPath); + return null; + }else { + gender = modelSysFile.get(0).getLevel2Type(); + } + + resp.setDesignItemId(designItemId); + resp.setGender(gender); + resp.setIsPreview(Boolean.FALSE); + resp.setProcessId(String.valueOf(userId)); + resp.setTimeZone("Etc/GMT-8"); + List designSingleItemDTOS = new ArrayList<>(); + resp.setDesignSingleItemDTOList(designSingleItemDTOS); + + designItemDetailVO.getClothes().forEach(cloth -> { + DesignSingleItemDTO itemDTO = CopyUtil.copyObject(cloth, DesignSingleItemDTO.class); + itemDTO.setChanged(Boolean.FALSE); + itemDTO.setDesignType("Library"); + itemDTO.setPath(cloth.getMinIOPath()); + PantoneVO color = cloth.getColor(); + String colorString = color.getR() + " " + color.getG() + " " + color.getB(); + itemDTO.setColor(colorString); + if (cloth.getLayersObject().isEmpty()){ + itemDTO.setOffset(Arrays.asList(0L,0L)); + itemDTO.setScale(new Float[]{1.0f,1.0f}); + }else { + DesignPythonOutfitVO designPythonOutfitVO = cloth.getLayersObject().get(0); + itemDTO.setOffset(designPythonOutfitVO.getOffset()); + itemDTO.setScale(designPythonOutfitVO.getScale()); + } + // 统一设置mask为null,不用旧版mask + itemDTO.setMaskMinioUrl(null); + designSingleItemDTOS.add(itemDTO); + }); + + return resp; + } + + // temp 用于处理历史like的design没有新的mask的问题 + public void designSingleIncludeLayers(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO, Long userId) { + // 记录入参 base64数据太长,所以这里去掉 + DesignSingleIncludeLayersDTO clone = SerializationUtils.clone(designSingleIncludeLayersDTO); + clone.getDesignSingleItemDTOList().forEach( i -> { + // 渐变色 + if (!Objects.isNull(i.getGradient()) && !StringUtil.isNullOrEmpty(i.getGradient().getColorImg())){ + log.info("set gradient colorImage为空,便于日志打印"); + i.getGradient().setColorImg(null); + } + // 画笔修改过的sketch + if (!StringUtil.isNullOrEmpty(i.getSketchString())){ + log.info("set sketchString为空,便于日志打印"); + i.setSketchString(null); + } + // 标注过的mask + if (!StringUtil.isNullOrEmpty(i.getMaskUrl())){ + log.info("set labelingMask为空,便于日志打印"); + i.setMaskUrl(null); + }else { + // todo 允许为空吗? +// throw new BusinessException("labeling mask cannot be empty"); + } + }); + + log.info("designSingle request入参 ==> " + JSONObject.toJSONString(clone)); + +// Long userId = UserContext.getUserHolder().getId(); + DesignItem designItem = selectById(designSingleIncludeLayersDTO.getDesignItemId()); + if (Objects.isNull(designItem)) { + throw new BusinessException("designItem.not.found"); + } + Design design = designService.getById(designItem.getDesignId()); + if (Objects.isNull(design)) { + throw new BusinessException("design.not.found"); + } + + DesignLibraryModelPointVO designLibraryModelPointVO = null; + // 设置模特 + if (Objects.nonNull(design.getTemplateId())) { + String modelUrl; + Integer high; + Integer width; + if (design.getModelType().equals(ModelType.SYSTEM.getValue())) { + SysFileVO sysFile = sysFileService.getById(design.getTemplateId()); + if (Objects.isNull(sysFile)) { + throw new BusinessException("model.not.found"); + } + modelUrl = sysFile.getUrl(); + high = 700; + width = 320; + } else if (design.getModelType().equals(ModelType.LIBRARY.getValue())){ + Library libFile = libraryService.getById(design.getTemplateId()); + if (Objects.isNull(libFile)) { + throw new BusinessException("model.not.found"); + } + modelUrl = libFile.getUrl(); + high = libFile.getHigh(); + width = libFile.getWidth(); + }else { + throw new BusinessException("unknown.modelType"); + } + LibraryModelPoint modelPoint = libraryModelPointService.getByRelationId(design.getTemplateId(), design.getModelType()); + if (Objects.isNull(modelPoint)) { + throw new BusinessException("modelPoint.not.found"); + } + + designLibraryModelPointVO = collectionElementService.calculateTemplatePoint(modelPoint, high, width, modelUrl); + } + + // 画笔修改的sketch截图 上传后替换path + // 由于用户在系统或自己上传sketch的基础上修改过的衣服,再次修改后,第一次修改的衣服不会回到某个池子被再次利用, + // 所以,这里选择使用system或collection相同的地址,只是放在不同的桶,这样能保证图片服务器上,类似的sketch不会存在很多 + sketchBase64ToPath(designSingleIncludeLayersDTO); + + // todo 将标注后的mask上传到minio,并将minio地址传给python端 +// maskBase64ToPath(designSingleIncludeLayersDTO); + + // 组装入参 + DesignPythonObjects objects = pythonService.covertDesignSingleParam( + designSingleIncludeLayersDTO, design.getSingleOverall(), design.getSwitchCategory(), designLibraryModelPointVO); + // design + JSONObject jsonObject = pythonService.designNew(objects); + // preview -> 不存数据库 submit -> 存数据库 + List tDesignPythonOutfitDetails; + JSONObject data = jsonObject.getJSONObject("data"); + if (data == null) { + throw new BusinessException("python response data is null"); + } + JSONObject outfit = data.getJSONObject("0"); + + JSONArray layers = outfit.getJSONArray("layers"); + Map categoryAndUndividedLayer = setTypeAndUndividedLayer(layers); + // 直接更新及保存图层信息,全部走submit 不走preview + saveDesignSingleItemDetailAndLayers(objects, design.getId(), designSingleIncludeLayersDTO.getDesignItemId() + , userId, outfit, designSingleIncludeLayersDTO.getTimeZone() + , designSingleIncludeLayersDTO.getDesignSingleItemDTOList() + , categoryAndUndividedLayer); + + // 如果当前item被like过,需要更新t_user_like表和t_user_like_group表 + // - 这里,因为处理的都是like过的,所以都需要更新 + updateUserLikeDate(designSingleIncludeLayersDTO.getDesignItemId(),designSingleIncludeLayersDTO.getTimeZone()); + + // 数据替换完成即可,不需要返回数据 + } + } diff --git a/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java b/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java index 9d44d2dd..57ba60c5 100644 --- a/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java @@ -16,7 +16,10 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * 服务实现类 @@ -88,4 +91,21 @@ public class UserLikeServiceImpl extends ServiceImpl i return userLikeMapper.selectList(qw); } + @Override + public List> getHistoryLikeWithGradient(){ + List> historyLikeWithGradient = baseMapper.getHistoryLikeWithGradient(); + return historyLikeWithGradient.stream() + .map(map -> { + Map newMap = new HashMap<>(); + if (map.containsKey("design_item_id")) { + newMap.put("designItemId", map.get("design_item_id")); + } + if (map.containsKey("design_outfit_id")) { + newMap.put("designPythonOutfitId", map.get("design_outfit_id")); + } + return newMap; + }) + .collect(Collectors.toList()); + } + } diff --git a/src/main/resources/mapper/primary/UserLikeMapper.xml b/src/main/resources/mapper/primary/UserLikeMapper.xml new file mode 100644 index 00000000..5067caab --- /dev/null +++ b/src/main/resources/mapper/primary/UserLikeMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + +