@@ -24,9 +24,11 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper ;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl ;
import com.google.common.collect.Lists ;
import com.mysql.cj.util.StringUtils ;
import io.netty.util.internal.StringUtil ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.commons.lang3.SerializationUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.beans.factory.annotation.Value ;
import org.springframework.stereotype.Service ;
import org.springframework.transaction.annotation.Transactional ;
@@ -85,6 +87,8 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
@Value ( " ${minio.bucketName.clothing} " )
private String clothingBucket ;
@Autowired
private RedisUtil redisUtil ;
@Override
public Long saveOne ( DesignItem designItem ) {
@@ -372,7 +376,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
designPythonOutfitService . updateById ( designPythonOutfit ) ;
// 6、删除designPythonOutfitDetail表中原始的图层信息( 逻辑删除)
designPythonOutfitDetailService . deleteByDesignPythonOutfitId ( designPythonOutfit . getId ( ) ) ;
designPythonOutfitDetailService . deleteByDesignPythonOutfitIdLogical ( designPythonOutfit . getId ( ) ) ;
// 7、将新生成的图层信息存入designPythonOutfitDetail表
JSONArray layers = outfit . getJSONArray ( " layers " ) ;
@@ -497,8 +501,15 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
// 所以, 这里选择使用system或collection相同的地址, 只是放在不同的桶, 这样能保证图片服务器上,类似的sketch不会存在很多
sketchBase64ToPath ( designSingleIncludeLayersDTO ) ;
// todo 将标注后的mask上传到minio,并将minio地址传给python端
maskBase64ToPath ( designSingleIncludeLayersDTO ) ;
// 将标注后的mask上传到minio,并将minio地址传给python端
// todo 如何当前design使用的仍是旧的mask 则置maskUrl为null
// 1、查询当前design item在不在history中
UserLike userLikeDesign = userLikeService . getByDesignItemId ( designItem . getId ( ) ) ;
Boolean setNull = Boolean . FALSE ;
if ( ! Objects . isNull ( userLikeDesign ) & & userLikeDesign . getConverted ( ) = = 0 ) {
setNull = Boolean . TRUE ;
}
maskBase64ToPath ( designSingleIncludeLayersDTO , setNull ) ;
// 组装入参
DesignPythonObjects objects = pythonService . covertDesignSingleParam (
@@ -581,22 +592,26 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
} ) ;
}
private void maskBase64ToPath ( DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO ) {
private void maskBase64ToPath ( DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO , Boolean setNull ){
designSingleIncludeLayersDTO . getDesignSingleItemDTOList ( ) . forEach ( item - > {
// 如果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 . getM askM inioUrl ( ) ) ;
} else {
// 将原图地址作为修改后的图片地址,放在不同的桶
String path = minioUtil . base64UploadToPath ( item . getMaskUrl ( ) , clothingBucket , " labelingMask/ " + UUID . randomUUID ( ) ) ;
if ( StringUtil . isNullOrEmpty ( path ) ) {
log . error ( " 标注的mask图片上传失败 " ) ;
throw new BusinessException ( " image.modify.failed " ) ;
if ( setNull ) {
item . setMaskUrl ( null ) ;
} else {
if ( ! StringUtil . isNullOrEmpty ( item . getMaskUrl ( ) ) ) {
// 由于前端不好处理这块, 所以, 当mask没有做任何修改的时候, 仍然会传原始m ask的m inio地址
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 ) ;
}
item . setMaskUrl ( path ) ;
}
}
} ) ;
@@ -909,94 +924,167 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
}
}
// 将历史like的design, 按有无渐变色将design_item_id、design_python_outfit_id分为两个数组
public void classificationByGradientColor ( ) {
List < List < Long > > noGradientList = new ArrayList < > ( ) ;
List < List < Long > > withGradientList = new ArrayList < > ( ) ;
List < List < Long > > duplicateGradientList = new ArrayList < > ( ) ;
// 1、获取t_user_like表中design_item_id不为-1的所有design_item_id, design_outfit_id
QueryWrapper < UserLike > queryWrapper = new QueryWrapper < > ( ) ;
queryWrapper . ne ( " design_item_id " , - 1 ) ;
queryWrapper . ne ( " converted " , 1 ) ;
List < UserLike > userLikes = userLikeMapper . selectList ( queryWrapper ) ;
log . info ( " userLike 总数 : {} " , userLikes . size ( ) ) ;
long start = System . currentTimeMillis ( ) ;
// 2、遍历每个design_item_id
try {
userLikes . forEach ( userLike - > {
log . info ( " user_like_id: {}, design_item_id:{}, design_python_outfit_id:{} " , userLike . getId ( ) , userLike . getDesignItemId ( ) , userLike . getDesignOutfitId ( ) ) ;
List < DesignItemDetail > designItemDetails = designItemDetailService . selectByDesignItemId ( userLike . getDesignItemId ( ) ) ;
if ( designItemDetails . isEmpty ( ) ) {
log . error ( " 无法找到history中的被like的design item => design_item_id : {} " , userLike . getDesignItemId ( ) ) ;
} else {
boolean flag = true ;
for ( DesignItemDetail designItemDetail : designItemDetails ) {
if ( ! designItemDetail . getType ( ) . equals ( " Body " ) & & ! StringUtils . isNullOrEmpty ( designItemDetail . getGradientString ( ) ) ) {
flag = false ;
break ;
}
}
List < Long > list = Arrays . asList ( userLike . getDesignItemId ( ) , userLike . getDesignOutfitId ( ) ) ;
if ( flag ) {
// 如果design_item_id对应的每个单品都没有使用渐变色, 则将该design_item_id noGradientList
if ( ! noGradientList . contains ( list ) ) {
noGradientList . add ( list ) ;
} else {
duplicateGradientList . add ( list ) ;
}
} else {
// 如果design_item_id对应的任一个单品使用了渐变色, 则将该design_item_id design_python_outfit_id加入withGradientList
if ( ! withGradientList . contains ( list ) ) {
withGradientList . add ( list ) ;
} else {
duplicateGradientList . add ( list ) ;
}
}
}
} ) ;
} catch ( Exception e ) {
log . error ( e . getMessage ( ) ) ;
}
long end = System . currentTimeMillis ( ) ;
log . info ( " 按是否使用了渐变色对历史like进行分类 执行时长:{}毫秒 " , end - start ) ;
// 3、将分类好的数据存入redis中
redisUtil . addToStringList ( RedisUtil . NO_GRADIENT , noGradientList ) ;
redisUtil . addToStringList ( RedisUtil . WITH_GRADIENT , withGradientList ) ;
log . info ( " 从t_user_like表, 通过渐变色分类, 完成, 其中总like量为: {}, 没有使用渐变色的like量为: {}, 使用了渐变色的like量为: {} " , userLikes . size ( ) , noGradientList . size ( ) , withGradientList . size ( ) ) ;
log . info ( " 使用了渐变色的like: {} " , withGradientList ) ;
log . info ( " 未使用渐变色的like: {} " , noGradientList ) ;
log . info ( " 重复的like: {},总数:{} " , duplicateGradientList , duplicateGradientList . size ( ) ) ;
}
public List < List < Long > > 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
@Transactional ( rollbackFor = Exception . class )
public void convertHistoryMaskWithoutGradient ( ) {
// 查询用户like过的design 且没有使用渐变色的 design_item_id和design_python_outfit_id
List < Map < String , Long > > historyLikeWithoutGradient = userLikeMapper . getHistoryLikeWithoutGradient ( ) ;
List < List < Long > > historyLikeWithoutGradient = redisUtil . getFromStringList ( RedisUtil . NO_GRADIENT ) ;
log . info ( " historyLikeWithoutGradient total count : {} " , historyLikeWithoutGradient . size ( ) ) ;
// 遍历list
// 先试一下, 刷新10条, 需要花费的时间
/*Map<String, Long> 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 < String , Long > userLikeMap = historyLikeWithoutGradient . get ( 0 ) ;
log . info ( " test 替换mask " + userLikeMap . toString ( ) ) ;
Long designItemId = userLikeMap . get ( " design_item_id " ) ;
Long designOutfit Id = userLikeMap . get ( " design_outfit_id " ) ;
int count = 0 ;
try {
for ( int i = 45 ; i < 50 ; i + + ) {
List < Long > userLikeMap = historyLikeWithoutGradient . get ( i ) ;
log . info ( " test 替换mask{} " , userLikeMap . toString ( ) ) ;
Long designItem Id = userLikeMap . get ( 0 ) ;
Long designOutfitId = userLikeMap . get ( 1 ) ;
// 查每个 design_item_id和design_python_outfit_id的detail
// 1、查询 design_item_id和design_python_outfit_id对应的accountId
List < UserLike > userLikeList = getUserLikeByDesignItemId ( designItemId , designOutfitId ) ;
// 如果已经替换了新的mask则直接跳过
if ( userLikeList . get ( 0 ) . getConverted ( ) = = 1 ) {
log . info ( " designItemId: {}, designOutfitId : {} mask已替换 " , designItemId , designOutfitId ) ;
continue ;
}
UserLikeGroup userLikeGroup = userLikeGroupService . getById ( userLikeList . get ( 0 ) . getUserLikeGroupId ( ) ) ;
if ( userLikeGroup = = null ) {
log . error ( " 在t_user_like_group表中找不到id为: {} 的记录 " , userLikeList . get ( 0 ) . getUserLikeGroupId ( ) ) ;
continue ;
}
// 2、查每个design_item_id和design_python_outfit_id的detail
long startDetail = System . currentTimeMillis ( ) ;
DesignItemDetailVO detail = designService . detail ( designOutfitId , designItemId ) ;
L ong accountId = userLikeMap . get ( " account_id " ) ;
// 组装参数
l ong endDetail = System . currentTimeMillis ( ) ;
log . info ( " 查询design detail 执行时长:{}毫秒 " , endDetail - startDetail ) ;
Long accountId = userLikeGroup . getAccountId ( ) ;
// 3、组装参数
long startConvert = System . currentTimeMillis ( ) ;
DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO = convertToDesignSingleIncludeLayersDTO ( detail , accountId ) ;
if ( Objects . isNull ( designSingleIncludeLayersDTO ) ) {
throw new BusinessException ( " cannot find model. designItemId: " + designItemId + " designOutfitId : " + designOutfitId ) ;
log . error ( " cannot find model. designItemId: {}, designOutfitId : {} " , designItemId , designOutfitId ) ;
continue ;
}
// 调用design single
long endConvert = System . currentTimeMillis ( ) ;
log . info ( " 组装designSingle参数 执行时长:{}毫秒 " , endConvert - startConvert ) ;
// 4、调用design single
long startDesignSingle = System . currentTimeMillis ( ) ;
designSingleIncludeLayers ( designSingleIncludeLayersDTO , accountId ) ;
long endDesignSingle = System . currentTimeMillis ( ) ;
log . info ( " 执行designSingle 执行时长:{}毫秒 " , endDesignSingle - startDesignSingle ) ;
// 标志字段置为1
UserLike userLike = new U serLike( ) ;
u serLike. setId ( userLikeMap . get ( " id " ) ) ;
userLike . setConverte d ( 1 ) ;
// 5、 标志字段置为1
for ( UserLike item : u serLikeList ) {
U serLike userLike = new UserLike ( ) ;
userLike . setId ( item . getI d ( ) ) ;
userLike . setConverted ( 1 ) ;
userLikeMapper . updateById ( userLike ) ;
}catch ( BusinessException e ) {
log . error ( " mask convert error : {} " , e . getMessage ( ) ) ;
userLikeMapper . updateById ( userLike ) ;
}
log . info ( " designItemId: {}, designOutfitId : {} mask替换完成 " , designItemId , designOutfitId ) ;
count + + ;
}
} catch ( BusinessException e ) {
log . error ( " mask convert error : {} " , e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
}
long end = System . currentTimeMillis ( ) ;
log . info ( " convert mask ,10 条 执行时长:" + ( end - start ) + " 毫秒 " ) ;
log . info ( " convert mask 成功 {} 条 执行时长:{}毫秒 " , count , end - start ) ;
}
private List < UserLike > getUserLikeByDesignItemId ( Long designItemId , Long designOutfitId ) {
QueryWrapper < UserLike > queryWrapper = new QueryWrapper < > ( ) ;
queryWrapper . eq ( " design_item_id " , designItemId )
. eq ( " design_outfit_id " , designOutfitId ) ;
return userLikeMapper . selectList ( queryWrapper ) ;
}
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 < SysFileVO > 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 " ) ;
@@ -1046,15 +1134,11 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
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 " ) ;
@@ -1078,6 +1162,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
modelUrl = sysFile . getUrl ( ) ;
high = 700 ;
width = 320 ;
designSingleIncludeLayersDTO . setGender ( sysFile . getLevel2Type ( ) ) ;
} else if ( design . getModelType ( ) . equals ( ModelType . LIBRARY . getValue ( ) ) ) {
Library libFile = libraryService . getById ( design . getTemplateId ( ) ) ;
if ( Objects . isNull ( libFile ) ) {
@@ -1086,6 +1171,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
modelUrl = libFile . getUrl ( ) ;
high = libFile . getHigh ( ) ;
width = libFile . getWidth ( ) ;
designSingleIncludeLayersDTO . setGender ( libFile . getLevel2Type ( ) ) ;
} else {
throw new BusinessException ( " unknown.modelType " ) ;
}
@@ -1102,16 +1188,15 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
// 所以, 这里选择使用system或collection相同的地址, 只是放在不同的桶, 这样能保证图片服务器上,类似的sketch不会存在很多
sketchBase64ToPath ( designSingleIncludeLayersDTO ) ;
// todo 将标注后的mask上传到minio,并将minio地址传给python端
// maskBase64ToPath(designSingleIncludeLayersDTO);
// 组装入参
DesignPythonObjects objects = pythonService . covertDesignSingleParam (
designSingleIncludeLayersDTO , design . getSingleOverall ( ) , design . getSwitchCategory ( ) , designLibraryModelPointVO ) ;
// design
long start = System . currentTimeMillis ( ) ;
JSONObject jsonObject = pythonService . designNew ( objects ) ;
// preview -> 不存数据库 submit -> 存数据库
List < TDesignPythonOutfitDetail > tDesignPythonOutfitDetails ;
long end = System . currentTimeMillis ( ) ;
log . info ( " design 执行时长:{}毫秒 " , end - start ) ;
JSONObject data = jsonObject . getJSONObject ( " data " ) ;
if ( data = = null ) {
throw new BusinessException ( " python response data is null " ) ;
@@ -1121,10 +1206,8 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
JSONArray layers = outfit . getJSONArray ( " layers " ) ;
Map < String , String > categoryAndUndividedLayer = setTypeAndUndividedLayer ( layers ) ;
// 直接更新及保存图层信息, 全部走submit 不走preview
saveDesignSingleItemDetailAndLayers (objects , design . getId ( ) , designSingleIncludeLayersDTO . getDesignItemId ( )
, userId , outfit , designSingleIncludeLayersDTO . getTimeZone ( )
, designSingleIncludeLayersDTO . getDesignSingleItemDTOList ( )
, categoryAndUndividedLayer ) ;
saveDesignSingleItemDetailAndLayersCopy ( design . getId ( ) , designSingleIncludeLayersDTO . getDesignItemId ( )
, userId , outfit , designSingleIncludeLayersDTO . getDesignSingleItemDTOList ( ) ) ;
// 如果当前item被like过, 需要更新t_user_like表和t_user_like_group表
// - 这里, 因为处理的都是like过的, 所以都需要更新
@@ -1133,4 +1216,50 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
// 数据替换完成即可,不需要返回数据
}
private void saveDesignSingleItemDetailAndLayersCopy ( Long designId , Long designItemId , Long userId
, JSONObject outfit , List < DesignSingleItemDTO > designSingleItemDTOList ) {
// 6、删除designPythonOutfitDetail表中原始的图层信息( 物理删除)
Long designPythonOutfitId = designPythonOutfitService . getByDesignItemId ( designItemId ) . getId ( ) ;
designPythonOutfitDetailService . deleteByDesignPythonOutfitIdPhysical ( designPythonOutfitId ) ;
// 7、将新生成的图层信息存入designPythonOutfitDetail表
JSONArray layers = outfit . getJSONArray ( " layers " ) ;
Map < Integer , List < Long > > priorityOffset = designSingleItemDTOList . stream ( )
. collect ( Collectors . toMap ( DesignSingleItemDTO : : getPriority , DesignSingleItemDTO : : getOffset ) ) ;
List < TDesignPythonOutfitDetail > list = setTDesignPythonOutfitDetailList ( layers , designId , designPythonOutfitId , userId , priorityOffset ) ;
designPythonOutfitDetailService . saveBatch ( list ) ;
}
public void deleteNotFoundModelDesign ( ) {
// 查询在user_like的design_item_detail中使用了找不到的model的design_item_id,design_outfit_id有哪些
List < Map < String , Long > > historyLikeWithoutModel = userLikeMapper . getHistoryLikeWithoutModel ( ) ;
List < List < Long > > convertedList = new ArrayList < > ( ) ;
for ( Map < String , Long > map : historyLikeWithoutModel ) {
Long designItemId = map . get ( " designItemId " ) ;
Long designOutfitId = map . get ( " designOutfitId " ) ;
convertedList . add ( Arrays . asList ( designItemId , designOutfitId ) ) ;
}
// 将redis中的这些数据删除, 再存回
List < List < Long > > withGradientList = redisUtil . getFromStringList ( RedisUtil . WITH_GRADIENT ) ;
List < List < Long > > noGradientList = redisUtil . getFromStringList ( RedisUtil . NO_GRADIENT ) ;
log . info ( " 有渐变色的design item: {},size: {} " , withGradientList , withGradientList . size ( ) ) ;
log . info ( " 没有渐变色的design item: {},size: {} " , noGradientList , noGradientList . size ( ) ) ;
withGradientList . removeAll ( convertedList ) ;
noGradientList . removeAll ( convertedList ) ;
log . info ( " 移除没有model的design后, 有渐变色的design item: {},size: {} " , withGradientList , withGradientList . size ( ) ) ;
log . info ( " 移除没有model的design后, 没有渐变色的design item: {},size: {} " , noGradientList , noGradientList . size ( ) ) ;
redisUtil . addToStringList ( RedisUtil . WITH_GRADIENT , withGradientList ) ;
redisUtil . addToStringList ( RedisUtil . NO_GRADIENT , noGradientList ) ;
}
public void designSingleWithGradient ( ) {
}
}