From 8fa76c6732ecda13bdb16ffe3042ea0140bc2d41 Mon Sep 17 00:00:00 2001 From: shahaibo <1023316923@qq.com> Date: Sun, 16 Mar 2025 13:09:50 +0800 Subject: [PATCH] =?UTF-8?q?TASK:AiDA=E6=A8=A1=E5=9D=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/da/common/config/MyTaskScheduler.java | 1040 ++++++++++++++++- .../com/ai/da/common/utils/RedisUtil.java | 200 +++- .../ai/da/controller/ProjectController.java | 83 ++ .../ai/da/controller/WorkspaceController.java | 8 + .../primary/CollectionElementMapper.java | 3 + .../da/mapper/primary/CollectionMapper.java | 4 + .../da/mapper/primary/DesignItemMapper.java | 4 + .../ai/da/mapper/primary/DesignMapper.java | 2 + .../ai/da/mapper/primary/ProjectMapper.java | 7 + .../da/mapper/primary/SketchDataMapper.java | 7 + .../TDesignPythonOutfitDetailMapper.java | 1 + .../primary/TDesignPythonOutfitMapper.java | 1 + .../mapper/primary/UserLikeGroupMapper.java | 4 + .../primary/UserPreferenceLogMapper.java | 7 + .../UserPreferenceLogPredictionMapper.java | 8 + .../primary/entity/CollectionElement.java | 2 + .../ai/da/mapper/primary/entity/Project.java | 35 + .../da/mapper/primary/entity/SketchData.java | 22 + .../mapper/primary/entity/UserLikeGroup.java | 2 + .../entity/UserPreferenceLogPrediction.java | 27 + .../primary/entity/UserPreferenceLogTest.java | 27 + .../da/mapper/primary/entity/Workspace.java | 2 + .../com/ai/da/model/dto/ModuleSaveDTO.java | 36 + .../da/model/dto/MoodBoardModuleSaveDTO.java | 19 + .../java/com/ai/da/model/dto/ProjectDTO.java | 29 + .../com/ai/da/model/dto/ProjectQueryDTO.java | 37 + .../com/ai/da/model/dto/WorkspaceSaveDTO.java | 1 + .../com/ai/da/model/enums/DesignProcess.java | 34 + .../java/com/ai/da/model/enums/Module.java | 39 + .../ai/da/model/vo/CavasModuleChooseVO.java | 14 + .../ai/da/model/vo/DesignModuleChooseVO.java | 17 + .../com/ai/da/model/vo/ModuleChooseVO.java | 34 + .../da/model/vo/MoodBoardModuleChooseVO.java | 20 + .../com/ai/da/model/vo/ProjectChooseVO.java | 37 + .../java/com/ai/da/model/vo/ProjectVO.java | 21 + .../da/model/vo/UserPreferenceLogTestDTO.java | 0 .../com/ai/da/model/vo/ValidateElementVO.java | 4 + .../java/com/ai/da/python/PythonService.java | 607 +++++++++- .../com/ai/da/service/CollectionService.java | 8 + .../java/com/ai/da/service/DesignService.java | 2 + .../com/ai/da/service/SysFileService.java | 2 + .../ai/da/service/UserLikeGroupService.java | 16 +- .../com/ai/da/service/WorkspaceService.java | 7 + .../service/impl/CollectionServiceImpl.java | 7 +- .../da/service/impl/SysFileServiceImpl.java | 30 + .../impl/UserLikeGroupServiceImpl.java | 673 ++++++++++- .../da/service/impl/WorkspaceServiceImpl.java | 112 ++ src/main/resources/application-dev.properties | 2 +- .../primary/CollectionElementMapper.xml.xml | 12 + .../mapper/primary/CollectionMapper.xml | 7 + .../mapper/primary/DesignItemMapper.xml | 7 + .../resources/mapper/primary/DesignMapper.xml | 7 + .../TDesignPythonOutfitDetailMapper.xml | 4 + .../primary/TDesignPythonOutfitMapper.xml | 4 + .../mapper/primary/UserLikeGroupMapper.xml | 23 +- 55 files changed, 3236 insertions(+), 132 deletions(-) create mode 100644 src/main/java/com/ai/da/controller/ProjectController.java create mode 100644 src/main/java/com/ai/da/mapper/primary/ProjectMapper.java create mode 100644 src/main/java/com/ai/da/mapper/primary/SketchDataMapper.java create mode 100644 src/main/java/com/ai/da/mapper/primary/UserPreferenceLogMapper.java create mode 100644 src/main/java/com/ai/da/mapper/primary/UserPreferenceLogPredictionMapper.java create mode 100644 src/main/java/com/ai/da/mapper/primary/entity/Project.java create mode 100644 src/main/java/com/ai/da/mapper/primary/entity/SketchData.java create mode 100644 src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogPrediction.java create mode 100644 src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogTest.java create mode 100644 src/main/java/com/ai/da/model/dto/ModuleSaveDTO.java create mode 100644 src/main/java/com/ai/da/model/dto/MoodBoardModuleSaveDTO.java create mode 100644 src/main/java/com/ai/da/model/dto/ProjectDTO.java create mode 100644 src/main/java/com/ai/da/model/dto/ProjectQueryDTO.java create mode 100644 src/main/java/com/ai/da/model/enums/DesignProcess.java create mode 100644 src/main/java/com/ai/da/model/enums/Module.java create mode 100644 src/main/java/com/ai/da/model/vo/CavasModuleChooseVO.java create mode 100644 src/main/java/com/ai/da/model/vo/DesignModuleChooseVO.java create mode 100644 src/main/java/com/ai/da/model/vo/ModuleChooseVO.java create mode 100644 src/main/java/com/ai/da/model/vo/MoodBoardModuleChooseVO.java create mode 100644 src/main/java/com/ai/da/model/vo/ProjectChooseVO.java create mode 100644 src/main/java/com/ai/da/model/vo/ProjectVO.java create mode 100644 src/main/java/com/ai/da/model/vo/UserPreferenceLogTestDTO.java create mode 100644 src/main/resources/mapper/primary/CollectionElementMapper.xml.xml diff --git a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java index 9dc8cd13..f2c3331d 100644 --- a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java +++ b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java @@ -1,38 +1,38 @@ package com.ai.da.common.config; -import com.ai.da.common.utils.ExcelReader; -import com.ai.da.common.utils.MinioUtil; -import com.ai.da.common.utils.SendEmailUtil; +import com.ai.da.common.utils.*; import com.ai.da.mapper.primary.*; import com.ai.da.mapper.primary.entity.*; +import com.ai.da.mapper.primary.entity.Collection; import com.ai.da.mapper.secondary.AttributeRetrievalMapper; -import com.ai.da.model.enums.StyleEnum; +import com.ai.da.model.dto.CollectionSketchDTO; +import com.ai.da.model.dto.DesignCollectionDTO; +import com.ai.da.model.vo.ValidateElementVO; +import com.ai.da.python.PythonService; +import com.ai.da.python.vo.DesignPythonObjects; +import com.ai.da.service.CollectionElementService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; -import java.nio.file.DirectoryStream; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDate; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.*; import java.util.stream.Collectors; @Slf4j @Component @@ -43,6 +43,14 @@ public class MyTaskScheduler { // clearMinio(); // addSystemFileStyle(); // sendTrialOrderExcelToManagements(); +// createLikeSketchData(); +// statisticalCoincidenceDegree(); +// freqAddTest(); +// runMetricsComparison(); +// testAverageHitRatio(); +// saveUserLikedSketchDataToRedis(4L); +// runComparisonAndRecordResults(5); +// saveDataToNumpyFormat(); } @Resource @@ -51,6 +59,9 @@ public class MyTaskScheduler { @Resource private TrialOrderMapper trialOrderMapper; + @Resource + private DesignMapper designMapper; + // 定时任务,每十五天执行一次 // @Scheduled(cron = "0 0 0 ? * MON") // @Scheduled(cron = "0 0 0 */15 * ?") @@ -87,11 +98,10 @@ public class MyTaskScheduler { } } } -// @Scheduled(cron = "0 0 9 * * ?") + // @Scheduled(cron = "0 0 9 * * ?") public void sendTrialOrderExcelToManagements() { // 获取前一天日期 LocalDate yesterday = LocalDate.now().minusDays(1); -// LocalDate before = LocalDate.now().minusDays(4); // 查询前一天的试用订单 QueryWrapper qw = new QueryWrapper<>(); @@ -131,9 +141,7 @@ public class MyTaskScheduler { row.createCell(6).setCellValue(trialOrder.getCountry()); row.createCell(7).setCellValue(trialOrder.getOccupation()); row.createCell(8).setCellValue(trialOrder.getCreateTime().format(formatter)); - if (!ObjectUtils.isEmpty(trialOrder.getUpdateTime())) { - row.createCell(9).setCellValue(trialOrder.getUpdateTime().format(formatter)); - } + row.createCell(9).setCellValue(trialOrder.getUpdateTime().format(formatter)); row.createCell(10).setCellValue(trialOrder.getStatus()); } @@ -141,10 +149,13 @@ public class MyTaskScheduler { String fileName = "trialOrder-" + yesterday.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".xlsx"; try (FileOutputStream fileOut = new FileOutputStream(fileName)) { workbook.write(fileOut); - SendEmailUtil.sendExcelEmail("1023316923@qq.com", null, Files.readAllBytes(Paths.get(fileName)), fileName); - SendEmailUtil.sendExcelEmail("calvinwong@aidlab.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); - SendEmailUtil.sendExcelEmail("kaicpang.pang@connect.polyu.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); - SendEmailUtil.sendExcelEmail("kimwong@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); +// SendEmailUtil.sendExcelEmail("1023316923@qq.com", null, Files.readAllBytes(Paths.get(fileName)), fileName); +// SendEmailUtil.sendExcelEmail("calvinwong@aidlab.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); +// SendEmailUtil.sendExcelEmail("kaicpang.pang@connect.polyu.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); +// SendEmailUtil.sendExcelEmail("kimwong@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); + SendEmailUtil.sendExcelEmail("ningning@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); + SendEmailUtil.sendExcelEmail("johnnyho@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); + SendEmailUtil.sendExcelEmail("ringolau@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); SendEmailUtil.sendExcelEmail("ningning@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); SendEmailUtil.sendExcelEmail("johnnyho@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); SendEmailUtil.sendExcelEmail("ringolau@code-create.com.hk", null, Files.readAllBytes(Paths.get(fileName)), fileName); @@ -153,10 +164,13 @@ public class MyTaskScheduler { e.printStackTrace(); } }else { - SendEmailUtil.sendNoExcelEmail("1023316923@qq.com", null); - SendEmailUtil.sendNoExcelEmail("calvinwong@aidlab.hk", null); - SendEmailUtil.sendNoExcelEmail("kaicpang.pang@connect.polyu.hk", null); - SendEmailUtil.sendNoExcelEmail("kimwong@code-create.com.hk", null); +// SendEmailUtil.sendNoExcelEmail("1023316923@qq.com", null); +// SendEmailUtil.sendNoExcelEmail("calvinwong@aidlab.hk", null); +// SendEmailUtil.sendNoExcelEmail("kaicpang.pang@connect.polyu.hk", null); +// SendEmailUtil.sendNoExcelEmail("kimwong@code-create.com.hk", null); + SendEmailUtil.sendNoExcelEmail("ningning@code-create.com.hk", null); + SendEmailUtil.sendNoExcelEmail("johnnyho@code-create.com.hk", null); + SendEmailUtil.sendNoExcelEmail("ringolau@code-create.com.hk", null); SendEmailUtil.sendNoExcelEmail("ningning@code-create.com.hk", null); SendEmailUtil.sendNoExcelEmail("johnnyho@code-create.com.hk", null); SendEmailUtil.sendNoExcelEmail("ringolau@code-create.com.hk", null); @@ -175,57 +189,182 @@ public class MyTaskScheduler { private DesignItemMapper designItemMapper; @Resource private DesignItemDetailMapper designItemDetailMapper; + + @Resource + private DesignItemDetailPrintMapper designItemDetailPrintMapper; + + @Resource + private GenerateDetailMapper generateDetailMapper; + + @Resource + private ToProductImageResultMapper toProductImageResultMapper; + @Resource private MinioUtil minioUtil; public void clearMinio() { + List collectionElements = collectionElementMapper.selectDeleteList(); + for (CollectionElement collectionElement : collectionElements) { + String url = collectionElement.getUrl(); + if (StringUtils.isNotBlank(url)) { + if (url.startsWith("aida-collection-element")) { + QueryWrapper lQw = new QueryWrapper<>(); + lQw.lambda().eq(Library::getUrl, url); + List libraries = libraryMapper.selectList(lQw); + if (CollectionUtils.isEmpty(libraries)) { + if (!url.contains("/")) { + continue; + } + minioUtil.deleteObject(url); + } + } + } +// collectionElementMapper.deleteById(collectionElement); + } + +// List designList = designMapper.selectDeleteList(); +// designMapper.deleteBatchIds(designList); +// +// List collectionList = collectionMapper.selectDeleteList(); +// collectionMapper.deleteBatchIds(collectionList); + // 获取当前所有history QueryWrapper userLikeGroupQueryWrapper = new QueryWrapper<>(); List userLikeGroupList = userLikeGroupMapper.selectList(userLikeGroupQueryWrapper); - List userLikeGroupIdList = userLikeGroupList.stream().map(UserLikeGroup::getId).collect(Collectors.toList()); + Set userLikeGroupIdSet = userLikeGroupList.stream().map(UserLikeGroup::getId).collect(Collectors.toSet()); QueryWrapper userLikeQueryWrapper = new QueryWrapper<>(); - userLikeQueryWrapper.lambda().in(UserLike::getUserLikeGroupId, userLikeGroupIdList); + userLikeQueryWrapper.lambda().in(UserLike::getUserLikeGroupId, userLikeGroupIdSet); // 所有喜欢的图片 List userLikes = userLikeMapper.selectList(userLikeQueryWrapper); - List designOutfitIdList = userLikes.stream().map(UserLike::getDesignOutfitId).collect(Collectors.toList()); + Set designOutfitIdSet = userLikes.stream().map(UserLike::getDesignOutfitId).collect(Collectors.toSet()); QueryWrapper designPythonOutfitQueryWrapper = new QueryWrapper<>(); - designPythonOutfitQueryWrapper.lambda().notIn(TDesignPythonOutfit::getId, designOutfitIdList); + designPythonOutfitQueryWrapper.lambda().notIn(TDesignPythonOutfit::getId, designOutfitIdSet); List tDesignPythonOutfits = designPythonOutfitMapper.selectList(designPythonOutfitQueryWrapper); -// int i = 0; -// for (TDesignPythonOutfit tDesignPythonOutfit : tDesignPythonOutfits) { -// String designUrl = tDesignPythonOutfit.getDesignUrl(); -// if (StringUtils.isNotBlank(designUrl)) { -// minioUtil.deleteObject(designUrl); -// i ++; -// } -// QueryWrapper designPythonOutfitDetailQueryWrapper = new QueryWrapper<>(); -// designPythonOutfitDetailQueryWrapper.lambda().eq(TDesignPythonOutfitDetail::getDesignPythonOutfitId, tDesignPythonOutfit.getId()); -// List tDesignPythonOutfitDetails = designPythonOutfitDetailMapper.selectList(designPythonOutfitDetailQueryWrapper); -// for (TDesignPythonOutfitDetail tDesignPythonOutfitDetail : tDesignPythonOutfitDetails) { -// if (!tDesignPythonOutfitDetail.getImageCategory().equals("body")) { -// if (StringUtils.isNotBlank(tDesignPythonOutfitDetail.getImageUrl())) { -// minioUtil.deleteObject(tDesignPythonOutfitDetail.getImageUrl()); -// i ++; -// } -// if (StringUtils.isNotBlank(tDesignPythonOutfitDetail.getMaskUrl())) { -// minioUtil.deleteObject(tDesignPythonOutfitDetail.getMaskUrl()); -// i ++; -// } -// } -// } -// } + int i = 0; + int designPythonOutfitMapperDelete = 0; + int designPythonOutfitDetailMapperDelete = 0; + int designItemMapperDelete = 0; + int designItemDetailPrintMapperDelete = 0; + int designItemDetailMapperDelete = 0; + for (TDesignPythonOutfit tDesignPythonOutfit : tDesignPythonOutfits) { + String designUrl = tDesignPythonOutfit.getDesignUrl(); + if (StringUtils.isNotBlank(designUrl)) { + minioUtil.deleteObject(designUrl); + i ++; + } + QueryWrapper designPythonOutfitDetailQueryWrapper = new QueryWrapper<>(); + designPythonOutfitDetailQueryWrapper.lambda().eq(TDesignPythonOutfitDetail::getDesignPythonOutfitId, tDesignPythonOutfit.getId()); + List tDesignPythonOutfitDetails = designPythonOutfitDetailMapper.selectList(designPythonOutfitDetailQueryWrapper); + for (TDesignPythonOutfitDetail tDesignPythonOutfitDetail : tDesignPythonOutfitDetails) { + if (!tDesignPythonOutfitDetail.getImageCategory().equals("body")) { + if (StringUtils.isNotBlank(tDesignPythonOutfitDetail.getImageUrl())) { + minioUtil.deleteObject(tDesignPythonOutfitDetail.getImageUrl()); + i ++; + } + if (StringUtils.isNotBlank(tDesignPythonOutfitDetail.getMaskUrl())) { + minioUtil.deleteObject(tDesignPythonOutfitDetail.getMaskUrl()); + i ++; + } + } + } + designPythonOutfitDetailMapperDelete += tDesignPythonOutfitDetails.size(); + if (!CollectionUtils.isEmpty(tDesignPythonOutfitDetails)) { + designPythonOutfitDetailMapper.deleteBatchIds(tDesignPythonOutfitDetails); + } + } + designPythonOutfitMapperDelete = tDesignPythonOutfits.size(); + if (!CollectionUtils.isEmpty(tDesignPythonOutfits)) { + designPythonOutfitMapper.deleteBatchIds(tDesignPythonOutfits); + } System.out.println("i"); -// List designItemIdList = userLikes.stream().map(UserLike::getDesignItemId).collect(Collectors.toList()); -// QueryWrapper designItemQueryWrapper = new QueryWrapper<>(); -// designItemQueryWrapper.lambda().in(DesignItem::getId,designItemIdList); -// List designItems = designItemMapper.selectList(designItemQueryWrapper); -// for (DesignItem designItem : designItems) { + List designItemIdList = designItemMapper.selectDeleteList(); +// for (DesignItem designItem : designItemIdList) { // QueryWrapper designItemDetailQueryWrapper = new QueryWrapper<>(); // designItemDetailQueryWrapper.lambda().eq(DesignItemDetail::getDesignItemId, designItem.getId()); // List designItemDetails = designItemDetailMapper.selectList(designItemDetailQueryWrapper); -// for (DesignItemDetail designItemDetail : designItemDetails) { +// } +// QueryWrapper designItemQueryWrapper = new QueryWrapper<>(); +// designItemQueryWrapper.lambda().in(DesignItem::getId,designItemIdList); +// List designItems = designItemMapper.selectList(designItemQueryWrapper); + designItemMapperDelete = designItemIdList.size(); + for (DesignItem designItem : designItemIdList) { + QueryWrapper designItemDetailQueryWrapper = new QueryWrapper<>(); + designItemDetailQueryWrapper.lambda().eq(DesignItemDetail::getDesignItemId, designItem.getId()); + List designItemDetails = designItemDetailMapper.selectList(designItemDetailQueryWrapper); + for (DesignItemDetail designItemDetail : designItemDetails) { + QueryWrapper didpQw = new QueryWrapper<>(); + didpQw.lambda().eq(DesignItemDetailPrint::getDesignItemDetailId, designItemDetail.getId()); + List designItemDetailPrintList = designItemDetailPrintMapper.selectList(didpQw); + designItemDetailPrintMapperDelete += designItemDetailPrintList.size(); + if (!CollectionUtils.isEmpty(designItemDetailPrintList)) { + if (!CollectionUtils.isEmpty(designItemDetailPrintList)) { + designItemDetailPrintMapper.deleteBatchIds(designItemDetailPrintList); + } + } + } + designItemDetailMapperDelete += designItemDetails.size(); + if (!CollectionUtils.isEmpty(designItemDetails)) { + designItemDetailMapper.deleteBatchIds(designItemDetails); + } + } + if (!CollectionUtils.isEmpty(designItemIdList)) { + designItemMapper.deleteBatchIds(designItemIdList); + } + + System.out.println(designPythonOutfitMapperDelete); + System.out.println(designPythonOutfitDetailMapperDelete); + System.out.println(designItemMapperDelete); + System.out.println(designItemDetailPrintMapperDelete); + System.out.println(designItemDetailMapperDelete); + + QueryWrapper gdQw = new QueryWrapper<>(); + gdQw.lambda().eq(GenerateDetail::getIsLike, 0); + List generateDetails = generateDetailMapper.selectList(gdQw); + for (GenerateDetail generateDetail : generateDetails) { + String url = generateDetail.getUrl(); + if (StringUtils.isNotBlank(url)) { + QueryWrapper lQw = new QueryWrapper<>(); + lQw.lambda().eq(Library::getUrl, url); + List libraries = libraryMapper.selectList(lQw); + if (CollectionUtils.isEmpty(libraries)) { + minioUtil.deleteObject(url); + } + } + } // +// QueryWrapper tpirQw = new QueryWrapper<>(); +// tpirQw.lambda().eq(ToProductImageResult::getIsLike, 0); +// List toProductImageResults = toProductImageResultMapper.selectList(tpirQw); +// for (ToProductImageResult toProductImageResult : toProductImageResults) { +// String url = toProductImageResult.getUrl(); +// if (StringUtils.isNotBlank(url)) { +// minioUtil.deleteObject(url); // } // } +// QueryWrapper qw1 = new QueryWrapper<>(); +// qw1.lambda().eq(TDesignPythonOutfit::getIsDeleted, 1); +// List tDesignPythonOutfits = designPythonOutfitMapper.selectListDelete(); +// for (TDesignPythonOutfit tDesignPythonOutfit : tDesignPythonOutfits) { +// String designUrl = tDesignPythonOutfit.getDesignUrl(); +// if (StringUtils.isNotBlank(designUrl)) { +// System.out.println(minioUtil.doesObjectExist(designUrl)); +// } +// } +// +//// QueryWrapper qw2 = new QueryWrapper<>(); +//// qw2.lambda().eq(TDesignPythonOutfitDetail::getIsDeleted, 1); +// List tDesignPythonOutfitDetails = designPythonOutfitDetailMapper.selectListDelete(); +// for (TDesignPythonOutfitDetail tDesignPythonOutfitDetail : tDesignPythonOutfitDetails) { +// if (!tDesignPythonOutfitDetail.getImageCategory().equals("body")) { +// if (StringUtils.isNotBlank(tDesignPythonOutfitDetail.getImageUrl())) { +// System.out.println(minioUtil.doesObjectExist(tDesignPythonOutfitDetail.getImageUrl())); +// } +// if (StringUtils.isNotBlank(tDesignPythonOutfitDetail.getMaskUrl())) { +// System.out.println(minioUtil.doesObjectExist(tDesignPythonOutfitDetail.getMaskUrl()));; +// } +// } +// } +// String preSignedUrl = minioUtil.getPreSignedUrl("aida-clothing/image/image_1698374859.3031476.png", 10000); +// System.out.println(preSignedUrl); } @Resource @@ -393,4 +532,787 @@ public class MyTaskScheduler { // // return fileNames; // } + + @Resource + private UserPreferenceLogMapper userPreferenceLogMapper; + + @Resource + private UserPreferenceLogPredictionMapper userPreferenceLogPredictionMapper; + + public void createLikeSketchData() { + List userLikeGroups = userLikeGroupMapper.getMoreThan50UserLikeAccount(); + List accountIdList = userLikeGroups.stream().map(UserLikeGroup::getAccountId).collect(Collectors.toList()); + +// List accountIdList = new ArrayList<>(); +// accountIdList.add(4L); + + for (Long accountId : accountIdList) { + QueryWrapper userLikeQw = new QueryWrapper<>(); + userLikeQw.lambda().eq(UserLikeGroup::getAccountId, accountId); + userLikeQw.lambda().orderByDesc(UserLikeGroup::getCreateDate); + List userLikeGroups1 = userLikeGroupMapper.selectList(userLikeQw); + + // 总集合 + List allUserLikes = new ArrayList<>(); + + // 将所有 UserLike 收集到一个集合中 + for (UserLikeGroup likeGroup : userLikeGroups1) { + QueryWrapper userLikeQueryWrapper = new QueryWrapper<>(); + userLikeQueryWrapper.lambda().eq(UserLike::getUserLikeGroupId, likeGroup.getId()); + List userLikes = userLikeMapper.selectList(userLikeQueryWrapper); + allUserLikes.addAll(userLikes); + } + + // 根据时间排序 + allUserLikes.sort(Comparator.comparing(UserLike::getCreateDate)); + + // 计算 80% 和 20% 的分割 + int totalLikesSize = allUserLikes.size(); + int splitIndexLikes = (int) Math.ceil(totalLikesSize * 0.8); + + // 分割用户喜欢的集合 + List first80PercentLikes = allUserLikes.subList(0, splitIndexLikes); + List last20PercentLikes = allUserLikes.subList(splitIndexLikes, totalLikesSize); + + // 分别处理前 80% 和后 20% 的数据 + + // 处理前 80% + for (UserLike userLike : first80PercentLikes) { + Long designItemId = userLike.getDesignItemId(); + QueryWrapper designItemDetailQueryWrapper = new QueryWrapper<>(); + designItemDetailQueryWrapper.lambda().eq(DesignItemDetail::getDesignItemId, designItemId); + List designItemDetails = designItemDetailMapper.selectList(designItemDetailQueryWrapper); + for (DesignItemDetail designItemDetail : designItemDetails) { + if (designItemDetail.getType().equals("Body") || !designItemDetail.getPath().contains("aida-sys-image")) { + continue; + } + UserPreferenceLogTest userPreferenceLogTest = new UserPreferenceLogTest(); + userPreferenceLogTest.setPath(designItemDetail.getPath()); + userPreferenceLogTest.setAccountId(accountId); + userPreferenceLogTest.setUserLikeGroupId(userLike.getUserLikeGroupId()); + userPreferenceLogTest.setDataTime(designItemDetail.getCreateDate().toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime()); + userPreferenceLogMapper.insert(userPreferenceLogTest); + } + } + + // 处理后 20% + if (last20PercentLikes.size() == 0) { + // 输出没有记录的用户 ID + log.info("用户 ID: " + accountId + " 在后 20% 的 userLike 列表为空"); + } + + for (UserLike userLike : last20PercentLikes) { + Long designItemId = userLike.getDesignItemId(); + QueryWrapper designItemDetailQueryWrapper = new QueryWrapper<>(); + designItemDetailQueryWrapper.lambda().eq(DesignItemDetail::getDesignItemId, designItemId); + List designItemDetails = designItemDetailMapper.selectList(designItemDetailQueryWrapper); + for (DesignItemDetail designItemDetail : designItemDetails) { + + if (designItemDetail.getType().equals("Body") || !designItemDetail.getPath().contains("aida-sys-image")) { + continue; + } + + UserPreferenceLogPrediction userPreferenceLogPrediction = new UserPreferenceLogPrediction(); + userPreferenceLogPrediction.setPath(designItemDetail.getPath()); + userPreferenceLogPrediction.setAccountId(accountId); + userPreferenceLogPrediction.setUserLikeGroupId(userLike.getUserLikeGroupId()); + userPreferenceLogPrediction.setDataTime(designItemDetail.getCreateDate().toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime()); + userPreferenceLogPredictionMapper.insert(userPreferenceLogPrediction); + } + } + } + } + + @Resource + private CollectionMapper collectionMapper; + + @Resource + private CollectionElementMapper collectionElementMapper; + + @Resource + private CollectionElementService collectionElementService; + + @Resource + private PythonService pythonService; + + @Resource + private SysFileMapper sysFileMapper; + @Resource + private LibraryMapper libraryMapper; + + + public List getTop20Percent(List userLikeGroups) { + // 检查列表是否为空 + if (userLikeGroups == null || userLikeGroups.isEmpty()) { + return new ArrayList<>(); // 返回空列表 + } + + // 计算需要取的记录数量 + int size = userLikeGroups.size(); + int topCount = (int) Math.ceil(size * 0.2); // 取 20%,向上取整 + + // 返回前 20% 的记录 + return userLikeGroups.stream() + .limit(topCount) + .collect(Collectors.toList()); + } + public double freqAddTest() { +// List userLikeGroups = userLikeGroupMapper.getMoreThan50UserLikeAccount(); +// List accountIdList = userLikeGroups.stream().map(UserLikeGroup::getAccountId).collect(Collectors.toList()); + long totalAssemblyTime = 0L; // 总耗时(毫秒) + int assemblyCount = 0; // 组装次数 + + List accountIdList = new ArrayList<>(); + accountIdList.add(4L); + + for (Long accountId : accountIdList) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(UserLikeGroup::getAccountId, accountId); + qw.lambda().orderByDesc(UserLikeGroup::getCreateDate); + List userLikeGroups1 = userLikeGroupMapper.selectList(qw); + + // 取前 20% + List top20Percent = getTop20Percent(userLikeGroups1); + List collectionIdList = top20Percent.stream().map(UserLikeGroup::getCollectionId).collect(Collectors.toList()); + // size 51 + for (Long collectionId : collectionIdList) { + QueryWrapper designQueryWrapper = new QueryWrapper<>(); + designQueryWrapper.lambda().eq(Design::getCollectionId, collectionId); + Design design = designMapper.selectList(designQueryWrapper).get(0); + + Collection collection = collectionMapper.selectById(collectionId); + + QueryWrapper elementQueryWrapper = new QueryWrapper<>(); + elementQueryWrapper.lambda().eq(CollectionElement::getCollectionId, collectionId); + List collectionElements = collectionElementMapper.selectList(elementQueryWrapper); + + List sketchboard = collectionElements.stream().filter(o -> o.equals("Sketchboard")).collect(Collectors.toList()); + + if (design.getSingleOverall().equals("single")) { + continue; + } + + DesignCollectionDTO designCollectionDTO = new DesignCollectionDTO(); + designCollectionDTO.setSketchBoards(CopyUtil.copyList(sketchboard, CollectionSketchDTO.class)); + designCollectionDTO.setSystemScale(design.getSystemScale()); + designCollectionDTO.setTemplateId(design.getTemplateId()); + designCollectionDTO.setModelType(design.getModelType()); + designCollectionDTO.setSingleOverall(design.getSingleOverall()); + designCollectionDTO.setTimeZone(new Date().toString()); + designCollectionDTO.setDesignNum(8); + + Long templateId = design.getTemplateId(); + String modelType = design.getModelType(); + if (modelType.equals("System")) { + SysFile sysFile = sysFileMapper.selectById(templateId); + designCollectionDTO.setModelSex(sysFile.getLevel2Type()); + } else { + Library library = libraryMapper.selectById(templateId); + if (Objects.isNull(library)) { + designCollectionDTO.setModelSex("Female"); + } else { + designCollectionDTO.setModelSex(library.getLevel2Type()); + } + } + + ValidateElementVO elementVO = collectionElementService.validateElement(designCollectionDTO); + elementVO.setAccountId(accountId); + + // 记录开始时间 + long startTime = System.currentTimeMillis(); + log.info("组装开始时间:" + new Date(startTime).toString()); + + pythonService.covertDesignParamTest( + designCollectionDTO.getSystemScale(), + designCollectionDTO.getSingleOverall(), + designCollectionDTO.getSwitchCategory(), + elementVO, + "testProcessId", + null, + collectionId + ); + + // 记录结束时间 + long endTime = System.currentTimeMillis(); + log.info("组装结束时间:" + new Date(endTime).toString()); + + // 累加组装耗时 + totalAssemblyTime += (endTime - startTime); + assemblyCount++; + } + } + + // 计算平均组装时间 + if (assemblyCount > 0) { + double averageAssemblyTimeInSeconds = totalAssemblyTime / (double) assemblyCount / 1000.0; + log.info("平均组装时间:{} 秒", averageAssemblyTimeInSeconds); + return averageAssemblyTimeInSeconds; + } else { + log.info("没有执行任何组装操作。"); + return 0.0; + } + } + +// public void statisticalCoincidenceDegree() { +// // 创建工作簿和表格 +// Workbook workbook = new XSSFWorkbook(); +// Sheet sheet = workbook.createSheet("用户数据"); +// +// // 创建表头 +// Row headerRow = sheet.createRow(0); +// headerRow.createCell(0).setCellValue("用户 ID"); +// headerRow.createCell(1).setCellValue("Test 匹配路径数量"); +// headerRow.createCell(2).setCellValue("Prediction 总路径数量"); +// headerRow.createCell(3).setCellValue("重合度"); +// +// // 假设 userLikeGroupMapper 和其他映射器已经定义并初始化 +// List userLikeGroups = userLikeGroupMapper.getMoreThan50UserLikeAccount(); +// List accountIdList = userLikeGroups.stream().map(UserLikeGroup::getAccountId).collect(Collectors.toList()); +// +// int rowIndex = 1; // 从第二行开始插入数据 +// for (Long accountId : accountIdList) { +// QueryWrapper qw1 = new QueryWrapper<>(); +// qw1.lambda().eq(UserPreferenceLogTest::getAccountId, accountId); +// List testList = userPreferenceLogMapper.selectList(qw1); +// +// QueryWrapper qw2 = new QueryWrapper<>(); +// qw2.lambda().eq(UserPreferenceLogPrediction::getAccountId, accountId); +// List predictionList = userPreferenceLogPredictionMapper.selectList(qw2); +// +// // 将 testPaths 和 predictionPaths 转为 Set 来计算重合度 +// Set testPaths = testList.stream() +// .map(UserPreferenceLogTest::getPath) +// .collect(Collectors.toSet()); +// +// Set predictionPaths = predictionList.stream() +// .map(UserPreferenceLogPrediction::getPath) +// .collect(Collectors.toSet()); +// +// // 计算匹配的路径数量(重合部分) +// Set intersection = new HashSet<>(testPaths); +// intersection.retainAll(predictionPaths); // 计算交集 +// +// // 计算重合度 +// double overlapRatio = (double) intersection.size() / predictionPaths.size(); +// +// // 将结果写入 Excel 文件 +// Row row = sheet.createRow(rowIndex++); +// row.createCell(0).setCellValue(accountId); +// row.createCell(1).setCellValue(intersection.size()); // 匹配路径数量 +// row.createCell(2).setCellValue(predictionPaths.size()); // Prediction 总路径数量 +// row.createCell(3).setCellValue(overlapRatio); // 重合度 +// +// // 输出到日志 +// log.info("用户 ID: " + accountId); +// log.info("Test 匹配路径数量: " + intersection.size()); +// log.info("Prediction 总路径数量: " + predictionPaths.size()); +// log.info("重合度: " + overlapRatio); +// } +// +// // 自动调整列宽 +// for (int i = 0; i < 4; i++) { +// sheet.autoSizeColumn(i); +// } +// +// // 写入 Excel 文件 +// try (FileOutputStream fileOut = new FileOutputStream("用户数据.xlsx")) { +// workbook.write(fileOut); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// +// System.out.println("Excel 文件已成功生成!"); +// } + + @Resource + private SketchDataMapper sketchDataMapper; + + public void runMetricsComparison() { + Long accountId = 13765L; + Map> metricsComparison = calculateMetricsComparison(accountId); + + System.out.println("Old Algorithm Metrics: " + metricsComparison.get("OldAlgorithm")); + System.out.println("New Algorithm Metrics: " + metricsComparison.get("NewAlgorithm")); + } + + public Map> calculateMetricsComparison(Long accountId) { + // 定义结果存储 + Map> comparisonMetrics = new HashMap<>(); + + // 分别计算新旧算法的指标 + Map oldAlgorithmMetrics = calculateMetricsForType(accountId, 1); // 旧算法 + Map newAlgorithmMetrics = calculateMetricsForType(accountId, 2); // 新算法 + + // 存入对比结果 + comparisonMetrics.put("OldAlgorithm", oldAlgorithmMetrics); + comparisonMetrics.put("NewAlgorithm", newAlgorithmMetrics); + + return comparisonMetrics; + } + + private Map calculateMetricsForType(Long accountId, int type) { + // 查询指定算法类型的预测池 Sketch 列表 + List predictionPaths = sketchDataMapper.selectList( + new QueryWrapper() + .lambda() + .eq(SketchData::getAccountId, accountId) + .eq(SketchData::getType, type) + ).stream().map(SketchData::getPath).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(predictionPaths)) { + throw new IllegalArgumentException("算法类型 " + type + " 的预测池为空,无法计算指标"); + } + + // 查询用户喜欢的 Sketch 列表 + Set likedPaths = userPreferenceLogPredictionMapper.selectList( + new QueryWrapper() + .lambda() + .eq(UserPreferenceLogPrediction::getAccountId, accountId) + ).stream().map(UserPreferenceLogPrediction::getPath).collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(likedPaths)) { + throw new IllegalArgumentException("用户喜欢的列表为空,无法计算指标"); + } + + // 计算预测池中用户喜欢的 Sketch 数量 + long likedInPrediction = predictionPaths.stream() + .filter(likedPaths::contains) + .count(); + +// // 计算 Precision 和 Recall +// double precision = (double) likedInPrediction / predictionPaths.size(); +// double recall = (double) likedInPrediction / likedPaths.size(); +// +// // 计算 F1 Score +// double f1Score = (precision + recall > 0) +// ? 2 * precision * recall / (precision + recall) +// : 0; + + // 计算 Hit Ratio (HR) + double hitRatio = (double) likedInPrediction / likedPaths.size(); + + // 返回结果 + Map metrics = new HashMap<>(); +// metrics.put("precision", precision); +// metrics.put("recall", recall); +// metrics.put("f1Score", f1Score); + metrics.put("hitRatio", hitRatio); + return metrics; + } + + public Map calculateMetrics(Long accountId, Long collectionId) { + // 查询预测池 Sketch 列表 + List predictionPaths = sketchDataMapper.selectList( + new QueryWrapper() + .lambda() + .eq(SketchData::getAccountId, accountId) + .eq(SketchData::getCollectionId, collectionId) + .eq(SketchData::getType, 2) // 2: 新算法 + ).stream().map(SketchData::getPath).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(predictionPaths)) { + throw new IllegalArgumentException("预测池为空,无法计算指标"); + } + + // 查询用户喜欢的 Sketch 列表 + List likedPaths = userPreferenceLogPredictionMapper.selectList( + new QueryWrapper() + .lambda() + .eq(UserPreferenceLogPrediction::getAccountId, accountId) + ).stream().map(UserPreferenceLogPrediction::getPath).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(likedPaths)) { + throw new IllegalArgumentException("用户喜欢的列表为空,无法计算指标"); + } + + // 计算预测池中用户喜欢的 Sketch 数量 + long likedInPrediction = predictionPaths.stream() + .filter(likedPaths::contains) + .count(); + + // 计算 Precision 和 Recall + double precision = (double) likedInPrediction / predictionPaths.size(); + double recall = (double) likedInPrediction / likedPaths.size(); + + // 返回结果 + Map metrics = new HashMap<>(); + metrics.put("precision", precision); + metrics.put("recall", recall); + return metrics; + } + + @Resource + private RedisUtil redisUtil; + + private void runComparisonAndRecordResults(int iterations) { + // 创建工作簿和表格 + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("Metrics Data"); + + // 创建表头 + Row headerRow = sheet.createRow(0); + headerRow.createCell(0).setCellValue("Iteration"); + headerRow.createCell(1).setCellValue("Algorithm Sketch Num"); + headerRow.createCell(2).setCellValue("Old Algorithm HitRatio"); + headerRow.createCell(3).setCellValue("New Algorithm HitRatio"); + headerRow.createCell(4).setCellValue("Average Assembly Time (s)"); + headerRow.createCell(5).setCellValue("确定第一件sketch时间 (s)"); // 第一部分时间 + headerRow.createCell(6).setCellValue("获取特征值时间 (s)"); // 第二部分时间 + headerRow.createCell(7).setCellValue("搭配另外sketch时间 (s)"); // 第三部分时间 + + int rowIndex = 1; // 数据起始行 + + for (int i = 1; i <= iterations; i++) { + // 清除 sketch_data 表 + sketchDataMapper.delete(new QueryWrapper<>()); + + // 获取平均组装时间 + double averageAssemblyTime = freqAddTest(); + + // 动态获取用户的 collectionIds + Long accountId = 4L; // 假设用户 ID 为 4 + List collectionIds = getCollectionIdsByAccount(accountId); + + if (CollectionUtils.isEmpty(collectionIds)) { + log.warn("用户 {} 没有相关的 collectionId 数据,跳过当前迭代", accountId); + continue; + } + + // 记录每次迭代的命中率和总时间 + double totalOldHitRatio = 0.0; + double totalNewHitRatio = 0.0; + +// List collectionIds = getCollectionIdsByAccount(4L); + + for (Long collectionId : collectionIds) { + Map hitRatios = calculateHitRatioByType(accountId, collectionId); + totalOldHitRatio += hitRatios.getOrDefault(1, 0.0); // type=1 的命中率 + totalNewHitRatio += hitRatios.getOrDefault(2, 0.0); // type=2 的命中率 + } + + // 计算平均命中率 + double averageOldHitRatio = totalOldHitRatio / collectionIds.size(); + double averageNewHitRatio = totalNewHitRatio / collectionIds.size(); + + // 获取 Sketch 数量 + Long newAlgorithmSketchNum = sketchDataMapper.selectCount( + new QueryWrapper().lambda().eq(SketchData::getType, 2) + ); + + // 从 Redis 获取三部分的耗时(秒) + double part1Time = redisUtil.getFirstSketchTime() / collectionIds.size(); // 第一部分:Sketch 耗时 + double part2Time = redisUtil.getGetAttributeRecognitionTime() / collectionIds.size(); // 第二部分:特征值获取耗时 + double part3Time = redisUtil.getOtherSketchTime() / collectionIds.size(); // 第三部分:搭配 Sketch 耗时 + + // 记录数据到 Excel 表格 + Row row = sheet.createRow(rowIndex++); + row.createCell(0).setCellValue(i); + row.createCell(1).setCellValue(newAlgorithmSketchNum); + row.createCell(2).setCellValue(averageOldHitRatio); // 旧算法命中率 + row.createCell(3).setCellValue(averageNewHitRatio); // 新算法命中率 + row.createCell(4).setCellValue(averageAssemblyTime); // 平均组装时间 + row.createCell(5).setCellValue(part1Time); // 第一部分耗时 + row.createCell(6).setCellValue(part2Time); // 第二部分耗时 + row.createCell(7).setCellValue(part3Time); // 第三部分耗时 + + log.info("Iteration {}: Old Algorithm Avg HitRatio = {}, New Algorithm Avg HitRatio = {}, New Sketch Num = {}, Average Assembly Time = {} s, " + + "Part 1 Time = {} s, Part 2 Time = {} s, Part 3 Time = {} s", + i, averageOldHitRatio, averageNewHitRatio, newAlgorithmSketchNum, averageAssemblyTime, part1Time, part2Time, part3Time); + + // 清除 Redis 缓存 + redisUtil.clearTaskElapsedTimeCache(); + } + + // 写入 Excel 文件 + try (FileOutputStream fileOut = new FileOutputStream("metrics_data.xlsx")) { + workbook.write(fileOut); + log.info("Excel 文件已成功生成: metrics_data.xlsx"); + } catch (IOException e) { + log.error("写入 Excel 文件失败", e); + } + } + + public Map calculateHitRatioByType(Long accountId, Long collectionId) { + // 存储 type=1 和 type=2 的命中率 + Map hitRatios = new HashMap<>(); + + // 获取用户 likedSketch 列表 + Set likedPaths = userPreferenceLogPredictionMapper.selectList( + new QueryWrapper() + .lambda() + .eq(UserPreferenceLogPrediction::getAccountId, accountId) + ).stream().map(UserPreferenceLogPrediction::getPath).collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(likedPaths)) { + throw new IllegalArgumentException("用户喜欢的列表为空,无法计算命中率"); + } + + // 遍历 type=1 和 type=2 + for (int type : Arrays.asList(1, 2)) { + // 查询当前类型的预测池数据 + List predictionPaths = sketchDataMapper.selectList( + new QueryWrapper() + .lambda() + .eq(SketchData::getAccountId, accountId) + .eq(SketchData::getCollectionId, collectionId) + .eq(SketchData::getType, type) + ).stream().map(SketchData::getPath).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(predictionPaths)) { + log.warn("类型 {} 的 collectionId {} 的预测池为空,命中率设置为 0", type, collectionId); + hitRatios.put(type, 0.0); + continue; + } + + // 计算命中数量 + long likedInPrediction = predictionPaths.stream() + .filter(likedPaths::contains) + .count(); + + // 计算命中率 + double hitRatio = (double) likedInPrediction / predictionPaths.size(); + hitRatios.put(type, hitRatio); + } + + return hitRatios; + } + + +// private double getAverageAssemblyTime() { +// // 假设 freqAddTest 中已经累加了总组装时间和次数 +// // 替换为实际的获取平均组装时间的逻辑 +// return totalAssemblyTime / (double) assemblyCount / 1000.0; // 转换为秒 +// } + + public double calculateSingleDesignHitRatio(Long accountId, int type) { + // 查询指定算法类型的预测池 Sketch 列表 + List predictionPaths = sketchDataMapper.selectList( + new QueryWrapper() + .lambda() + .eq(SketchData::getAccountId, accountId) + .eq(SketchData::getType, type) // type: 1 旧算法,2 新算法 + ).stream().map(SketchData::getPath).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(predictionPaths)) { + throw new IllegalArgumentException("预测池为空,无法计算指标"); + } + + // 查询用户喜欢的 Sketch 列表 + Set likedPaths = userPreferenceLogPredictionMapper.selectList( + new QueryWrapper() + .lambda() + .eq(UserPreferenceLogPrediction::getAccountId, accountId) + ).stream().map(UserPreferenceLogPrediction::getPath).collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(likedPaths)) { + throw new IllegalArgumentException("用户喜欢的列表为空,无法计算指标"); + } + + // 计算预测池中用户喜欢的 Sketch 数量 + long likedInPrediction = predictionPaths.stream() + .filter(likedPaths::contains) + .count(); + + // 计算 Hit Ratio (HR) + return (double) likedInPrediction / likedPaths.size(); + } + + public Map calculateAverageHitRatio(Long accountId, List collectionIds) { + // 存储新旧算法的平均命中率 + Map averageHitRatios = new HashMap<>(); + Map> hitRatiosByType = new HashMap<>(); + + // 初始化列表存储每个 collection 的命中率 + hitRatiosByType.put(1, new ArrayList<>()); // type=1 + hitRatiosByType.put(2, new ArrayList<>()); // type=2 + + // 获取用户 likedSketch 列表 + Set likedPaths = userPreferenceLogPredictionMapper.selectList( + new QueryWrapper() + .lambda() + .eq(UserPreferenceLogPrediction::getAccountId, accountId) + ).stream().map(UserPreferenceLogPrediction::getPath).collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(likedPaths)) { + throw new IllegalArgumentException("用户喜欢的列表为空,无法计算命中率"); + } + + // 遍历每个 collectionId + for (Long collectionId : collectionIds) { + // 遍历 type=1 和 type=2 + for (int type : Arrays.asList(1, 2)) { + // 获取当前类型的生成数据 + List predictionPaths = sketchDataMapper.selectList( + new QueryWrapper() + .lambda() + .eq(SketchData::getAccountId, accountId) + .eq(SketchData::getCollectionId, collectionId) + .eq(SketchData::getType, type) + ).stream().map(SketchData::getPath).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(predictionPaths)) { + log.warn("类型 {} 的 collectionId {} 的预测池为空,跳过计算", type, collectionId); + continue; + } + + // 计算命中数量 + long likedInPrediction = predictionPaths.stream() + .filter(likedPaths::contains) + .count(); + + // 计算命中率 + double hitRatio = (double) likedInPrediction / predictionPaths.size(); + hitRatiosByType.get(type).add(hitRatio); // 存储每个 collection 的命中率 + } + } + + // 计算平均命中率 + hitRatiosByType.forEach((type, hitRatios) -> { + double averageHitRatio = hitRatios.stream().mapToDouble(Double::doubleValue).average().orElse(0.0); + averageHitRatios.put(type, averageHitRatio); + }); + + return averageHitRatios; + } + + public void testAverageHitRatio(Long accountId) { + + // 动态获取 collectionId 列表 + List collectionIds = getCollectionIdsByAccount(accountId); + + if (CollectionUtils.isEmpty(collectionIds)) { + log.warn("用户 {} 没有相关的 collectionId 数据", accountId); + return; + } + + // 计算平均命中率 + Map averageHitRatios = calculateAverageHitRatio(accountId, collectionIds); + + // 输出结果 + log.info("用户 {} 的平均命中率:{}", accountId, averageHitRatios); + + double ratioType1 = averageHitRatios.getOrDefault(1, 0.0); + double ratioType2 = averageHitRatios.getOrDefault(2, 0.0); + log.info("命中率对比:type=1 的平均命中率为 {:.2%},type=2 的平均命中率为 {:.2%}", ratioType1, ratioType2); + } + + public List getCollectionIdsByAccount(Long accountId) { + // 查询该用户的所有 collectionId + return sketchDataMapper.selectList( + new QueryWrapper() + .lambda() + .eq(SketchData::getAccountId, accountId) // 筛选用户 + .select(SketchData::getCollectionId) // 只查询 collectionId + ).stream() + .map(SketchData::getCollectionId) + .distinct() // 去重,确保 collectionId 唯一 + .collect(Collectors.toList()); + } + + @Resource + private RedisTemplate redisTemplate; + + public void saveUserLikedSketchDataToRedis(Long userId) { + // Redis 键前缀 + String redisKey = "user_liked_sketch:" + userId; + // 1. 清除该用户相关的 Redis 缓存 + // 删除所有 sketch 的喜欢次数记录 + redisTemplate.delete(redisKey); + + // 删除最大喜欢次数的缓存 + redisTemplate.delete(redisKey + ":maxLikes"); + + // 1. 查询用户喜欢的所有 sketch 数据 + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(UserPreferenceLogTest::getAccountId, userId); + List userPreferenceLogTests = userPreferenceLogMapper.selectList(qw); + + + // 最大喜欢次数 + int maxLikes = 0; + + // 2. 遍历所有用户的喜欢记录,更新 Redis 中的喜欢次数 + for (UserPreferenceLogTest userPreferenceLogTest : userPreferenceLogTests) { + String sketchPath = userPreferenceLogTest.getPath(); + + // 使用 Redis HINCRBY 增加某个 sketch path 的喜欢次数 + Long newCount = redisTemplate.opsForHash().increment(redisKey, sketchPath, 1); + + // 更新最大喜欢次数 + maxLikes = Math.max(maxLikes, newCount.intValue()); + } + + // 3. 将最大喜欢次数存入 Redis + redisTemplate.opsForValue().set(redisKey + ":maxLikes", String.valueOf(maxLikes)); + } + +// public void getAccountLikedNumRedis() { +// String redisKey = "user_liked_sketch:" + 4L; +// +// redisUtil +// +// // 尝试从 Redis 获取该 sketch path 的喜欢次数 +// Integer likedCount = (Integer) redisTemplate.opsForHash().get(redisKey); +// } + + public void saveDataToNumpyFormat() { + Long accountId = 4L; // 目标用户 ID + + // 保存历史数据 + saveHistoryData(accountId); + + // 保存目标数据 + saveTargetData(accountId); + } + + private void saveHistoryData(Long accountId) { + // 查询用户历史喜欢的 Sketch 及其次数 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda() + .eq(UserPreferenceLogTest::getAccountId, accountId) + .groupBy(UserPreferenceLogTest::getPath); + + queryWrapper.select("path", "COUNT(*) AS count"); + + List> historyData = userPreferenceLogMapper.selectMaps(queryWrapper); + + // 将数据保存为文本文件 + try (FileWriter writer = new FileWriter("history_data.txt")) { + for (Map row : historyData) { + String path = (String) row.get("path"); + Long count = (Long) row.get("count"); + writer.write(path + "," + count + "\n"); + } + System.out.println("历史数据已保存到 history_data.txt"); + } catch (IOException e) { + System.err.println("保存历史数据时发生错误: " + e.getMessage()); + } + } + + private void saveTargetData(Long accountId) { + // 查询用户即将喜欢的 Sketch 集合 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda() + .eq(UserPreferenceLogPrediction::getAccountId, accountId) + .groupBy(UserPreferenceLogPrediction::getPath); + + queryWrapper.select("path"); + + List> targetData = userPreferenceLogPredictionMapper.selectMaps(queryWrapper); + + // 将数据保存为文本文件 + try (FileWriter writer = new FileWriter("target_data.txt")) { + for (Map row : targetData) { + String path = (String) row.get("path"); + writer.write(path + "\n"); + } + System.out.println("目标数据已保存到 target_data.txt"); + } catch (IOException e) { + System.err.println("保存目标数据时发生错误: " + e.getMessage()); + } + } } 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 f7b9ea1a..eb242a1a 100644 --- a/src/main/java/com/ai/da/common/utils/RedisUtil.java +++ b/src/main/java/com/ai/da/common/utils/RedisUtil.java @@ -1,5 +1,9 @@ package com.ai.da.common.utils; +import com.ai.da.python.vo.DesignPythonObject; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; @@ -8,6 +12,8 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -279,6 +285,77 @@ public class RedisUtil { redisTemplate.expire(redisKey, 5, TimeUnit.MINUTES); } + public void addPathToCache(Long collectionId, Long userId, String path) { + // Redis 中的键,唯一标识由 collectionId 和 userId 组成 + String redisKey = "path:cache:" + collectionId + ":" + userId; + + // 增加路径的计数 + redisTemplate.opsForHash().increment(redisKey, path, 1); + + // 设置过期时间为 2 小时(7200 秒) + redisTemplate.expire(redisKey, 8, TimeUnit.HOURS); + } + + public int getPathUsageCount(Long collectionId, Long userId, String path) { + String redisKey = "path:cache:" + collectionId + ":" + userId; + + // 获取路径的使用次数 + Object count = redisTemplate.opsForHash().get(redisKey, path); + return count != null ? Integer.parseInt(count.toString()) : 0; + } + + public void addAssembledObjects(Long collectionId, Set assembledObjects) { + // Redis 中的键,使用 collectionId 来唯一标识 + String redisKey = "collection:assembledObjects:" + collectionId; + + // 将 assembledObjects 转换为 JSON 格式存储,避免直接存储对象 + String assembledObjectsJson = convertToJson(assembledObjects); + + // 使用 Redis 的 set 操作更新集合 + redisTemplate.opsForValue().set(redisKey, assembledObjectsJson); + + // 设置过期时间为 5 分钟(300 秒) + redisTemplate.expire(redisKey, 30, TimeUnit.MINUTES); + } + + // 将 Set 转换为 JSON 格式 + private String convertToJson(Set assembledObjects) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(assembledObjects); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return null; + } + } + + public Set getAssembledObjects(Long collectionId) { + // Redis 中的键,使用 collectionId 来唯一标识 + String redisKey = "collection:assembledObjects:" + collectionId; + + // 从 Redis 获取存储的 JSON 字符串 + String assembledObjectsJson = (String) redisTemplate.opsForValue().get(redisKey); + + if (assembledObjectsJson == null) { + return new HashSet<>(); // 如果没有找到数据,返回一个空的 Set + } + + // 将 JSON 字符串转换为 Set + return convertFromJson(assembledObjectsJson); + } + + // 将 JSON 字符串转换为 Set + private Set convertFromJson(String json) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + // 使用 TypeReference 来指定目标类型是 Set + return objectMapper.readValue(json, new TypeReference>() {}); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return new HashSet<>(); // 如果转换失败,返回空的 Set + } + } + public final static String PAYMENT_INFO_LAST_SCAN_TIME = "PaymentInfoLastScanTime"; public final static String AFFILIATE_LINK_VIEW_KEY = "AffiliateLink:view:"; @@ -293,13 +370,126 @@ public class RedisUtil { return redisTemplate.opsForValue().increment(key, 0); } - public void batchDeleteKeysWithSamePrefix(String prefix){ - Set keys = redisTemplate.keys(prefix + "*"); - assert keys != null; - if (!keys.isEmpty()){ - redisTemplate.delete(keys); + /** + * 记录任务的耗时到Redis + * @param taskKey 任务标识,如 "taskA" + * @param elapsedTime 本次耗时,单位为毫秒 + */ + public void recordTaskElapsedTime(String taskKey, long elapsedTime) { + String hashKey = "task:stats"; + + // 累加总耗时 + redisTemplate.opsForHash().increment(hashKey, taskKey + ":totalTime", elapsedTime); + + // 增加计数器 + redisTemplate.opsForHash().increment(hashKey, taskKey + ":count", 1); + } + + /** + * 获取任务的平均耗时 + * @param taskKey 任务标识,如 "taskA" + * @return 平均耗时(毫秒) + */ + public double getTaskAverageTime(String taskKey) { + String hashKey = "task:stats"; + + // 获取总耗时和计数 + Object totalTime = redisTemplate.opsForHash().get(hashKey, taskKey + ":totalTime"); + Object count = redisTemplate.opsForHash().get(hashKey, taskKey + ":count"); + + // 计算平均值 + if (totalTime == null || count == null) { + return 0; + } + return Double.parseDouble(totalTime.toString()) / Long.parseLong(count.toString()); + } + + /** + * 清除指定任务的统计数据 + * @param taskKey 任务标识,如 "taskA" + */ + public void clearTaskStats(String taskKey) { + String hashKey = "task:stats"; + + // 删除总耗时和计数器 + redisTemplate.opsForHash().delete(hashKey, taskKey + ":totalTime", taskKey + ":count"); + } + + public void recordTaskElapsedTime(String taskKey, double elapsedTimeInSeconds) { + // 将耗时转换为 BigDecimal,并四舍五入保留四位小数 + BigDecimal elapsedTime = new BigDecimal(elapsedTimeInSeconds).setScale(4, RoundingMode.HALF_UP); + + // 累加总耗时(以毫秒为单位) + redisTemplate.opsForHash().increment("task:stats", taskKey + ":totalTime", elapsedTime.doubleValue()); + + // 增加计数器 + redisTemplate.opsForHash().increment("task:stats", taskKey + ":count", 1); + } + + // 获取第一部分(Sketch)耗时 + public double getFirstSketchTime() { + // 获取 "firstSketchTime:totalTime" 对应的值,并返回(单位为秒) + Object time = redisTemplate.opsForHash().get("task:stats", "firstSketchTime:totalTime"); + return time != null ? (double) time : 0.0; + } + + // 获取第二部分(获取特征值)耗时 + public double getGetAttributeRecognitionTime() { + // 获取 "getAttributeRecognitionTime:totalTime" 对应的值,并返回(单位为秒) + Object time = redisTemplate.opsForHash().get("task:stats", "getAttributeRecognitionTime:totalTime"); + return time != null ? (double) time : 0.0; + } + + // 获取第三部分(搭配 Sketch)耗时 + public double getOtherSketchTime() { + // 获取 "otherSketchTime:totalTime" 对应的值,并返回(单位为秒) + Object time = redisTemplate.opsForHash().get("task:stats", "otherSketchTime:totalTime"); + return time != null ? (double) time : 0.0; + } + + // 清理三部分的缓存 + public void clearTaskElapsedTimeCache() { + // 删除第一部分的缓存 + redisTemplate.opsForHash().delete("task:stats", "firstSketchTime:totalTime"); + redisTemplate.opsForHash().delete("task:stats", "firstSketchTime:count"); + + // 删除第二部分的缓存 + redisTemplate.opsForHash().delete("task:stats", "getAttributeRecognitionTime:totalTime"); + redisTemplate.opsForHash().delete("task:stats", "getAttributeRecognitionTime:count"); + + // 删除第三部分的缓存 + redisTemplate.opsForHash().delete("task:stats", "otherSketchTime:totalTime"); + redisTemplate.opsForHash().delete("task:stats", "otherSketchTime:count"); + } + + public boolean incrementLikeCount(Long userId, String sketchPath) { + String redisKey = "user_like_count:" + userId; + try { + redisTemplate.opsForHash().increment(redisKey, sketchPath, 1); + return true; + } catch (Exception e) { + log.error("Error incrementing like count for userId {} and sketchPath {}: {}", userId, sketchPath, e.getMessage()); + return false; } } + public int getLikeCount(Long userId, String sketchPath) { + String redisKey = "user_like_count:" + userId; + Object count = redisTemplate.opsForHash().get(redisKey, sketchPath); + return count != null ? Integer.parseInt(count.toString()) : 0; + } + + public void storeMaxLikeCount(Long userId, int maxLikeCount) { + String redisKey = "user_max_like_count:" + userId; + redisTemplate.opsForValue().set(redisKey, String.valueOf(maxLikeCount)); + } + + public int getMaxLikeCount(Long userId) { + String redisKey = "user_max_like_count:" + userId; + String maxLikeCount = redisTemplate.opsForValue().get(redisKey); + return maxLikeCount != null ? Integer.parseInt(maxLikeCount) : 0; + } + + public final static String STRIPE_EXCEPTION_LOG = "StripeException:"; } diff --git a/src/main/java/com/ai/da/controller/ProjectController.java b/src/main/java/com/ai/da/controller/ProjectController.java new file mode 100644 index 00000000..b99183b8 --- /dev/null +++ b/src/main/java/com/ai/da/controller/ProjectController.java @@ -0,0 +1,83 @@ +package com.ai.da.controller; + +import com.ai.da.common.response.PageBaseResponse; +import com.ai.da.common.response.Response; +import com.ai.da.model.dto.ModuleSaveDTO; +import com.ai.da.model.dto.ProjectDTO; +import com.ai.da.model.dto.ProjectQueryDTO; +import com.ai.da.model.vo.*; +import com.ai.da.service.UserLikeGroupService; +import com.ai.da.service.WorkspaceService; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +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; + +import javax.annotation.Resource; +import javax.validation.Valid; + +@Api(tags = "Project模块") +@Slf4j +@RestController +@RequestMapping("/api/project") +public class ProjectController { + + @Resource + private WorkspaceService workspaceService; + + @Resource + private UserLikeGroupService userLikeGroupService; + + @PostMapping("/saveOrUpdate") + @ApiOperationSupport(order = 1) + @ApiOperation(value = "新增或编辑", notes = "传入project") + public Response saveOrUpdateProject(@Valid @RequestBody ProjectDTO projectDTO) { + return Response.success(workspaceService.saveOrUpdateProject(projectDTO)); + } + + @PostMapping("/page") + @ApiOperationSupport(order = 2) + @ApiOperation(value = "分页查询", notes = "传入project") + public Response> page(@Valid @RequestBody ProjectQueryDTO projectQueryDTO) { + return Response.success(PageBaseResponse.success(userLikeGroupService.getPage(projectQueryDTO))); + } + +// @PostMapping("/detail") +// @ApiOperationSupport(order = 3) +// @ApiOperation(value = "详情", notes = "传入project") +// public Response saveOrUpdateProject(@Valid @RequestBody ProjectDTO projectDTO) { +// return Response.success(workspaceService.saveOrUpdateProject(projectDTO)); +// } +// + @PostMapping("/choose") + @ApiOperationSupport(order = 4) + @ApiOperation(value = "选择", notes = "传入project") + public Response choose(@Valid @RequestBody ProjectDTO projectDTO) { + return Response.success(userLikeGroupService.choose(projectDTO)); + } + + @PostMapping("/getModuleContent") + @ApiOperationSupport(order = 5) + @ApiOperation(value = "获取模块内容", notes = "传入project") + public Response getModuleContent(@Valid @RequestBody ProjectDTO projectDTO) { + return Response.success(userLikeGroupService.getModuleContent(projectDTO)); + } + + @PostMapping("/saveModuleContent") + @ApiOperationSupport(order = 6) + @ApiOperation(value = "存储模块内容", notes = "传入project") + public Response saveModuleContent(@Valid @RequestBody ModuleSaveDTO moduleSaveDTO) { + return Response.success(userLikeGroupService.saveModuleContent(moduleSaveDTO)); + } +// +// @PostMapping("/delete") +// @ApiOperationSupport(order = 5) +// @ApiOperation(value = "删除", notes = "传入project") +// public Response saveOrUpdateProject(@Valid @RequestBody ProjectDTO projectDTO) { +// return Response.success(workspaceService.saveOrUpdateProject(projectDTO)); +// } +} diff --git a/src/main/java/com/ai/da/controller/WorkspaceController.java b/src/main/java/com/ai/da/controller/WorkspaceController.java index 436da3d8..c22f5436 100644 --- a/src/main/java/com/ai/da/controller/WorkspaceController.java +++ b/src/main/java/com/ai/da/controller/WorkspaceController.java @@ -3,6 +3,7 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; import com.ai.da.mapper.primary.entity.Style; import com.ai.da.mapper.primary.entity.Workspace; +import com.ai.da.model.dto.ProjectDTO; import com.ai.da.model.dto.WorkspaceDTO; import com.ai.da.model.dto.WorkspaceSaveDTO; import com.ai.da.model.enums.BizJson; @@ -131,4 +132,11 @@ public class WorkspaceController { public Response> styleList() { return Response.success(workspaceService.styleList()); } + + @PostMapping("/saveOrUpdateProject") + @ApiOperationSupport(order = 3) + @ApiOperation(value = "新增或编辑", notes = "传入project") + public Response saveOrUpdateProject(@Valid @RequestBody ProjectDTO projectDTO) { + return Response.success(workspaceService.saveOrUpdateProject(projectDTO)); + } } diff --git a/src/main/java/com/ai/da/mapper/primary/CollectionElementMapper.java b/src/main/java/com/ai/da/mapper/primary/CollectionElementMapper.java index 55a3188a..d32a80b2 100644 --- a/src/main/java/com/ai/da/mapper/primary/CollectionElementMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/CollectionElementMapper.java @@ -3,6 +3,8 @@ package com.ai.da.mapper.primary; import com.ai.da.common.config.mybatis.plus.CommonMapper; import com.ai.da.mapper.primary.entity.CollectionElement; +import java.util.List; + /** * Mapper 接口 * @@ -11,4 +13,5 @@ import com.ai.da.mapper.primary.entity.CollectionElement; */ public interface CollectionElementMapper extends CommonMapper { + List selectDeleteList(); } diff --git a/src/main/java/com/ai/da/mapper/primary/CollectionMapper.java b/src/main/java/com/ai/da/mapper/primary/CollectionMapper.java index b9a7bd1e..820bbb85 100644 --- a/src/main/java/com/ai/da/mapper/primary/CollectionMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/CollectionMapper.java @@ -3,6 +3,8 @@ package com.ai.da.mapper.primary; import com.ai.da.common.config.mybatis.plus.CommonMapper; import com.ai.da.mapper.primary.entity.Collection; +import java.util.List; + /** * Mapper 接口 * @@ -12,4 +14,6 @@ import com.ai.da.mapper.primary.entity.Collection; public interface CollectionMapper extends CommonMapper { //返回插入数据后生成的主键 Long insertCollection(Collection collection); + + List selectDeleteList(); } diff --git a/src/main/java/com/ai/da/mapper/primary/DesignItemMapper.java b/src/main/java/com/ai/da/mapper/primary/DesignItemMapper.java index cdede99b..2bdc1f18 100644 --- a/src/main/java/com/ai/da/mapper/primary/DesignItemMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/DesignItemMapper.java @@ -3,6 +3,8 @@ package com.ai.da.mapper.primary; import com.ai.da.common.config.mybatis.plus.CommonMapper; import com.ai.da.mapper.primary.entity.DesignItem; +import java.util.List; + /** * Mapper 接口 * @@ -12,4 +14,6 @@ import com.ai.da.mapper.primary.entity.DesignItem; public interface DesignItemMapper extends CommonMapper { Long insertDesignItem(DesignItem designItem); + + List selectDeleteList(); } diff --git a/src/main/java/com/ai/da/mapper/primary/DesignMapper.java b/src/main/java/com/ai/da/mapper/primary/DesignMapper.java index ece90931..425b5a2c 100644 --- a/src/main/java/com/ai/da/mapper/primary/DesignMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/DesignMapper.java @@ -19,4 +19,6 @@ public interface DesignMapper extends CommonMapper { Long insertDesign(Design design); List getDesignStatistic(String startTime, String endTime, List ids, String email); + + List selectDeleteList(); } diff --git a/src/main/java/com/ai/da/mapper/primary/ProjectMapper.java b/src/main/java/com/ai/da/mapper/primary/ProjectMapper.java new file mode 100644 index 00000000..5738a6d0 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/ProjectMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.Project; + +public interface ProjectMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/SketchDataMapper.java b/src/main/java/com/ai/da/mapper/primary/SketchDataMapper.java new file mode 100644 index 00000000..3a698f2b --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/SketchDataMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.SketchData; + +public interface SketchDataMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitDetailMapper.java b/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitDetailMapper.java index 4ec7fe8e..64bb668b 100644 --- a/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitDetailMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitDetailMapper.java @@ -29,4 +29,5 @@ public interface TDesignPythonOutfitDetailMapper extends CommonMapper selectListDelete(); } diff --git a/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitMapper.java b/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitMapper.java index c3284391..fe7ebb42 100644 --- a/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitMapper.java @@ -25,4 +25,5 @@ public interface TDesignPythonOutfitMapper extends CommonMapper selectTDesignPythonOutfitPage(IPage page, TDesignPythonOutfitVO tDesignPythonOutfit); + List selectListDelete(); } diff --git a/src/main/java/com/ai/da/mapper/primary/UserLikeGroupMapper.java b/src/main/java/com/ai/da/mapper/primary/UserLikeGroupMapper.java index 4d71e0b2..bcf63b13 100644 --- a/src/main/java/com/ai/da/mapper/primary/UserLikeGroupMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/UserLikeGroupMapper.java @@ -3,6 +3,8 @@ package com.ai.da.mapper.primary; import com.ai.da.common.config.mybatis.plus.CommonMapper; import com.ai.da.mapper.primary.entity.UserLikeGroup; +import java.util.List; + /** * Mapper 接口 * @@ -12,4 +14,6 @@ import com.ai.da.mapper.primary.entity.UserLikeGroup; public interface UserLikeGroupMapper extends CommonMapper { //返回插入数据后生成的主键 Long insertUserLikeGroup(UserLikeGroup userLikeGroup); + + List getMoreThan50UserLikeAccount(); } diff --git a/src/main/java/com/ai/da/mapper/primary/UserPreferenceLogMapper.java b/src/main/java/com/ai/da/mapper/primary/UserPreferenceLogMapper.java new file mode 100644 index 00000000..99f5d9dc --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/UserPreferenceLogMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.UserPreferenceLogTest; + +public interface UserPreferenceLogMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/UserPreferenceLogPredictionMapper.java b/src/main/java/com/ai/da/mapper/primary/UserPreferenceLogPredictionMapper.java new file mode 100644 index 00000000..1b9e5e23 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/UserPreferenceLogPredictionMapper.java @@ -0,0 +1,8 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.UserPreferenceLogPrediction; +import com.ai.da.mapper.primary.entity.UserPreferenceLogTest; + +public interface UserPreferenceLogPredictionMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/CollectionElement.java b/src/main/java/com/ai/da/mapper/primary/entity/CollectionElement.java index fa3a6df0..45bec9eb 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/CollectionElement.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/CollectionElement.java @@ -86,4 +86,6 @@ public class CollectionElement implements Serializable { * 更新时间 */ private Date updateDate; + + private Long projectId; } diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Project.java b/src/main/java/com/ai/da/mapper/primary/entity/Project.java new file mode 100644 index 00000000..ac337376 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/Project.java @@ -0,0 +1,35 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("project") +public class Project implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long accountId; + + private String name; + + private String process; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/SketchData.java b/src/main/java/com/ai/da/mapper/primary/entity/SketchData.java new file mode 100644 index 00000000..73ee798b --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/SketchData.java @@ -0,0 +1,22 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@Accessors(chain = true) +@TableName("sketch_data") +public class SketchData implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private Long accountId; + private Long collectionId; + private String path; + private int type;//1 旧算法 2新算法 +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/UserLikeGroup.java b/src/main/java/com/ai/da/mapper/primary/entity/UserLikeGroup.java index 4f3867ca..887dc61b 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/UserLikeGroup.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/UserLikeGroup.java @@ -58,4 +58,6 @@ public class UserLikeGroup implements Serializable { * 更新时间 */ private Date updateDate; + + private Long projectId; } diff --git a/src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogPrediction.java b/src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogPrediction.java new file mode 100644 index 00000000..8b38f1e5 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogPrediction.java @@ -0,0 +1,27 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("user_preference_log_prediction") +public class UserPreferenceLogPrediction implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private Long userLikeGroupId; + private Long accountId; + private String path; + private LocalDateTime dataTime; + +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogTest.java b/src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogTest.java new file mode 100644 index 00000000..07ba59fa --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/UserPreferenceLogTest.java @@ -0,0 +1,27 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("user_preference_log_test") +public class UserPreferenceLogTest implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private Long userLikeGroupId; + private Long accountId; + private String path; + private LocalDateTime dataTime; + +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Workspace.java b/src/main/java/com/ai/da/mapper/primary/entity/Workspace.java index 2fe6fe9e..89694294 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/Workspace.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/Workspace.java @@ -97,5 +97,7 @@ public class Workspace implements Serializable { @ApiModelProperty(value = "是否删除") private Integer isDeleted; + private Long projectId; + } diff --git a/src/main/java/com/ai/da/model/dto/ModuleSaveDTO.java b/src/main/java/com/ai/da/model/dto/ModuleSaveDTO.java new file mode 100644 index 00000000..cf6acb6b --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/ModuleSaveDTO.java @@ -0,0 +1,36 @@ +package com.ai.da.model.dto; + +import com.ai.da.model.vo.CollectionColorVO; +import com.ai.da.model.vo.CollectionElementVO; +import com.ai.da.model.vo.MoodBoardModuleChooseVO; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.List; + +@Data +public class ModuleSaveDTO { + private Long projectId; + + private MoodBoardModuleSaveDTO moodBoard; + + @ApiModelProperty("印花板图片 数组") + private List printBoard; + + @NotEmpty(message = "colorBoards.cannot.be.empty") + @ApiModelProperty("颜色板RGB值 数组") + private List colorBoard; + + @ApiModelProperty("手稿板图片id 数组") + private List sketchBoard; + +// private MoodBoardModuleChooseVO moodBoard; +// private List printBoard; +// private List colorBoard; +// private List sketchBoard; + +} diff --git a/src/main/java/com/ai/da/model/dto/MoodBoardModuleSaveDTO.java b/src/main/java/com/ai/da/model/dto/MoodBoardModuleSaveDTO.java new file mode 100644 index 00000000..a81c9fbc --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/MoodBoardModuleSaveDTO.java @@ -0,0 +1,19 @@ +package com.ai.da.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MoodBoardModuleSaveDTO { + private List moodBoards; + + private Long moodTemplateId; + + private String moodboardPosition; +} diff --git a/src/main/java/com/ai/da/model/dto/ProjectDTO.java b/src/main/java/com/ai/da/model/dto/ProjectDTO.java new file mode 100644 index 00000000..b3505923 --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/ProjectDTO.java @@ -0,0 +1,29 @@ + +package com.ai.da.model.dto; + +import com.ai.da.mapper.primary.entity.Project; +import com.ai.da.mapper.primary.entity.Workspace; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * 数据传输对象实体类 + * + * @author SHAHAIBO + * @since 2023-08-01 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProjectDTO extends Project { + private static final long serialVersionUID = 1L; + + private Long styleId; + +// private String process; + + private Workspace workspace; + + private List moduleList; +} diff --git a/src/main/java/com/ai/da/model/dto/ProjectQueryDTO.java b/src/main/java/com/ai/da/model/dto/ProjectQueryDTO.java new file mode 100644 index 00000000..4b499993 --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/ProjectQueryDTO.java @@ -0,0 +1,37 @@ + +package com.ai.da.model.dto; + +import com.ai.da.mapper.primary.entity.Project; +import com.ai.da.mapper.primary.entity.Workspace; +import com.ai.da.model.vo.PageQueryBaseVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +/** + * 数据传输对象实体类 + * + * @author SHAHAIBO + * @since 2023-08-01 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProjectQueryDTO extends PageQueryBaseVo { + + @ApiModelProperty("项目名称") + private String projectName; + + @ApiModelProperty("开始时间 时间戳") + private Long startDate; + + @ApiModelProperty("开始时间 时间戳") + private Long endDate; + + private List classificationIdList; + + @ApiModelProperty("1交集2并集") + private Integer intersection; +} diff --git a/src/main/java/com/ai/da/model/dto/WorkspaceSaveDTO.java b/src/main/java/com/ai/da/model/dto/WorkspaceSaveDTO.java index 5d5831f1..9073feb8 100644 --- a/src/main/java/com/ai/da/model/dto/WorkspaceSaveDTO.java +++ b/src/main/java/com/ai/da/model/dto/WorkspaceSaveDTO.java @@ -19,4 +19,5 @@ public class WorkspaceSaveDTO extends Workspace { private Long styleId; + private String process; } diff --git a/src/main/java/com/ai/da/model/enums/DesignProcess.java b/src/main/java/com/ai/da/model/enums/DesignProcess.java new file mode 100644 index 00000000..e41e865a --- /dev/null +++ b/src/main/java/com/ai/da/model/enums/DesignProcess.java @@ -0,0 +1,34 @@ +package com.ai.da.model.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum DesignProcess implements IEnumDisplay { + + SERIES_DESIGN("Series design"), + SINGLE_DESIGN("Single design"), + FINISHED_PRODUCT("Finished product"), + PRINT_DESIGN("Print design"), + SKETCH_COLLAGE_PROCESS("Sketch Collage process"), + THREE_D_PLATE_MAKING("3D plate making"); + + private final String value; + + DesignProcess(String value) { + this.value = value; + } + + @Override + @JsonValue + public String getValue() { + return this.value; + } + + public static DesignProcess getProcess(String value) { + for (DesignProcess process : values()) { + if (process.value.equalsIgnoreCase(value)) { + return process; + } + } + throw new IllegalArgumentException("No matching constant for [" + value + "]"); + } +} diff --git a/src/main/java/com/ai/da/model/enums/Module.java b/src/main/java/com/ai/da/model/enums/Module.java new file mode 100644 index 00000000..78c24bc5 --- /dev/null +++ b/src/main/java/com/ai/da/model/enums/Module.java @@ -0,0 +1,39 @@ +package com.ai.da.model.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum Module implements IEnumDisplay { + moodBoard("MoodBoard"), + printBoard("PrintBoard"), + colorBoard("ColorBoard"), + sketchBoard("SketchBoard"), + mannequin("Mannequin"), + design("Design"), + toProduct("To Product"), + relight("Relight"), + poseTransfer("Pose Transfer"), + canvas("Canvas"), + patternMaking3D("3D Pattern Making"), + deReconstruction("De/Reconstruction"); + + private final String value; + + Module(String value) { + this.value = value; + } + + @Override + @JsonValue + public String getValue() { + return this.value; + } + + public static Module getName(String value) { + for (Module module : values()) { + if (module.value.equalsIgnoreCase(value)) { + return module; + } + } + throw new IllegalArgumentException("No matching constant for [" + value + "]"); + } +} diff --git a/src/main/java/com/ai/da/model/vo/CavasModuleChooseVO.java b/src/main/java/com/ai/da/model/vo/CavasModuleChooseVO.java new file mode 100644 index 00000000..dabe132d --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/CavasModuleChooseVO.java @@ -0,0 +1,14 @@ +package com.ai.da.model.vo; + +import com.ai.da.model.dto.PortfolioDTO; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CavasModuleChooseVO { + private PortfolioDTO portfolioDTO; + private Integer beenPublished; +} diff --git a/src/main/java/com/ai/da/model/vo/DesignModuleChooseVO.java b/src/main/java/com/ai/da/model/vo/DesignModuleChooseVO.java new file mode 100644 index 00000000..ddea9a60 --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/DesignModuleChooseVO.java @@ -0,0 +1,17 @@ +package com.ai.da.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DesignModuleChooseVO { + @ApiModelProperty("分组id") + private Long userGroupId; + + @ApiModelProperty("分组详细数组") + private java.util.List userLikeDetails; +} diff --git a/src/main/java/com/ai/da/model/vo/ModuleChooseVO.java b/src/main/java/com/ai/da/model/vo/ModuleChooseVO.java new file mode 100644 index 00000000..b614cb5e --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/ModuleChooseVO.java @@ -0,0 +1,34 @@ +package com.ai.da.model.vo; + +import com.ai.da.model.dto.PortfolioDTO; +import com.ai.da.model.dto.ToProductImageDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@ApiModel("用户choose详细-响应") +public class ModuleChooseVO { + private Long projectId; + private Long collectionId; + + private MoodBoardModuleChooseVO moodBoard; + private List printBoard; + private List colorBoard; + private List sketchBoard; +// private moodBoardModuleChooseVO mannequin; + private DesignModuleChooseVO design; + private List toProduct; + private List relight; + + private CavasModuleChooseVO canvas; +// private moodBoardModuleChooseVO poseTransfer; +// private moodBoardModuleChooseVO patternMaking3D; +// private moodBoardModuleChooseVO deReconstruction; +} diff --git a/src/main/java/com/ai/da/model/vo/MoodBoardModuleChooseVO.java b/src/main/java/com/ai/da/model/vo/MoodBoardModuleChooseVO.java new file mode 100644 index 00000000..2703881b --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/MoodBoardModuleChooseVO.java @@ -0,0 +1,20 @@ +package com.ai.da.model.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class MoodBoardModuleChooseVO { + private String moodTemplateId; + + private String moodTemplateUrl; + private String moodTemplateName; + private String moodboardPosition; + + private List moodBoards; +} diff --git a/src/main/java/com/ai/da/model/vo/ProjectChooseVO.java b/src/main/java/com/ai/da/model/vo/ProjectChooseVO.java new file mode 100644 index 00000000..81f9d1b0 --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/ProjectChooseVO.java @@ -0,0 +1,37 @@ +package com.ai.da.model.vo; + +import com.ai.da.model.dto.PortfolioDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@AllArgsConstructor +@Data +@ApiModel("用户choose详细-响应") +public class ProjectChooseVO { + + private Long id; + +// @ApiModelProperty("分组id") +// private Long userGroupId; +// +// @ApiModelProperty("分组详细数组") +// private List userLikeDetails; +// +// @ApiModelProperty("关联的collection") +// private UserLikeCollectionVO collection; +// +// private String sex; +// +// private Integer beenPublished; +// +//// private Portfolio portfolio; +// private PortfolioDTO portfolioDTO; + + private WorkspaceVO workspaceVO; + + private String process; +} diff --git a/src/main/java/com/ai/da/model/vo/ProjectVO.java b/src/main/java/com/ai/da/model/vo/ProjectVO.java new file mode 100644 index 00000000..9ab4656a --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/ProjectVO.java @@ -0,0 +1,21 @@ +package com.ai.da.model.vo; + +import com.ai.da.mapper.primary.entity.UserLikeGroup; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +@ApiModel("用户savedCollection分组-响应") +public class ProjectVO { + + @ApiModelProperty("分组ID") + private Long id; + + private UserLikeGroupVO userLikeGroupVO; + + @ApiModelProperty("更新时间") + private Long updateDate; +} diff --git a/src/main/java/com/ai/da/model/vo/UserPreferenceLogTestDTO.java b/src/main/java/com/ai/da/model/vo/UserPreferenceLogTestDTO.java new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/com/ai/da/model/vo/ValidateElementVO.java b/src/main/java/com/ai/da/model/vo/ValidateElementVO.java index 73912616..2c0f6c2f 100644 --- a/src/main/java/com/ai/da/model/vo/ValidateElementVO.java +++ b/src/main/java/com/ai/da/model/vo/ValidateElementVO.java @@ -51,4 +51,8 @@ public class ValidateElementVO { private List requestIdList; private Integer designNum; + + private Long collectionId; + + private Long accountId; } diff --git a/src/main/java/com/ai/da/python/PythonService.java b/src/main/java/com/ai/da/python/PythonService.java index f67e7916..3d5ea133 100644 --- a/src/main/java/com/ai/da/python/PythonService.java +++ b/src/main/java/com/ai/da/python/PythonService.java @@ -4,10 +4,13 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.exceptions.ExceptionUtil; import com.ai.da.common.config.FileProperties; import com.ai.da.common.config.exception.BusinessException; +import com.ai.da.common.context.UserContext; import com.ai.da.common.enums.*; import com.ai.da.common.utils.*; import com.ai.da.mapper.primary.CollocationMapper; import com.ai.da.mapper.primary.DressingMapper; +import com.ai.da.mapper.primary.SketchDataMapper; +import com.ai.da.mapper.primary.UserPreferenceLogMapper; import com.ai.da.mapper.primary.entity.*; import com.ai.da.mapper.secondary.AttributeRetrievalMapper; import com.ai.da.mapper.secondary.entity.AttributeRetrieval; @@ -32,6 +35,7 @@ import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @@ -224,7 +228,8 @@ public class PythonService { * @return */ public DesignPythonObjects covertDesignParam(BigDecimal systemScale, String singleOverall, - String switchCategory, ValidateElementVO elementVO, String processId) { + String switchCategory, ValidateElementVO elementVO, String processId, Set assembledObjects, Long collectionId) { + AuthPrincipalVo userHolder = UserContext.getUserHolder(); DesignPythonObjects designPythonObjects = new DesignPythonObjects(); List objects = new ArrayList<>(); designPythonObjects.setObjects(objects); @@ -236,16 +241,20 @@ public class PythonService { elementVO.setNoPinPrintNum(noPinPrintNum); int[] sketchNumbers = new int[3]; - int designNum = elementVO.getDesignNum(); - Set assembledObjects = new HashSet<>(); // 用于存储已组装的 DesignPythonObject + if (CollectionUtil.isEmpty(assembledObjects)) { + assembledObjects = new HashSet<>(); // 用于存储已组装的 DesignPythonObject + } DesignPythonObject lastAssembledObject = null; // 上一次组装的对象 + long totalContainsTime = 0; // 用于累计 contains 方法的时间 + int containsCheckCount = 0; // contains 方法调用次数 + for (int i = 0; i < designNum; i++) { CurrentDesignPictureTypeEnum designPictureType = calculateCurrentDesignPictureTypeNew(elementVO, sketchNumbers, systemScale); if (designPictureType == null) break; - CurrentDesignPrintPictureTypeEnum designPrintPictureType = calculateCurrentDesignPintPictureType(pinPrintNum, noPinPrintNum, noPrintNum); + CurrentDesignPrintPictureTypeEnum designPrintPictureType = calculateCurrentDesignPrintPictureType(pinPrintNum, noPinPrintNum, noPrintNum); if (designPrintPictureType == null) break; updateSketchNumbers(designPictureType, sketchNumbers); @@ -260,56 +269,63 @@ public class PythonService { noPrintNum--; break; } + DesignPythonItemPrint designPythonItemPrint = getRandomPrint(elementVO, designPrintPictureType); elementVO.setDesignPythonItemPrint(designPythonItemPrint); - elementVO.setDesignPrintPictureTypeLayoutList(calculateCurrentDesignPintPictureTypeLayout(elementVO.getModelSex())); + elementVO.setDesignPrintPictureTypeLayoutList(calculateCurrentDesignPrintPictureTypeLayout(elementVO.getModelSex())); + List beforeAssemblyHasUseMd5List = new ArrayList<>(elementVO.getHasUseMd5List()); + elementVO.setCollectionId(collectionId); DesignPythonObject pythonObject = createDesignPythonObject(elementVO, designPictureType, systemScale, singleOverall, switchCategory, i); +// List afterAssemblyHasUseMd5List = elementVO.getHasUseMd5List(); // 如果当前对象与已组装的对象重复,则跳过当前组装 DesignPythonObject designPythonObjectCopy = getCopy(pythonObject); + // 计算 contains 方法的执行时间 + long startTime = System.nanoTime(); boolean isDuplicate = assembledObjects.contains(designPythonObjectCopy); + long endTime = System.nanoTime(); + System.out.println("单次 方法调用耗时(纳秒): " + (endTime - startTime)); + totalContainsTime += (endTime - startTime); + containsCheckCount++; if (isDuplicate) { // if (lastAssembledObject != null && assembledObjects.contains(lastAssembledObject)) { -// // 如果当前组装与前一个组装的对象重复,且前一个组装也重复,结束组装 // System.out.println("当前组装的对象与前两个组装的对象重复,结束组装。"); // break; // } elementVO.setHasUseMd5List(beforeAssemblyHasUseMd5List); i --; - - switch (designPrintPictureType) { - case PIN: - pinPrintNum++; - break; - case NO_PIN: - noPinPrintNum++; - break; - case NO: - noPrintNum++; - break; - } continue; } // 将当前对象添加到已组装的集合中,并记录 assembledObjects.add(designPythonObjectCopy); // lastAssembledObject = designPythonObjectCopy; // 更新上一次组装的对象 + for (DesignPythonItem item : pythonObject.getItems()) { + redisUtil.addPathToCache(collectionId, userHolder.getId(), item.getPath()); + } objects.add(pythonObject); redisUtil.addProcessId(processId, i + 1); } + + // 输出统计结果 + System.out.println("contains 方法调用次数: " + containsCheckCount); + System.out.println("contains 方法累计执行时间(纳秒): " + totalContainsTime); + System.out.println("contains 方法平均执行时间(纳秒): " + (containsCheckCount > 0 ? totalContainsTime / containsCheckCount : 0)); + + redisUtil.addAssembledObjects(collectionId, assembledObjects); return designPythonObjects; } private DesignPythonObject getCopy(DesignPythonObject pythonObject) { DesignPythonObject designPythonObjectCopy = CopyUtil.copyObject(pythonObject, DesignPythonObject.class); designPythonObjectCopy.setObjectSign(null); - DesignPythonBasic basic = designPythonObjectCopy.getBasic(); - basic.setSave_name(null); - designPythonObjectCopy.setBasic(basic); +// DesignPythonBasic basic = designPythonObjectCopy.getBasic(); +// basic.setSave_name(null); +// designPythonObjectCopy.setBasic(basic); List items = designPythonObjectCopy.getItems(); List itemsCopy = new ArrayList<>(); for (DesignPythonItem item : items) { @@ -355,7 +371,17 @@ public class PythonService { private DesignPythonObject createDesignPythonObject(ValidateElementVO elementVO, CurrentDesignPictureTypeEnum designPictureType, BigDecimal systemScale, String singleOverall, String switchCategory, int i) { DesignPythonObject pythonObject = new DesignPythonObject(); pythonObject.setItems(coverToDesignPythonItemNew(elementVO, designPictureType, systemScale)); - pythonObject.setBasic(coverToBasic(pythonObject.getItems().get(0), singleOverall, switchCategory, elementVO.getDesignLibraryModelPoint())); +// pythonObject.setBasic(coverToBasic(pythonObject.getItems().get(0), singleOverall, switchCategory, elementVO.getDesignLibraryModelPoint())); +// if (CollectionUtil.isNotEmpty(elementVO.getRequestIdList())) { +// pythonObject.setObjectSign(elementVO.getRequestIdList().get(i)); +// } + return pythonObject; + } + + private DesignPythonObject createDesignPythonObjectNew(ValidateElementVO elementVO, CurrentDesignPictureTypeEnum designPictureType, BigDecimal systemScale, String singleOverall, String switchCategory, int i, Long accountId) { + DesignPythonObject pythonObject = new DesignPythonObject(); + pythonObject.setItems(coverToDesignPythonItemNewNew(elementVO, designPictureType, systemScale, accountId)); +// pythonObject.setBasic(coverToBasic(pythonObject.getItems().get(0), singleOverall, switchCategory, elementVO.getDesignLibraryModelPoint())); if (CollectionUtil.isNotEmpty(elementVO.getRequestIdList())) { pythonObject.setObjectSign(elementVO.getRequestIdList().get(i)); } @@ -486,7 +512,7 @@ public class PythonService { // } //计算当前的Print图片类型 - private CurrentDesignPrintPictureTypeEnum calculateCurrentDesignPintPictureType(long pinPrintNum, long noPinPrintNum, long noPrintNum) { + private CurrentDesignPrintPictureTypeEnum calculateCurrentDesignPrintPictureType(long pinPrintNum, long noPinPrintNum, long noPrintNum) { List codes = Lists.newArrayList(); if (pinPrintNum > 0) { //pin默认优先选择 不参与计算 后续有调整再说 @@ -511,7 +537,7 @@ public class PythonService { } //计算当前的Print图片类型具体分布位置 0. 上衣 1.下衣 2.上衣和下衣都print - private List calculateCurrentDesignPintPictureTypeLayout(String modelSex) { + private List calculateCurrentDesignPrintPictureTypeLayout(String modelSex) { if (modelSex.equals(Sex.FEMALE.getValue())) { Long randomIndex = RandomsUtil.randomSysFile(0L, 3L); if (randomIndex == 0) { @@ -607,6 +633,81 @@ public class PythonService { private List coverToDesignPythonItemNew(ValidateElementVO elementVO, CurrentDesignPictureTypeEnum designPictureType, BigDecimal systemScale) { List itemList = new ArrayList<>(); + + // 第一部分:计算 第一件 Sketch 耗时 + long firstSketchStartTime = System.currentTimeMillis(); + DesignPythonItem designPythonItem = calculatePythonItem(elementVO, designPictureType); + long firstSketchEndTime = System.currentTimeMillis(); + + // 记录第一部分耗时(秒) + redisUtil.recordTaskElapsedTime("firstSketchTime", (firstSketchEndTime - firstSketchStartTime) / 1000.0); + + if (Objects.nonNull(designPythonItem)) { + itemList.add(designPythonItem); + + if (elementVO.getSingleOverall().equals(SingleOverallEnum.OVERALL.getRealName())) { + List otherSketchCategoryList = getOtherSketchCategoryList(elementVO.getModelSex(), designPythonItem); + + // 提前缓存 AttributeRecognition 结果,减少多次调用 + long getAttributeStartTime = System.currentTimeMillis(); + JSONObject attributeRecognition = getAttributeRecognitionCached(designPythonItem, elementVO); + long getAttributeEndTime = System.currentTimeMillis(); + + // 记录第二部分获取特征值耗时(秒) + redisUtil.recordTaskElapsedTime("getAttributeRecognitionTime", (getAttributeEndTime - getAttributeStartTime) / 1000.0); + + if (!otherSketchCategoryList.isEmpty()) { + long otherSketchStartTime = System.currentTimeMillis(); +// for (String styleCategory : otherSketchCategoryList) { +// DesignPythonItem otherSketch = processAttributeRecognition(attributeRecognition, elementVO, designPictureType, styleCategory, systemScale); +// } + + otherSketchCategoryList.parallelStream().forEach(styleCategory -> { + DesignPythonItem otherSketch = processAttributeRecognition(attributeRecognition, elementVO, designPictureType, styleCategory, systemScale); + synchronized (itemList) { + itemList.add(otherSketch); + } + }); + long otherSketchEndTime = System.currentTimeMillis(); + + // 记录第三部分搭配 Sketch 耗时(秒) + redisUtil.recordTaskElapsedTime("otherSketchTime", (otherSketchEndTime - otherSketchStartTime) / 1000.0); + } + + itemList.addAll(calculatePythonItemHairstyleShoes(elementVO, elementVO.getDesignLibraryModelPoint())); + } + } + + return itemList; + } + + private JSONObject getAttributeRecognitionCached(DesignPythonItem designPythonItem, ValidateElementVO elementVO) { + try { + String cacheKey = String.format("attributeRecognition:%s:%s:%s", + MD5Utils.encryptFile(minioUtil.download(designPythonItem.getPath())), + designPythonItem.getType(), + elementVO.getModelSex()); + long startContainTime = System.nanoTime(); + if (redisUtil.hasKey(cacheKey)) { + long endContainTime = System.nanoTime(); + log.info("redisUtil.hasKey(cacheKey) time: {} seconds", (endContainTime - startContainTime) / 1_000_000_000.0); + return JSONObject.parseObject(redisUtil.getFromString(cacheKey)); + } else { + long startTime = System.nanoTime(); + JSONObject attributeRecognition = getAttributeRecognition(designPythonItem.getPath(), designPythonItem.getType(), elementVO.getModelSex()); + redisUtil.addToString(cacheKey, attributeRecognition.toJSONString()); + long endTime = System.nanoTime(); + log.info("getAttributeRecognition execution time: {} seconds", (endTime - startTime) / 1_000_000_000.0); + return attributeRecognition; + } + } catch (Exception e) { + log.error("Failed to get AttributeRecognition: {}", e.getMessage()); + return null; + } + } + + private List coverToDesignPythonItemNewNew(ValidateElementVO elementVO, CurrentDesignPictureTypeEnum designPictureType, BigDecimal systemScale, Long accountId) { + List itemList = new ArrayList<>(); DesignPythonItem designPythonItem = calculatePythonItem(elementVO, designPictureType); if (Objects.nonNull(designPythonItem)) { itemList.add(designPythonItem); @@ -625,13 +726,31 @@ public class PythonService { return itemList; } + @Resource + private SketchDataMapper sketchDataMapper; + private DesignPythonItem processAttributeRecognition(JSONObject attributeRecognition, ValidateElementVO elementVO, CurrentDesignPictureTypeEnum designPictureType, String styleCategory, BigDecimal systemScale) { switch (designPictureType) { case PIN: return processPinAttributeRecognition(attributeRecognition, elementVO, styleCategory, systemScale); case NO_PIN: case SYS_FILE: - return processNoPinOrSysFileAttributeRecognition(attributeRecognition, elementVO, styleCategory, systemScale); + List designPythonItemList = processNoPinOrSysFileAttributeRecognition(attributeRecognition, elementVO, styleCategory, systemScale); + for (int i = 0; i < 2; i++) { + DesignPythonItem designPythonItem = designPythonItemList.get(i); + + SketchData sketchData = new SketchData(); + sketchData.setAccountId(elementVO.getAccountId()); + sketchData.setPath(designPythonItem.getPath()); + if (i == 0) { + sketchData.setType(2); + }else { + sketchData.setType(1); + } + sketchData.setCollectionId(elementVO.getCollectionId()); + sketchDataMapper.insert(sketchData); + } + return designPythonItemList.get(1); default: throw new BusinessException("unknown designPictureType"); } @@ -645,44 +764,335 @@ public class PythonService { return coverSketchToDesignPythonItem(collectPin.get(randomNum).getId(), collectPin.get(randomNum), elementVO); } else { List collectNoPin = getFilteredCollectionElements(elementVO.getSketchBoardElements(), 0, styleCategory); - return processNoPinOrSysFileAttributeRecognitionWithPool(collectNoPin, attributeRecognition, elementVO, styleCategory, systemScale); + List designPythonItemList = processNoPinOrSysFileAttributeRecognitionWithPool(collectNoPin, attributeRecognition, elementVO, styleCategory, systemScale); + for (int i = 0; i < 2; i++) { + DesignPythonItem designPythonItem = designPythonItemList.get(i); + + SketchData sketchData = new SketchData(); + sketchData.setAccountId(elementVO.getAccountId()); + sketchData.setPath(designPythonItem.getPath()); + if (i == 0) { + // 第一个 新算法 + sketchData.setType(2); + }else { + // 后一个 老算法 + sketchData.setType(1); + } + sketchData.setCollectionId(elementVO.getCollectionId()); + sketchDataMapper.insert(sketchData); + } + return designPythonItemList.get(1); } } - private DesignPythonItem processNoPinOrSysFileAttributeRecognition(JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory, BigDecimal systemScale) { + private List processNoPinOrSysFileAttributeRecognition(JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory, BigDecimal systemScale) { List collectNoPin = getFilteredCollectionElements(elementVO.getSketchBoardElements(), 0, styleCategory); return processNoPinOrSysFileAttributeRecognitionWithPool(collectNoPin, attributeRecognition, elementVO, styleCategory, systemScale); } - private DesignPythonItem processNoPinOrSysFileAttributeRecognitionWithPool(List collectionElements, JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory, BigDecimal systemScale) { - int poolNum = 20; + private List processNoPinOrSysFileAttributeRecognitionWithPool(List collectionElements, JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory, BigDecimal systemScale) { + int poolNum = 40; + List result = new ArrayList<>(); if (CollectionUtil.isNotEmpty(collectionElements)) { int collectionNoPinSize = collectionElements.size(); if (systemScale.compareTo(BigDecimal.ZERO) == 0) { int randomNum = RandomsUtil.randomSysFile(collectionNoPinSize); - return coverSketchToDesignPythonItem(null, collectionElements.get(randomNum), elementVO); + CollectionElement collectionElement = getRomdomCollectionElement(collectionElements, null, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); + if (Objects.isNull(collectionElement)) { + log.info("bug"); + } + DesignPythonItem designPythonItemNew = coverSketchToDesignPythonItem(null, collectionElement, elementVO); + result.add(designPythonItemNew); + DesignPythonItem designPythonItemOld = coverSketchToDesignPythonItem(null, collectionElements.get(randomNum), elementVO); + result.add(designPythonItemOld); + return result; } else if (systemScale.compareTo(BigDecimal.ONE) != 0) { BigDecimal collectNoPinSize = BigDecimal.valueOf(collectionNoPinSize); poolNum = collectNoPinSize.divide(systemScale, 0, RoundingMode.DOWN).intValue(); + if (poolNum < 20) { + poolNum = 40; + } List list = getSystemSketchPool(attributeRecognition, styleCategory, elementVO.getModelSex(), poolNum, elementVO.getStyle()); + + CollectionElement collectionElementNew = getRomdomCollectionElement(collectionElements, list, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); + if (Objects.isNull(collectionElementNew)) { + log.info("bug"); + } + DesignPythonItem designPythonItemNew = coverSketchToDesignPythonItem(null, collectionElementNew, elementVO); + result.add(designPythonItemNew); collectionElements.addAll(list); int randomNum = RandomsUtil.randomSysFile(collectionElements.size()); - if (randomNum < collectionNoPinSize) { - return coverSketchToDesignPythonItem(collectionElements.get(randomNum).getId(), collectionElements.get(randomNum), elementVO); - } else { - return coverSketchToDesignPythonItem(null, collectionElements.get(randomNum), elementVO); - } + DesignPythonItem designPythonItemOld = coverSketchToDesignPythonItem(null, collectionElements.get(randomNum), elementVO); +// if (randomNum < collectionNoPinSize) { +// return coverSketchToDesignPythonItem(collectionElements.get(randomNum).getId(), collectionElements.get(randomNum), elementVO); +// } else { +// return coverSketchToDesignPythonItem(null, collectionElements.get(randomNum), elementVO); +// } + result.add(designPythonItemOld); + return result; } } List list = getSystemSketchPool(attributeRecognition, styleCategory, elementVO.getModelSex(), poolNum, elementVO.getStyle()); + if (CollectionUtil.isEmpty(list)) { + System.out.println("bug"); + } int randomNum = RandomsUtil.randomSysFile(list.size()); - return coverSketchToDesignPythonItem(null, list.get(randomNum), elementVO); + CollectionElement collectionElementNew = getRomdomCollectionElement(null, list, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); + DesignPythonItem designPythonItemNew = coverSketchToDesignPythonItem(null, collectionElementNew, elementVO); + result.add(designPythonItemNew); + DesignPythonItem designPythonItemOld = coverSketchToDesignPythonItem(null, list.get(randomNum), elementVO); + result.add(designPythonItemOld); + return result; + } + +// private DesignPythonItem processNoPinOrSysFileAttributeRecognitionWithPoolNew(List collectionElements, JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory, BigDecimal systemScale) { +// int poolNum = 20; +// if (CollectionUtil.isNotEmpty(collectionElements)) { +// int collectionNoPinSize = collectionElements.size(); +// if (systemScale.compareTo(BigDecimal.ZERO) == 0) { +// CollectionElement collectionElement = getRomdomCollectionElement(collectionElements, null, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); +// return coverSketchToDesignPythonItem(null, collectionElement, elementVO); +// } else if (systemScale.compareTo(BigDecimal.ONE) != 0) { +// BigDecimal collectNoPinSize = BigDecimal.valueOf(collectionNoPinSize); +// poolNum = collectNoPinSize.divide(systemScale, 0, RoundingMode.DOWN).intValue(); +// List list = getSystemSketchPool(attributeRecognition, styleCategory, elementVO.getModelSex(), poolNum, elementVO.getStyle()); +//// collectionElements.addAll(list); +//// int randomNum = RandomsUtil.randomSysFile(collectionElements.size()); +// +// CollectionElement collectionElement = getRomdomCollectionElement(collectionElements, list, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); +// return coverSketchToDesignPythonItem(null, collectionElement, elementVO); +// } +// } +// List list = getSystemSketchPool(attributeRecognition, styleCategory, elementVO.getModelSex(), poolNum, elementVO.getStyle()); +// CollectionElement collectionElement = getRomdomCollectionElement(null, list, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); +// return coverSketchToDesignPythonItem(null, collectionElement, elementVO); +// } + + private DesignPythonItem processNoPinOrSysFileAttributeRecognitionWithPoolNew(List collectionElements, JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory, BigDecimal systemScale) { + int poolNum = 20; + if (CollectionUtil.isNotEmpty(collectionElements)) { + int collectionNoPinSize = collectionElements.size(); + if (systemScale.compareTo(BigDecimal.ZERO) == 0) { + CollectionElement collectionElement = getRomdomCollectionElement(collectionElements, null, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); + return coverSketchToDesignPythonItem(null, collectionElement, elementVO); + } else if (systemScale.compareTo(BigDecimal.ONE) != 0) { + BigDecimal collectNoPinSize = BigDecimal.valueOf(collectionNoPinSize); + + // 使用 BigDecimal 类型来计算 poolNum + BigDecimal poolNumAsBigDecimal = collectNoPinSize.divide(systemScale, 0, RoundingMode.DOWN); + + // 比较 poolNum + collectNoPinSize 是否小于 20 + if (poolNumAsBigDecimal.add(collectNoPinSize).compareTo(BigDecimal.valueOf(20)) < 0) { + // 判断成立,设置 poolNum 为 20 - collectNoPinSize + poolNum = BigDecimal.valueOf(20).subtract(collectNoPinSize).intValue(); + } + List list = getSystemSketchPool(attributeRecognition, styleCategory, elementVO.getModelSex(), poolNum, elementVO.getStyle()); + CollectionElement collectionElement = getRomdomCollectionElement(collectionElements, list, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); + return coverSketchToDesignPythonItem(null, collectionElement, elementVO); + } + } + List list = getSystemSketchPool(attributeRecognition, styleCategory, elementVO.getModelSex(), poolNum, elementVO.getStyle()); +// int randomNum = RandomsUtil.randomSysFile(list.size()); + CollectionElement collectionElement = getRomdomCollectionElement(null, list, systemScale, elementVO.getCollectionId(), elementVO.getAccountId()); + return coverSketchToDesignPythonItem(null, collectionElement, elementVO); + } + + private CollectionElement getRomdomCollectionElement(List noPinSketchList, List systemSketchList, BigDecimal systemScale, Long collectionId, Long accountId) { + // 确定选择的池子:根据 systemScale 决定选取 noPin 或 system + boolean selectNoPin = Math.random() < (1 - systemScale.doubleValue()); + + List selectedList = new ArrayList<>(); + if (selectNoPin) { + if (!CollectionUtils.isEmpty(noPinSketchList)) { + selectedList.addAll(noPinSketchList); + }else { + selectedList.addAll(systemSketchList); + } + }else { + selectedList.addAll(systemSketchList); + } + + if (CollectionUtil.isEmpty(selectedList)) { + return null; // 如果选中的池子为空,返回 null + } + + // 计算每个元素的得分 + Map scoreMap = new HashMap<>(); + for (CollectionElement element : selectedList) { + double baseScore = Math.random(); // 基础分:0 到 1 的随机数 + + // 根据是否是之前用过或喜欢过的 sketch 调整得分 + double adjustment = 0.0; + int likedSketch = isLikedSketch(element, accountId); + int maxLikedSketch = getMaxLikedSketchNum(accountId); + if (maxLikedSketch > 0) { + if (likedSketch > 0) { + adjustment = Math.log(1 + likedSketch)/Math.log(1 + maxLikedSketch); + } + } + + double finalScore = adjustment; +// double finalScore = 0.7 * baseScore + 0.3 * adjustment; + scoreMap.put(element, finalScore); + } + + // 按得分排序并返回最高分的元素 + return selectedList.stream() + .sorted((e1, e2) -> Double.compare(scoreMap.get(e2), scoreMap.get(e1))) // 按分数降序排序 + .findFirst() + .orElse(null); // 如果池子为空,返回 null + } + + @Resource + private RedisTemplate redisTemplate; + + // 检查是否是 like 过的 sketch + private int isLikedSketch(CollectionElement element, Long accountId) { + String redisKey = "user_liked_sketch:" + accountId; + + // 尝试从 Redis 获取该 sketch path 的喜欢次数 + Integer likedCount = (Integer) redisTemplate.opsForHash().get(redisKey, element.getUrl()); + if (likedCount != null) { + return likedCount; // 如果缓存中有,直接返回 + } + + // 如果缓存中没有,则查询数据库 + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(UserPreferenceLogTest::getPath, element.getUrl()); + qw.lambda().eq(UserPreferenceLogTest::getAccountId, accountId); +// List userPreferenceLogTests = userPreferenceLogMapper.selectList(qw); +// if (CollectionUtils.isEmpty(userPreferenceLogTests)) { +// return 0; +// } +// +// 将结果存入 Redis +// redisTemplate.opsForHash().put(redisKey, element.getUrl(), userPreferenceLogTests.size()); +// +// 返回查询到的结果 +// return userPreferenceLogTests.size(); + return 10; + } + + private int getMaxLikedSketchNum(Long accountId) { +// String redisKey = "user_liked_sketch:" + accountId + ":maxLikes"; +// +// // 尝试从 Redis 获取最大喜欢次数 +// String maxLikesStr = (String) redisTemplate.opsForValue().get(redisKey); +// if (maxLikesStr != null) { +// return Integer.parseInt(maxLikesStr); // 如果缓存中有,直接返回 +// } +// +// // 如果缓存中没有,则查询数据库 +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().eq(UserPreferenceLogTest::getAccountId, accountId); +// List userPreferenceLogTests = userPreferenceLogMapper.selectList(qw); +// if (CollectionUtils.isEmpty(userPreferenceLogTests)) { +// return 0; +// } + +// // 按路径统计数量 +// Map pathCountMap = userPreferenceLogTests.stream() +// .collect(Collectors.groupingBy(UserPreferenceLogTest::getPath, Collectors.counting())); +// +// // 获取最大喜欢次数 +// int maxLiked = pathCountMap.values().stream() +// .max(Long::compare) +// .orElse(0L) +// .intValue(); +// +// // 将最大喜欢次数存入 Redis +// redisTemplate.opsForValue().set(redisKey, String.valueOf(maxLiked)); + + return 10; } private List getFilteredCollectionElements(List elements, int hasPin, String styleCategory) { return CollectionUtil.isNotEmpty(elements) ? elements.stream().filter(o -> o.getHasPin() == hasPin && o.getLevel2Type().equals(styleCategory)).collect(Collectors.toList()) : null; } + // 历史使用记录,可以通过一个 Map 存储 MD5 或 ID + private static Map usageHistory = new HashMap<>(); + + // 给定扰动参数 + private static final double DISTURBANCE_FACTOR = 1; + + private static double calculateScore(CollectionElement element, boolean isNoPin, double systemScale, int noPinCount, int systemCount) { + double score = 0.0; + + return score; + } + + public static void main(String[] args) { + List noPinSketchList = new ArrayList<>(); + List systemSketchList = new ArrayList<>(); + + // 构造 noPin 和 system 的元素 + for (int i = 0; i < 50; i++) { + CollectionElement element = new CollectionElement(); + element.setMd5("noPin_" + i); // 设置 md5 前缀为 noPin + noPinSketchList.add(element); + } + for (int i = 0; i < 50; i++) { + CollectionElement element = new CollectionElement(); + element.setMd5("system_" + i); // 设置 md5 前缀为 system + systemSketchList.add(element); + } + + // 设置 systemScale 测试值 + double systemScale = 0.6; + + // 模拟测试次数 + int totalTests = 1000000; + int noPinWinCount = 0; + + for (int i = 0; i < totalTests; i++) { + CollectionElement highestElement = getHighestScoredElement(noPinSketchList, systemSketchList, systemScale); + if (highestElement != null && highestElement.getMd5().startsWith("noPin")) { + noPinWinCount++; + } + } + + double probability = (double) noPinWinCount / totalTests; + System.out.printf("Probability of highest score being noPin: %.4f%n", probability); + } + + private static CollectionElement getHighestScoredElement(List noPinSketchList, + List systemSketchList, + double systemScale) { + // 获取 noPin 列表中得分最高的元素 + CollectionElement highestNoPinElement = getHighestScoreElement(noPinSketchList, true, systemScale, + noPinSketchList.size(), systemSketchList.size()); + // 获取 system 列表中得分最高的元素 + CollectionElement highestSystemElement = getHighestScoreElement(systemSketchList, false, systemScale, + noPinSketchList.size(), systemSketchList.size()); + + // 比较两者得分并返回最高分的元素 +// if (highestNoPinElement != null && highestSystemElement != null) { +// return highestNoPinElement.getScore() >= highestSystemElement.getScore() ? highestNoPinElement : highestSystemElement; +// } + return null; + } + + private static CollectionElement getHighestScoreElement(List sketchList, + boolean isNoPin, + double systemScale, + int noPinCount, + int systemCount) { + double maxScore = Double.NEGATIVE_INFINITY; + CollectionElement highestElement = null; + + for (CollectionElement element : sketchList) { + double score = calculateScore(element, isNoPin, systemScale, noPinCount, systemCount); +// element.setScore(score); // 设置得分以便比较 +// if (score > maxScore) { +// maxScore = score; +// highestElement = element; +// } + } + return highestElement; + } + + private DesignPythonItem processAttributeRecognitionBySameCategory(JSONObject attributeRecognition, ValidateElementVO elementVO, String styleCategory) { List list = getSystemSketchPoolBySameCategory(attributeRecognition, styleCategory, elementVO.getModelSex(), elementVO.getStyle()); int randomNum = RandomsUtil.randomSysFile(list.size()); @@ -866,7 +1276,7 @@ public class PythonService { paramArray.add(paramJSONObject); String param = JSON.toJSONString(paramArray, SerializerFeature.DisableCircularReferenceDetect); - log.info("PythonService##design 请求参数:####{}", param); +// log.info("PythonService##design 请求参数:####{}", param); RequestBody body = RequestBody.create(mediaType, param); Request request = new Request.Builder() .url(accessPythonIp + ":" + accessPythonPort + "/api/attribute_recognition") @@ -879,7 +1289,7 @@ public class PythonService { if (response.isSuccessful()) { String responseBody = Objects.requireNonNull(response.body()).string(); JSONObject responseObject = JSON.parseObject(responseBody); - log.info("PythonService##responseObject###{}", responseObject); +// log.info("PythonService##responseObject###{}", responseObject); return responseObject; } else { log.error("PythonService##design 请求异常:{}", response); @@ -1634,10 +2044,10 @@ public class PythonService { pythonItem.setPath(sysFileVO.getUrl()); pythonItem.setBusinessId(sysFileVO.getId()); if (SysFileLevel2TypeEnum.SHOES.getRealName().equals(type)) { - CollectionColorDTO randomColor = getRandomColor(elementVO.getColorBoards()); - pythonItem.setColor(randomColor.getRgbValue()); - pythonItem.setGradient(randomColor.getGradientMinioUrl()); - pythonItem.setGradientString(randomColor.getGradientString()); +// CollectionColorDTO randomColor = getRandomColor(elementVO.getColorBoards()); +// pythonItem.setColor(randomColor.getRgbValue()); +// pythonItem.setGradient(randomColor.getGradientMinioUrl()); +// pythonItem.setGradientString(randomColor.getGradientString()); } } } @@ -2000,10 +2410,10 @@ public class PythonService { designPythonItemBlouse.setPath(path); //所有的icon都是none designPythonItemBlouse.setIcon("none"); - CollectionColorDTO randomColor = getRandomColor(elementVO.getColorBoards()); - designPythonItemBlouse.setColor(randomColor.getRgbValue()); - designPythonItemBlouse.setGradient(randomColor.getGradientMinioUrl()); - designPythonItemBlouse.setGradientString(randomColor.getGradientString()); +// CollectionColorDTO randomColor = getRandomColor(elementVO.getColorBoards()); +// designPythonItemBlouse.setColor(randomColor.getRgbValue()); +// designPythonItemBlouse.setGradient(randomColor.getGradientMinioUrl()); +// designPythonItemBlouse.setGradientString(randomColor.getGradientString()); if (!elementVO.getDesignPythonItemPrint().getPath().equals("none") && elementVO.getDesignPrintPictureTypeLayoutList().contains(type)) { DesignPythonItemPrint designPythonItemPrint = CopyUtil.copyObject(elementVO.getDesignPythonItemPrint(), DesignPythonItemPrint.class); @@ -2025,14 +2435,17 @@ public class PythonService { designPythonItemBlouse.setElementId(elementId); designPythonItemBlouse.setBusinessId(elementId); } + if (Objects.isNull(collectionElement)) { + log.info("bug"); + } designPythonItemBlouse.setType(collectionElement.getLevel2Type()); designPythonItemBlouse.setPath(collectionElement.getUrl()); //所有的icon都是none designPythonItemBlouse.setIcon("none"); - CollectionColorDTO randomColor = getRandomColor(elementVO.getColorBoards()); - designPythonItemBlouse.setColor(randomColor.getRgbValue()); - designPythonItemBlouse.setGradient(randomColor.getGradientMinioUrl()); - designPythonItemBlouse.setGradientString(randomColor.getGradientString()); +// CollectionColorDTO randomColor = getRandomColor(elementVO.getColorBoards()); +// designPythonItemBlouse.setColor(randomColor.getRgbValue()); +// designPythonItemBlouse.setGradient(randomColor.getGradientMinioUrl()); +// designPythonItemBlouse.setGradientString(randomColor.getGradientString()); if (!elementVO.getDesignPythonItemPrint().getPath().equals("none") && elementVO.getDesignPrintPictureTypeLayoutList().contains(collectionElement.getLevel2Type())) { DesignPythonItemPrint designPythonItemPrint = CopyUtil.copyObject(elementVO.getDesignPythonItemPrint(), DesignPythonItemPrint.class); @@ -3799,4 +4212,98 @@ public class PythonService { throw new BusinessException("design.interface.exception"); } + + public DesignPythonObjects covertDesignParamTest(BigDecimal systemScale, String singleOverall, + String switchCategory, ValidateElementVO elementVO, String processId, Set assembledObjects, Long collectionId) { + AuthPrincipalVo userHolder = UserContext.getUserHolder(); + DesignPythonObjects designPythonObjects = new DesignPythonObjects(); + List objects = new ArrayList<>(); + designPythonObjects.setObjects(objects); +// designPythonObjects.setProcess_id(processId); + + long pinPrintNum = calculateDesignPinPrintNum(elementVO.getPrintBoardElements()); + long noPinPrintNum = calculateDesignNoPinPrintNum(elementVO.getPrintBoardElements(), elementVO.getDesignNum()); + long noPrintNum = elementVO.getDesignNum() - pinPrintNum - noPinPrintNum; + elementVO.setNoPinPrintNum(noPinPrintNum); + + int[] sketchNumbers = new int[3]; + int designNum = elementVO.getDesignNum(); + if (CollectionUtil.isEmpty(assembledObjects)) { + assembledObjects = new HashSet<>(); // 用于存储已组装的 DesignPythonObject + } + DesignPythonObject lastAssembledObject = null; // 上一次组装的对象 + + long totalContainsTime = 0; // 用于累计 contains 方法的时间 + int containsCheckCount = 0; // contains 方法调用次数 + + for (int i = 0; i < designNum; i++) { + CurrentDesignPictureTypeEnum designPictureType = calculateCurrentDesignPictureTypeNew(elementVO, sketchNumbers, systemScale); + if (designPictureType == null) break; + + CurrentDesignPrintPictureTypeEnum designPrintPictureType = calculateCurrentDesignPrintPictureType(pinPrintNum, noPinPrintNum, noPrintNum); + if (designPrintPictureType == null) break; + + updateSketchNumbers(designPictureType, sketchNumbers); + switch (designPrintPictureType) { + case PIN: + pinPrintNum--; + break; + case NO_PIN: + noPinPrintNum--; + break; + case NO: + noPrintNum--; + break; + } + + DesignPythonItemPrint designPythonItemPrint = getRandomPrint(elementVO, designPrintPictureType); + elementVO.setDesignPythonItemPrint(designPythonItemPrint); + elementVO.setDesignPrintPictureTypeLayoutList(calculateCurrentDesignPrintPictureTypeLayout(elementVO.getModelSex())); + + List beforeAssemblyHasUseMd5List = new ArrayList<>(elementVO.getHasUseMd5List()); + elementVO.setCollectionId(collectionId); + DesignPythonObject pythonObject = createDesignPythonObject(elementVO, designPictureType, systemScale, singleOverall, switchCategory, i); + +// List afterAssemblyHasUseMd5List = elementVO.getHasUseMd5List(); + // 如果当前对象与已组装的对象重复,则跳过当前组装 + DesignPythonObject designPythonObjectCopy = getCopy(pythonObject); + + // 计算 contains 方法的执行时间 + long startTime = System.nanoTime(); + boolean isDuplicate = assembledObjects.contains(designPythonObjectCopy); + long endTime = System.nanoTime(); +// System.out.println("单次 方法调用耗时(纳秒): " + (endTime - startTime)); + totalContainsTime += (endTime - startTime); + containsCheckCount++; + + if (isDuplicate) { +// if (lastAssembledObject != null && assembledObjects.contains(lastAssembledObject)) { +// System.out.println("当前组装的对象与前两个组装的对象重复,结束组装。"); +// break; +// } + elementVO.setHasUseMd5List(beforeAssemblyHasUseMd5List); + i --; + continue; + } + + // 将当前对象添加到已组装的集合中,并记录 + assembledObjects.add(designPythonObjectCopy); +// lastAssembledObject = designPythonObjectCopy; // 更新上一次组装的对象 +// for (DesignPythonItem item : pythonObject.getItems()) { +// redisUtil.addPathToCache(collectionId, userHolder.getId(), item.getPath()); +// } + + objects.add(pythonObject); +// redisUtil.addProcessId(processId, i + 1); + } + + // 输出统计结果 +// System.out.println("contains 方法调用次数: " + containsCheckCount); +// System.out.println("contains 方法累计执行时间(纳秒): " + totalContainsTime); +// System.out.println("contains 方法平均执行时间(纳秒): " + (containsCheckCount > 0 ? totalContainsTime / containsCheckCount : 0)); + + redisUtil.addAssembledObjects(collectionId, assembledObjects); + return designPythonObjects; + } + } diff --git a/src/main/java/com/ai/da/service/CollectionService.java b/src/main/java/com/ai/da/service/CollectionService.java index 41cb5760..27c5100b 100644 --- a/src/main/java/com/ai/da/service/CollectionService.java +++ b/src/main/java/com/ai/da/service/CollectionService.java @@ -1,9 +1,13 @@ package com.ai.da.service; import com.ai.da.mapper.primary.entity.Collection; +import com.ai.da.mapper.primary.entity.CollectionElement; +import com.ai.da.model.vo.CollectionColorVO; import com.ai.da.model.vo.UserLikeCollectionVO; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + /** * 服务类 * @@ -25,4 +29,8 @@ public interface CollectionService extends IService { * 查询choose关联的collection */ UserLikeCollectionVO chooseCollection(Long id); + + String getMoodboardPositionString(Long id); + + List resolveColorBoard(List collectionElements); } diff --git a/src/main/java/com/ai/da/service/DesignService.java b/src/main/java/com/ai/da/service/DesignService.java index 9dc7591d..3cfbfd48 100644 --- a/src/main/java/com/ai/da/service/DesignService.java +++ b/src/main/java/com/ai/da/service/DesignService.java @@ -95,6 +95,8 @@ public interface DesignService extends IService { Integer designProcess(String processId); + void parseMoodboardPosition(String moodboardPosition, Long collectionIdParam); + void relationImageId(DesignPythonObjects objects); List sketchesBoundingBox(ReDesignCollectionDTO reDesignCollectionDTO); diff --git a/src/main/java/com/ai/da/service/SysFileService.java b/src/main/java/com/ai/da/service/SysFileService.java index d7d1a454..0b35bb04 100644 --- a/src/main/java/com/ai/da/service/SysFileService.java +++ b/src/main/java/com/ai/da/service/SysFileService.java @@ -60,4 +60,6 @@ public interface SysFileService extends IService { List getByUrlList(List urlList); List getByIds(List ids); + + SysFile getOneBySex(Long styleId, String sex); } diff --git a/src/main/java/com/ai/da/service/UserLikeGroupService.java b/src/main/java/com/ai/da/service/UserLikeGroupService.java index e0e9050f..eacc34b3 100644 --- a/src/main/java/com/ai/da/service/UserLikeGroupService.java +++ b/src/main/java/com/ai/da/service/UserLikeGroupService.java @@ -1,14 +1,14 @@ package com.ai.da.service; +import com.ai.da.common.response.PageBaseResponse; import com.ai.da.mapper.primary.entity.CanvasElementUpload; import com.ai.da.mapper.primary.entity.ToProductImageResult; +import com.ai.da.mapper.primary.entity.TrialOrder; import com.ai.da.mapper.primary.entity.UserLikeGroup; -import com.ai.da.model.dto.ExportSaveDTO; -import com.ai.da.model.dto.ProductImageInitializeDTO; -import com.ai.da.model.dto.ProductImageLikeDTO; -import com.ai.da.model.dto.ToProductImageDTO; +import com.ai.da.model.dto.*; import com.ai.da.model.vo.*; import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -37,6 +37,8 @@ public interface UserLikeGroupService extends IService { */ UserLikeChooseVO choose(Long userGroupId); + ProjectChooseVO choose(ProjectDTO projectDTO); + void deleteTrialData(Long id); void updateDate(Long id,String timeZone); @@ -72,4 +74,10 @@ public interface UserLikeGroupService extends IService { String download(); Boolean productImageInitialize(ProductImageInitializeDTO productImageInitializeDTO); + + IPage getPage(ProjectQueryDTO projectQueryDTO); + + ModuleChooseVO getModuleContent(ProjectDTO projectDTO); + + ModuleChooseVO saveModuleContent(ModuleSaveDTO moduleSaveDTO); } diff --git a/src/main/java/com/ai/da/service/WorkspaceService.java b/src/main/java/com/ai/da/service/WorkspaceService.java index 83fb4090..12ca9d01 100644 --- a/src/main/java/com/ai/da/service/WorkspaceService.java +++ b/src/main/java/com/ai/da/service/WorkspaceService.java @@ -3,6 +3,7 @@ package com.ai.da.service; import com.ai.da.mapper.primary.entity.Style; import com.ai.da.mapper.primary.entity.Workspace; +import com.ai.da.model.dto.ProjectDTO; import com.ai.da.model.dto.WorkspaceDTO; import com.ai.da.model.dto.WorkspaceSaveDTO; import com.ai.da.model.enums.BizJson; @@ -11,6 +12,7 @@ import com.ai.da.model.vo.StyleVO; import com.ai.da.model.vo.WorkspaceVO; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.transaction.annotation.Transactional; import java.io.FileNotFoundException; import java.util.List; @@ -53,4 +55,9 @@ public interface WorkspaceService extends IService { Workspace getCurrentWorkspace(); List styleList(); + + @Transactional + Long saveOrUpdateProject(ProjectDTO projectDTO); + + Long getByProjectId(Long projectId); } diff --git a/src/main/java/com/ai/da/service/impl/CollectionServiceImpl.java b/src/main/java/com/ai/da/service/impl/CollectionServiceImpl.java index a90ba255..454b3258 100644 --- a/src/main/java/com/ai/da/service/impl/CollectionServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/CollectionServiceImpl.java @@ -19,7 +19,6 @@ import com.ai.da.model.vo.UserLikeCollectionVO; import com.ai.da.service.CollectionElementService; import com.ai.da.service.CollectionService; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; @@ -196,7 +195,8 @@ public class CollectionServiceImpl extends ServiceImpl qw = new QueryWrapper<>(); qw.lambda().eq(MoodboardPosition::getCollectionId, id); List moodboardPositions = moodboardPositionMapper.selectList(qw); @@ -258,7 +258,8 @@ public class CollectionServiceImpl extends ServiceImpl resolveColorBoard(List collectionElements) { + @Override + public List resolveColorBoard(List collectionElements) { return CopyUtil.copyList(collectionElements, CollectionColorVO.class, (o, d) -> { String name = o.getName(); if (StringUtils.isBlank(name)) { diff --git a/src/main/java/com/ai/da/service/impl/SysFileServiceImpl.java b/src/main/java/com/ai/da/service/impl/SysFileServiceImpl.java index 031ee657..08d6f412 100644 --- a/src/main/java/com/ai/da/service/impl/SysFileServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/SysFileServiceImpl.java @@ -6,7 +6,9 @@ import com.ai.da.common.config.exception.BusinessException; import com.ai.da.common.enums.SysFileLevel1TypeEnum; import com.ai.da.common.enums.SysFileLevel2TypeEnum; import com.ai.da.common.utils.*; +import com.ai.da.mapper.primary.StyleMapper; import com.ai.da.mapper.primary.SysFileMapper; +import com.ai.da.mapper.primary.entity.Style; import com.ai.da.mapper.primary.entity.SysFile; import com.ai.da.model.vo.SysFileVO; import com.ai.da.service.SysFileService; @@ -43,6 +45,8 @@ public class SysFileServiceImpl extends ServiceImpl impl private SysFileMapper sysFileMapper; @Resource private FileProperties fileProperties; + @Resource + private StyleMapper styleMapper; @Transactional(rollbackFor = Exception.class) @Override @@ -267,4 +271,30 @@ public class SysFileServiceImpl extends ServiceImpl impl queryWrapper.in("id", ids); return sysFileMapper.selectList(queryWrapper); } + + @Override + public SysFile getOneBySex(Long styleId, String sex) { + Style style = new Style(); + if (styleId != null) { + style = styleMapper.selectById(styleId); + } + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(SysFile::getLevel1Type, "Models"); + qw.lambda().eq(SysFile::getLevel2Type, sex); + if (style.getId() != null) { + qw.lambda().eq(SysFile::getLevel3Type, style.getName()); + } + List sysFileList = sysFileMapper.selectList(qw); + if (!CollectionUtils.isEmpty(sysFileList)) { + return sysFileList.get(0); + } + return null; + } + + public static void main(String[] args) { + Style style = new Style(); + if (Objects.nonNull(style)) { + System.out.println("buxing"); + } + } } diff --git a/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java b/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java index 425199bd..ed6f38e8 100644 --- a/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java @@ -4,17 +4,20 @@ import cn.hutool.core.collection.CollectionUtil; import com.ai.da.common.config.exception.BusinessException; import com.ai.da.common.constant.CommonConstant; import com.ai.da.common.context.UserContext; +import com.ai.da.common.enums.CollectionLevel1TypeEnum; import com.ai.da.common.enums.CreditsEventsEnum; +import com.ai.da.common.enums.DesignTypeEnum; +import com.ai.da.common.response.PageBaseResponse; +import com.ai.da.common.response.Response; import com.ai.da.common.response.ResultEnum; import com.ai.da.common.utils.*; import com.ai.da.mapper.primary.*; import com.ai.da.mapper.primary.entity.*; +import com.ai.da.mapper.primary.entity.Collection; import com.ai.da.mapper.secondary.AttributeRetrievalMapper; import com.ai.da.mapper.secondary.entity.AttributeRecognitionJSON; -import com.ai.da.model.dto.PortfolioDTO; -import com.ai.da.model.dto.ProductImageInitializeDTO; -import com.ai.da.model.dto.ProductImageLikeDTO; -import com.ai.da.model.dto.ToProductImageDTO; +import com.ai.da.model.dto.*; +import com.ai.da.model.enums.Module; import com.ai.da.model.vo.*; import com.ai.da.python.PythonService; import com.ai.da.service.*; @@ -24,19 +27,24 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.base.Function; import com.google.gson.Gson; import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.*; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; @@ -58,6 +66,9 @@ public class UserLikeGroupServiceImpl extends ServiceImpl moduleList = projectDTO.getModuleList(); +// for (String module : moduleList) { +// +// } + + Long workspaceId = workspaceService.getByProjectId(project.getId()); + WorkspaceVO workspaceVO = workspaceService.getByIdNew(workspaceId); + + String process = project.getProcess(); + +// UserLikeGroup group = getByProjectId(projectDTO.getId()); +// if (Objects.isNull(group)) { +// throw new BusinessException("history.not.found"); +// } +// List userLikeVOS = userLikeService.getGroupDetail(group.getId()); +// String sex = null; +// +// QueryWrapper userLikeSortQw = new QueryWrapper<>(); +// userLikeSortQw.lambda().eq(UserLikeSort::getUserLikeGroupId, group.getId()); +// List userLikeSortList = userLikeSortMapper.selectList(userLikeSortQw); +// if (CollectionUtil.isEmpty(userLikeSortList)) { +// Integer sort = 1; +// for (UserLikeVO userLikeVO : userLikeVOS) { +// UserLikeSort userLikeSort = new UserLikeSort(); +// userLikeSort.setUserLikeId(userLikeVO.getId()); +// userLikeSort.setUserLikeGroupId(group.getId()); +// userLikeSort.setSort(sort); +// userLikeSortMapper.insert(userLikeSort); +// sort ++; +// } +// } +// +// userLikeVOS.forEach(o -> { +// TDesignPythonOutfit tDesignPythonOutfit1 = designPythonOutfitMapper.selectById(o.getDesignOutfitId()); +// o.setUrl(tDesignPythonOutfit1.getDesignUrl()); +// if (o.getUrl().contains("/")) { +// int index = o.getUrl().lastIndexOf("/"); +// o.setPictureName(o.getUrl().substring(index + 1)); +// } +// o.setDesignOutfitUrl(minioUtil.getPreSignedUrl(o.getUrl(), 24 * 60)); +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().eq(TDesignPythonOutfit::getDesignItemId, o.getDesignItemId()); +// List tDesignPythonOutfits = designPythonOutfitMapper.selectList(qw); +// if (CollectionUtil.isNotEmpty(tDesignPythonOutfits)) { +// TDesignPythonOutfit tDesignPythonOutfit = tDesignPythonOutfits.get(0); +// o.setDesignOutfitId(tDesignPythonOutfit.getId()); +// } +// +// QueryWrapper userLikeSortQueryWrapper = new QueryWrapper<>(); +// userLikeSortQueryWrapper.lambda().eq(UserLikeSort::getUserLikeId, o.getId()); +// List userLikeSorts = userLikeSortMapper.selectList(userLikeSortQueryWrapper); +// if (CollectionUtil.isNotEmpty(userLikeSorts)) { +// UserLikeSort userLikeSort = userLikeSorts.get(0); +// o.setSort(userLikeSort.getSort()); +// o.setUserLikeSortId(userLikeSort.getId()); +// } +// }); +// UserLikeCollectionVO userLikeCollection = collectionService.chooseCollection(group.getCollectionId()); +// Integer beenPublished = 0; +// QueryWrapper qw = new QueryWrapper<>(); +// qw.lambda().eq(Portfolio::getUserLikeGroupSourceId, group.getId()); +// List portfolios = portfolioMapper.selectList(qw); +//// Portfolio portfolio = new Portfolio(); +// PortfolioDTO portfolioDTO = new PortfolioDTO(); +// if (CollectionUtil.isNotEmpty(portfolios)) { +//// portfolio = portfolios.get(0); +// portfolioDTO = CopyUtil.copyObject(portfolios.get(0), PortfolioDTO.class); +// beenPublished = 1; +// portfolioDTO.setTagsDTO(tagsMapper.getTagByPortfolioId(portfolioDTO.getId())); +// } + return new ProjectChooseVO(projectDTO.getId(), workspaceVO, process); + } + + private UserLikeGroup getByProjectId(Long projectId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(UserLikeGroup::getProjectId, projectId); + List userLikeGroupList = userLikeGroupMapper.selectList(qw); + if (CollectionUtil.isEmpty(userLikeGroupList)) { + throw new BusinessException("Lack of associated userLikeGroup."); + } + return userLikeGroupList.get(0); + } + @Override public void deleteTrialData(Long userId) { QueryWrapper qw = new QueryWrapper<>(); @@ -1022,4 +1131,560 @@ public class UserLikeGroupServiceImpl extends ServiceImpl getPage(ProjectQueryDTO query) { + AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder(); + // 分页数据 + QueryWrapper queryWrapper = new QueryWrapper<>(); + + queryWrapper.eq("account_id", authPrincipalVo.getId()); + if (!StringUtils.isEmpty(query.getProjectName())) { + queryWrapper.like("name", query.getProjectName()); + } + if (Objects.nonNull(query.getStartDate())) { + queryWrapper.ge("update_time", new Date(query.getStartDate())); + } + if (Objects.nonNull(query.getEndDate())) { + queryWrapper.le("update_time", new Date(query.getEndDate())); + } + // 新增分类过滤 + if (CollectionUtil.isNotEmpty(query.getClassificationIdList())) { + List projectIdList = new ArrayList<>(); + if (query.getIntersection() == 0) { + for (Long classificationId : query.getClassificationIdList()) { + projectIdList.addAll(classificationService.getLibraryIdListByClassificationId(classificationId)); + } + if (CollectionUtil.isNotEmpty(projectIdList)) { + queryWrapper.in("id", projectIdList); + }else { + return new Page<>(); + } + }else { + for (int i = 0; i < query.getClassificationIdList().size(); i++) { + List historyIdListByClassificationId = classificationService.getLibraryIdListByClassificationId(query.getClassificationIdList().get(i)); + if (i == 0) { + projectIdList.addAll(historyIdListByClassificationId); + }else { + projectIdList.retainAll(historyIdListByClassificationId); + } + if (CollectionUtil.isEmpty(projectIdList)) { + return new Page<>(); + } + } + queryWrapper.in("id", projectIdList); + } + } + queryWrapper.orderByDesc("update_date"); + IPage page = projectMapper.selectPage( + new Page<>(query.getPage(), query.getSize()), queryWrapper); + if (CollectionUtils.isEmpty(page.getRecords())) { + return new Page<>(); + } + Set projectIdSet = page.getRecords().stream().map(Project::getId).collect(Collectors.toSet()); + QueryWrapper userLikeGroupQueryWrapper = new QueryWrapper<>(); + userLikeGroupQueryWrapper.lambda().in(UserLikeGroup::getProjectId, projectIdSet); + List userLikeGroups = userLikeGroupMapper.selectList(userLikeGroupQueryWrapper); + + List groupIds = userLikeGroups.stream().map(UserLikeGroup::getId).collect(Collectors.toList()); + List groupDetails = userLikeService.getGroupDetails(groupIds); +// if (CollectionUtils.isEmpty(groupDetails)) { +// throw new BusinessException("groupDetails.not.found"); +// } + Map> groupDetailMap = groupDetails.stream() + .collect(Collectors.groupingBy(UserLikeVO::getUserLikeGroupId)); + + Account account = accountService.getById(authPrincipalVo.getId()); + IPage convert = page.convert((Function) project -> { + if (project != null) { + ProjectVO projectVO = CopyUtil.copyObject(project, ProjectVO.class); + projectVO.setUpdateDate(project.getUpdateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); + + QueryWrapper userLikeGroupQueryWrapper1 = new QueryWrapper<>(); + userLikeGroupQueryWrapper1.lambda().eq(UserLikeGroup::getProjectId, projectVO.getId()); + UserLikeGroup userLikeGroup = userLikeGroupMapper.selectOne(userLikeGroupQueryWrapper1); + UserLikeGroupVO userLikeGroupVO = CopyUtil.copyObject(userLikeGroup, UserLikeGroupVO.class); + userLikeGroupVO.setAuthor(account.getUserName()); + //count 和detail + if (groupDetailMap.keySet().contains(userLikeGroupVO.getId())) { + List details = groupDetailMap.get(userLikeGroupVO.getId()); + for (UserLikeVO detail : details) { + TDesignPythonOutfit tDesignPythonOutfit = designPythonOutfitMapper.selectById(detail.getDesignOutfitId()); + detail.setUrl(minioUtil.getPreSignedUrl(tDesignPythonOutfit.getDesignUrl(), 24 * 60)); + } + userLikeGroupVO.setGroupDetails(details); + userLikeGroupVO.setSketchCount(CollectionUtils.isEmpty(details) ? 0 : details.size()); + }else { + userLikeGroupVO.setSketchCount(0); + } + if (userLikeGroupVO.getOriginal() == 0) { + userLikeGroupVO.setOriginalAccountName(accountService.getById(userLikeGroupVO.getOriginalAccountId()).getUserName()); + Portfolio byId = portfolioService.getByIdAll(userLikeGroupVO.getOriginalPortfolioId()); + if (Objects.nonNull(byId)) { + String portfolioName = byId.getPortfolioName(); + userLikeGroupVO.setOriginalPortfolioName(portfolioName); + } + } + projectVO.setUserLikeGroupVO(userLikeGroupVO); + return projectVO; + } + return null; + }); + return convert; + } + + @Override + public ModuleChooseVO getModuleContent(ProjectDTO projectDTO) { + ModuleChooseVO moduleChooseVO = new ModuleChooseVO(); + moduleChooseVO.setProjectId(projectDTO.getId()); +// UserLikeCollectionVO userLikeCollectionVO = new UserLikeCollectionVO(); + for (String module : projectDTO.getModuleList()) { + if (module.equals(Module.colorBoard.name())) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectDTO.getId()); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.COLOR_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + moduleChooseVO.setColorBoard(collectionService.resolveColorBoard(collectionElements)); + }else if (module.equals(Module.moodBoard.name())) { + MoodBoardModuleChooseVO moodBoardModuleChooseVO = new MoodBoardModuleChooseVO(); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectDTO.getId()); + qw.lambda().ne(CollectionElement::getCollectionId, 0); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + Long collectionId = null; + for (CollectionElement collectionElement : collectionElements) { + if (collectionElement.getCollectionId() != null) { + collectionId = collectionElement.getCollectionId(); + break; + } + } + Collection collection = collectionService.getById(collectionId); + if (null != collection.getMoodboardPosition()) { + String moodboardPositionString = collectionService.getMoodboardPositionString(collection.getId()); + if (StringUtils.isEmpty(moodboardPositionString)) { + moodBoardModuleChooseVO.setMoodboardPosition(collection.getMoodboardPosition()); + }else { + moodBoardModuleChooseVO.setMoodboardPosition(moodboardPositionString); + } + } + if (collection.getMoodTemplateId() != null) { + CollectionElement layoutElement = collectionElementMapper.selectById(collection.getMoodTemplateId()); + moodBoardModuleChooseVO.setMoodTemplateId(collection.getMoodTemplateId()); + moodBoardModuleChooseVO.setMoodTemplateName(layoutElement.getName()); + moodBoardModuleChooseVO.setMoodTemplateUrl(minioUtil.getPreSignedUrl(layoutElement.getUrl(), 24 * 60)); + } + List list = new ArrayList<>(); + for (CollectionElement collectionElement : collectionElements) { + CollectionElementVO collectionElementVO = CopyUtil.copyObject(collectionElement, CollectionElementVO.class); + collectionElementVO.setDesignType(DesignTypeEnum.COLLECTION.getRealName()); + String url = collectionElement.getUrl(); + collectionElementVO.setOriginalUrl(url); + if (minioUtil.doesObjectExist(url)) { + collectionElementVO.setUrl(minioUtil.getPreSignedUrl(url, 24 * 60)); + } + if (minioUtil.doesObjectExist(collectionElementVO.getOriginalUrl())) { + list.add(collectionElementVO); + } + } + moodBoardModuleChooseVO.setMoodBoards(list); + moduleChooseVO.setMoodBoard(moodBoardModuleChooseVO); + }else if (module.equals(Module.printBoard.name())) { + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectDTO.getId()); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + List list = new ArrayList<>(); + + for (CollectionElement collectionElement : collectionElements) { + CollectionElementVO collectionElementVO = CopyUtil.copyObject(collectionElement, CollectionElementVO.class); + collectionElementVO.setIsPin(collectionElement.getHasPin()); + collectionElementVO.setDesignType(DesignTypeEnum.COLLECTION.getRealName()); + String url = collectionElement.getUrl(); + collectionElementVO.setOriginalUrl(url); + if (minioUtil.doesObjectExist(url)) { + collectionElementVO.setUrl(minioUtil.getPreSignedUrl(url, 24 * 60)); + } + if (minioUtil.doesObjectExist(collectionElementVO.getOriginalUrl())) { + list.add(collectionElementVO); + } + } + moduleChooseVO.setPrintBoard(list); + }else if (module.equals(Module.sketchBoard.name())) { + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectDTO.getId()); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + List list = new ArrayList<>(); + + for (CollectionElement collectionElement : collectionElements) { + CollectionElementVO collectionElementVO = CopyUtil.copyObject(collectionElement, CollectionElementVO.class); + collectionElementVO.setIsPin(collectionElement.getHasPin()); + collectionElementVO.setDesignType(DesignTypeEnum.COLLECTION.getRealName()); + String url = collectionElement.getUrl(); + collectionElementVO.setOriginalUrl(url); + if (minioUtil.doesObjectExist(url)) { + collectionElementVO.setUrl(minioUtil.getPreSignedUrl(url, 24 * 60)); + if (url.contains(".")) { + String[] split = url.split("\\."); + collectionElementVO.setUrlWithWhiteSide(minioUtil.getPreSignedUrl(split[0] + "-show." + split[1], 24 * 60)); + } else { + collectionElementVO.setUrlWithWhiteSide(minioUtil.getPreSignedUrl(url + "-show", 24 * 60)); + } + } + if (minioUtil.doesObjectExist(collectionElementVO.getOriginalUrl())) { + list.add(collectionElementVO); + } + } + moduleChooseVO.setSketchBoard(list); + }else if (module.equals(Module.design.name())) { + DesignModuleChooseVO vo = new DesignModuleChooseVO(); + UserLikeGroup group = getByProjectId(projectDTO.getId()); + Long userGroupId = group.getId(); +// if (Objects.isNull(group)) { +// throw new BusinessException("history.not.found"); +// } + List userLikeVOS = userLikeService.getGroupDetail(userGroupId); + String sex = null; + + QueryWrapper userLikeSortQw = new QueryWrapper<>(); + userLikeSortQw.lambda().eq(UserLikeSort::getUserLikeGroupId, userGroupId); + List userLikeSortList = userLikeSortMapper.selectList(userLikeSortQw); + if (CollectionUtil.isEmpty(userLikeSortList)) { + Integer sort = 1; + for (UserLikeVO userLikeVO : userLikeVOS) { + UserLikeSort userLikeSort = new UserLikeSort(); + userLikeSort.setUserLikeId(userLikeVO.getId()); + userLikeSort.setUserLikeGroupId(userGroupId); + userLikeSort.setSort(sort); + userLikeSortMapper.insert(userLikeSort); + sort ++; + } + } + + userLikeVOS.forEach(o -> { + TDesignPythonOutfit tDesignPythonOutfit1 = designPythonOutfitMapper.selectById(o.getDesignOutfitId()); + o.setUrl(tDesignPythonOutfit1.getDesignUrl()); + if (o.getUrl().contains("/")) { + int index = o.getUrl().lastIndexOf("/"); + o.setPictureName(o.getUrl().substring(index + 1)); + } + o.setDesignOutfitUrl(minioUtil.getPreSignedUrl(o.getUrl(), 24 * 60)); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(TDesignPythonOutfit::getDesignItemId, o.getDesignItemId()); + List tDesignPythonOutfits = designPythonOutfitMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(tDesignPythonOutfits)) { + TDesignPythonOutfit tDesignPythonOutfit = tDesignPythonOutfits.get(0); + o.setDesignOutfitId(tDesignPythonOutfit.getId()); + } + + QueryWrapper userLikeSortQueryWrapper = new QueryWrapper<>(); + userLikeSortQueryWrapper.lambda().eq(UserLikeSort::getUserLikeId, o.getId()); + List userLikeSorts = userLikeSortMapper.selectList(userLikeSortQueryWrapper); + if (CollectionUtil.isNotEmpty(userLikeSorts)) { + UserLikeSort userLikeSort = userLikeSorts.get(0); + o.setSort(userLikeSort.getSort()); + o.setUserLikeSortId(userLikeSort.getId()); + } + }); + vo.setUserGroupId(userGroupId); + vo.setUserLikeDetails(userLikeVOS); + }else if (module.equals(Module.canvas.name())) { + CavasModuleChooseVO vo = new CavasModuleChooseVO(); + + UserLikeGroup userLikeGroup = getByProjectId(projectDTO.getId()); + + Integer beenPublished = 0; + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Portfolio::getUserLikeGroupSourceId, userLikeGroup.getId()); + List portfolios = portfolioMapper.selectList(qw); + + PortfolioDTO portfolioDTO = new PortfolioDTO(); + if (CollectionUtil.isNotEmpty(portfolios)) { + + portfolioDTO = CopyUtil.copyObject(portfolios.get(0), PortfolioDTO.class); + beenPublished = 1; + portfolioDTO.setTagsDTO(tagsMapper.getTagByPortfolioId(portfolioDTO.getId())); + } + vo.setBeenPublished(beenPublished); + vo.setPortfolioDTO(portfolioDTO); + moduleChooseVO.setCanvas(vo); + }else if (module.equals(Module.toProduct.name())) { + UserLikeGroup userLikeGroup = getByProjectId(projectDTO.getId()); + Long userLikeGroupId = userLikeGroup.getId(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(ToProductImageResult::getIsLike, 1); + qw.lambda().eq(ToProductImageResult::getUserLikeGroupId, userLikeGroupId); + qw.lambda().eq(ToProductImageResult::getResultType, "ToProductImage"); + List toProductImageResults = toProductImageResultMapper.selectList(qw); + for (ToProductImageResult toProductImageResult : toProductImageResults) { + toProductImageResult.setUrl(minioUtil.getPreSignedUrl(toProductImageResult.getUrl(), 24 * 60)); + } + List toProductImageResultVOS = CopyUtil.copyList(toProductImageResults, ToProductImageResultVO.class); + for (ToProductImageResultVO toProductImageResultVO : toProductImageResultVOS) { + if (toProductImageResultVO.getElementType().equals("ProductElement")) { + ToProductElement toProductElement = toProductElementMapper.selectById(toProductImageResultVO.getElementId()); + toProductImageResultVO.setSourceUrl(minioUtil.getPreSignedUrl(toProductElement.getUrl(), 24 * 60)); + }else if ((toProductImageResultVO.getElementType().equals("DesignOutfit"))) { + TDesignPythonOutfit tDesignPythonOutfit = designPythonOutfitMapper.selectById(toProductImageResultVO.getElementId()); + toProductImageResultVO.setSourceUrl(minioUtil.getPreSignedUrl(tDesignPythonOutfit.getDesignUrl(), 24 * 60)); + }else { + ToProductImageResult toProductImageResult1 = toProductImageResultMapper.selectById(toProductImageResultVO.getElementId()); + toProductImageResultVO.setSourceUrl(minioUtil.getPreSignedUrl(toProductImageResult1.getUrl(), 24 * 60)); + } + } + moduleChooseVO.setToProduct(toProductImageResultVOS); + }else if (module.equals(Module.relight.name())) { + UserLikeGroup userLikeGroup = getByProjectId(projectDTO.getId()); + Long userLikeGroupId = userLikeGroup.getId(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(ToProductImageResult::getIsLike, 1); + qw.lambda().eq(ToProductImageResult::getUserLikeGroupId, userLikeGroupId); + qw.lambda().eq(ToProductImageResult::getResultType, "Relight"); + List toProductImageResults = toProductImageResultMapper.selectList(qw); + for (ToProductImageResult toProductImageResult : toProductImageResults) { + toProductImageResult.setUrl(minioUtil.getPreSignedUrl(toProductImageResult.getUrl(), 24 * 60)); + } + List toProductImageResultVOS = CopyUtil.copyList(toProductImageResults, ToProductImageResultVO.class); + for (ToProductImageResultVO toProductImageResultVO : toProductImageResultVOS) { + if (toProductImageResultVO.getElementType().equals("ProductElement")) { + ToProductElement toProductElement = toProductElementMapper.selectById(toProductImageResultVO.getElementId()); + toProductImageResultVO.setSourceUrl(minioUtil.getPreSignedUrl(toProductElement.getUrl(), 24 * 60)); + }else if ((toProductImageResultVO.getElementType().equals("DesignOutfit"))) { + TDesignPythonOutfit tDesignPythonOutfit = designPythonOutfitMapper.selectById(toProductImageResultVO.getElementId()); + toProductImageResultVO.setSourceUrl(minioUtil.getPreSignedUrl(tDesignPythonOutfit.getDesignUrl(), 24 * 60)); + }else { + ToProductImageResult toProductImageResult1 = toProductImageResultMapper.selectById(toProductImageResultVO.getElementId()); + toProductImageResultVO.setSourceUrl(minioUtil.getPreSignedUrl(toProductImageResult1.getUrl(), 24 * 60)); + } + } + moduleChooseVO.setToProduct(toProductImageResultVOS); + } + } + return moduleChooseVO; + } + + @Override + public ModuleChooseVO saveModuleContent(ModuleSaveDTO moduleSaveDTO) { + Long accountId = UserContext.getUserHolder().getId(); + Long projectId = moduleSaveDTO.getProjectId(); + if (Objects.nonNull(moduleSaveDTO.getMoodBoard())) { + MoodBoardModuleSaveDTO moodBoard = moduleSaveDTO.getMoodBoard(); + if (moodBoard.getMoodTemplateId() != null) { + // moodboard合成图存储 + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, moduleSaveDTO.getProjectId()); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()); + qw.lambda().eq(CollectionElement::getCollectionId, 0); + List compositeImageList = collectionElementMapper.selectList(qw); + if (CollectionUtils.isEmpty(compositeImageList)) { + CollectionElement collectionElement = collectionElementMapper.selectById(moodBoard.getMoodTemplateId()); + collectionElement.setProjectId(moduleSaveDTO.getProjectId()); + collectionElementMapper.updateById(collectionElement); + if (!StringUtils.isEmpty(moodBoard.getMoodboardPosition())) { + // 合成图位置信息通过collectElementId关联(旧逻辑通过collectionId关联) + designService.parseMoodboardPosition(moodBoard.getMoodboardPosition(), collectionElement.getId()); + } + }else { + CollectionElement compositeImage = compositeImageList.get(0); + if (!Objects.equals(compositeImage.getId(), moodBoard.getMoodTemplateId())) { + compositeImage.setProjectId(null); + CollectionElement collectionElement = collectionElementMapper.selectById(moodBoard.getMoodTemplateId()); + collectionElement.setProjectId(moduleSaveDTO.getProjectId()); + collectionElementMapper.updateById(collectionElement); + if (!StringUtils.isEmpty(moodBoard.getMoodboardPosition())) { + // 合成图位置信息通过collectElementId关联(旧逻辑通过collectionId关联) + designService.parseMoodboardPosition(moodBoard.getMoodboardPosition(), collectionElement.getId()); + } + } + } + } + List moodBoards = moodBoard.getMoodBoards(); + if (CollectionUtil.isNotEmpty(moodBoards)) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectId); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()); + qw.lambda().ne(CollectionElement::getCollectionId, 0); + List collectionElements = collectionElementMapper.selectList(qw); + Set old = collectionElements.stream().map(CollectionElement::getId).collect(Collectors.toSet()); + + for (DesignCollectionElementDTO board : moodBoards) { + if (board.getDesignType().equals(DesignTypeEnum.LIBRARY.getRealName())) { + Library library = libraryMapper.selectById(board.getId()); + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel1Type(CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()); + collectionElement.setName(library.getName()); + collectionElement.setUrl(library.getUrl()); + collectionElement.setHasPin((byte) 0); + collectionElement.setMd5(library.getMd5()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + }else if (board.getDesignType().equals(DesignTypeEnum.GENERATE.getRealName())) { + GenerateDetail generateDetail = generateDetailMapper.selectById(board.getId()); + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel1Type(CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()); +// collectionElement.setName(generateDetail.get()); + collectionElement.setUrl(generateDetail.getUrl()); + collectionElement.setHasPin((byte) 0); + collectionElement.setMd5(generateDetail.getMd5()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + }else { + if (old.contains(board.getId())) { + old.remove(board.getId()); + }else { + CollectionElement collectionElement = collectionElementMapper.selectById(board.getId()); + collectionElement.setProjectId(projectId); + collectionElementMapper.updateById(collectionElement); + } + } + } + collectionElementMapper.deleteBatchIds(old); + } + } + if (CollectionUtils.isEmpty(moduleSaveDTO.getPrintBoard())){ + List printBoards = moduleSaveDTO.getPrintBoard(); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectId); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + Set old = collectionElements.stream().map(CollectionElement::getId).collect(Collectors.toSet()); + + for (DesignCollectionPrintElementDTO board : printBoards) { + if (board.getDesignType().equals(DesignTypeEnum.LIBRARY.getRealName())) { + Library library = libraryMapper.selectById(board.getId()); + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel1Type(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); + collectionElement.setLevel2Type(board.getLevel2Type()); + collectionElement.setName(library.getName()); + collectionElement.setUrl(library.getUrl()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setMd5(library.getMd5()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + }else if (board.getDesignType().equals(DesignTypeEnum.GENERATE.getRealName())) { + GenerateDetail generateDetail = generateDetailMapper.selectById(board.getId()); + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel1Type(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); +// collectionElement.setLevel2Type(board.getLevel2Type()); +// collectionElement.setName(generateDetail.get()); + collectionElement.setUrl(generateDetail.getUrl()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setMd5(generateDetail.getMd5()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + }else { + if (old.contains(board.getId())) { + CollectionElement collectionElement = collectionElementMapper.selectById(board.getId()); +// collectionElement.setLevel2Type(board.getLevel2Type()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setUpdateDate(new Date()); + collectionElementMapper.updateById(collectionElement); + old.remove(board.getId()); + }else { + CollectionElement collectionElement = collectionElementMapper.selectById(board.getId()); + collectionElement.setProjectId(projectId); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setUpdateDate(new Date()); + collectionElementMapper.updateById(collectionElement); + } + } + } + collectionElementMapper.deleteBatchIds(old); + } + if (CollectionUtils.isEmpty(moduleSaveDTO.getColorBoard())){ + List colorBoards = moduleSaveDTO.getColorBoard(); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectId); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.COLOR_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + Set old = collectionElements.stream().map(CollectionElement::getId).collect(Collectors.toSet()); + + for (CollectionColorDTO board : colorBoards) { + if (old.contains(Long.valueOf(board.getId()))) { + old.remove(Long.valueOf(board.getId())); + }else { + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel2Type(CollectionLevel1TypeEnum.COLOR_BOARD.getRealName()); + collectionElement.setName(board.getName()); + collectionElement.setHasPin((byte) 0); + collectionElement.setColorRgb(board.getRgbValue()); + collectionElement.setMd5("0"); + collectionElement.setGradientString(board.getGradientString()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + } + } + collectionElementMapper.deleteBatchIds(old); + } + if (CollectionUtils.isEmpty(moduleSaveDTO.getSketchBoard())){ + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectId); + qw.lambda().eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()); + List collectionElements = collectionElementMapper.selectList(qw); + Set old = collectionElements.stream().map(CollectionElement::getId).collect(Collectors.toSet()); + List sketchBoards = moduleSaveDTO.getSketchBoard(); + for (CollectionSketchDTO board : sketchBoards) { + if (board.getDesignType().equals(DesignTypeEnum.LIBRARY.getRealName())) { + Library library = libraryMapper.selectById(board.getSketchBoardId()); + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel1Type(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); + collectionElement.setLevel2Type(board.getLevel2Type()); + collectionElement.setName(library.getName()); + collectionElement.setUrl(library.getUrl()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setMd5(library.getMd5()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + }else if (board.getDesignType().equals(DesignTypeEnum.GENERATE.getRealName())) { + GenerateDetail generateDetail = generateDetailMapper.selectById(board.getSketchBoardId()); + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setProjectId(projectId); + collectionElement.setLevel1Type(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); + collectionElement.setLevel2Type(board.getLevel2Type()); +// collectionElement.setName(generateDetail.get()); + collectionElement.setUrl(generateDetail.getUrl()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setMd5(generateDetail.getMd5()); + collectionElement.setCreateDate(new Date()); + collectionElementMapper.insert(collectionElement); + }else { + if (old.contains(board.getSketchBoardId())) { + CollectionElement collectionElement = collectionElementMapper.selectById(board.getSketchBoardId()); + collectionElement.setLevel2Type(board.getLevel2Type()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setUpdateDate(new Date()); + collectionElementMapper.updateById(collectionElement); + old.remove(board.getSketchBoardId()); + }else { + CollectionElement collectionElement = collectionElementMapper.selectById(board.getSketchBoardId()); + collectionElement.setProjectId(projectId); + collectionElement.setLevel2Type(board.getLevel2Type()); + collectionElement.setHasPin(board.getIsPin()); + collectionElement.setUpdateDate(new Date()); + collectionElementMapper.updateById(collectionElement); + } + } + } + collectionElementMapper.deleteBatchIds(old); + } + return null; + } } diff --git a/src/main/java/com/ai/da/service/impl/WorkspaceServiceImpl.java b/src/main/java/com/ai/da/service/impl/WorkspaceServiceImpl.java index b4b5cf8d..a52039f4 100644 --- a/src/main/java/com/ai/da/service/impl/WorkspaceServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/WorkspaceServiceImpl.java @@ -8,20 +8,24 @@ import com.ai.da.common.response.ResultEnum; import com.ai.da.common.utils.*; import com.ai.da.mapper.primary.*; import com.ai.da.mapper.primary.entity.*; +import com.ai.da.model.dto.ProjectDTO; import com.ai.da.model.dto.WorkspaceDTO; import com.ai.da.model.dto.WorkspaceSaveDTO; import com.ai.da.model.enums.*; import com.ai.da.model.vo.*; +import com.ai.da.service.SysFileService; import com.ai.da.service.WorkspaceService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sun.org.apache.bcel.internal.generic.NEW; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -30,6 +34,7 @@ import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.annotation.Resource; import java.io.*; import java.nio.file.Files; +import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -46,6 +51,9 @@ public class WorkspaceServiceImpl extends ServiceImpl selectWorkspacePage(IPage page, WorkspaceVO workspace) { @@ -583,6 +594,107 @@ public class WorkspaceServiceImpl extends ServiceImpl qw = new QueryWrapper<>(); + qw.lambda().eq(Workspace::getProjectId, projectDTO.getId()); + List workspaces = workspaceMapper.selectList(qw); + if (CollectionUtils.isEmpty(workspaces)) { + throw new BusinessException("Lack of associated workspace."); + }else { + Workspace workspace = workspaces.get(0); + Workspace workspaceNew = CopyUtil.copyObject(projectDTO.getWorkspace(), Workspace.class); + workspaceNew.setId(workspace.getId()); + workspace.setUpdateTime(LocalDateTime.now()); + workspaceMapper.updateById(workspaceNew); + } + + if (projectDTO.getStyleId() != null) { + QueryWrapper wRSQW = new QueryWrapper<>(); + wRSQW.lambda().eq(WorkspaceRelStyle::getWorkspaceId, projectDTO.getWorkspace().getId()); + List workspaceRelStyles = workspaceRelStyleMapper.selectList(wRSQW); + if (CollectionUtils.isEmpty(workspaceRelStyles)) { + WorkspaceRelStyle rel = new WorkspaceRelStyle(); + rel.setWorkspaceId(projectDTO.getWorkspace().getId()); + rel.setStyleId(projectDTO.getStyleId()); + workspaceRelStyleMapper.insert(rel); + }else { + WorkspaceRelStyle workspaceRelStyleOld = workspaceRelStyles.get(0); + if (!Objects.equals(workspaceRelStyleOld.getStyleId(), projectDTO.getStyleId())) { + workspaceRelStyleOld.setStyleId(projectDTO.getStyleId()); + workspaceRelStyleMapper.updateById(workspaceRelStyleOld); + } + } + }else { + QueryWrapper wRSQW = new QueryWrapper<>(); + wRSQW.lambda().eq(WorkspaceRelStyle::getWorkspaceId, projectDTO.getWorkspace().getId()); + List workspaceRelStyles = workspaceRelStyleMapper.selectList(wRSQW); + if (!CollectionUtils.isEmpty(workspaceRelStyles)) { + workspaceRelStyleMapper.deleteBatchIds(workspaceRelStyles); + } + } + return projectId; + }else { + Project project = CopyUtil.copyObject(projectDTO, Project.class); + project.setAccountId(userInfo.getId()); + LocalDateTime now = LocalDateTime.now(); + project.setCreateTime(now); + project.setUpdateTime(now); + projectMapper.insert(project); + + Workspace workspace = CopyUtil.copyObject(projectDTO.getWorkspace(), Workspace.class); + workspace.setIsLastIndex(0); + workspace.setAccountId(userInfo.getId()); + workspace.setProjectId(project.getId()); + workspace.setCreateTime(LocalDateTime.now()); + workspace.setUpdateTime(LocalDateTime.now()); + + if (projectDTO.getProcess().equals(DesignProcess.SERIES_DESIGN.name())) { + SysFile sysFile = sysFileService.getOneBySex(projectDTO.getStyleId(), projectDTO.getWorkspace().getSex()); + + if (projectDTO.getWorkspace().getSex().equals(Sex.FEMALE.getValue())) { + workspace.setMannequinFemaleId(sysFile.getId()); + workspace.setMannequinFemaleType("System"); + }else { + workspace.setMannequinMaleId(sysFile.getId()); + workspace.setMannequinMaleType("System"); + } + } + + workspaceMapper.insert(workspace); + + if (projectDTO.getStyleId() != null) { + WorkspaceRelStyle rel = new WorkspaceRelStyle(); + rel.setWorkspaceId(workspace.getId()); + rel.setStyleId(projectDTO.getStyleId()); + workspaceRelStyleMapper.insert(rel); + } + return project.getId(); + } + } + + @Override + public Long getByProjectId(Long projectId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Workspace::getProjectId, projectId); + List workspaceList = workspaceMapper.selectList(qw); + if (CollectionUtils.isEmpty(workspaceList)) { + throw new BusinessException("Lack of associated workspace."); + } + return workspaceList.get(0).getId(); + } + public static List getPNGFiles(String directoryPath) { List pngFiles = new ArrayList<>(); File directory = new File(directoryPath); diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 9fcc04d6..c7762a20 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -20,7 +20,7 @@ spring.security.jwtExpiration=8640000000 spring.security.ignorePaths=/,/favicon.ico,/doc.html,/webjars/**,/swagger-resources,/v2/api-docs,\ /api/account/**,/api/element/**,/api/python/**,/api/design/**,/api/history/**,/api/library/**,/api/third/party/**,/api/generate/**,/api/workspace/**,/api/classification/**,\ /api/product/**,/api/ali-pay/**,/api/order-info/**,/api/paypal/**,/api/credits/**,/api/inquiry/**,/api/tasks/**,/api/python/prepareForSR,/api/alipay-hk/**,/api/portfolio/**,\ - /api/stripe/**,/api/message/**,/api/tags/**,/notification/**,/api/affiliate/** + /api/stripe/**,/api/message/**,/api/tags/**,/notification/**,/api/affiliate/**,/api/project/** spring.security.authApi=/auth/login diff --git a/src/main/resources/mapper/primary/CollectionElementMapper.xml.xml b/src/main/resources/mapper/primary/CollectionElementMapper.xml.xml new file mode 100644 index 00000000..ab39eb67 --- /dev/null +++ b/src/main/resources/mapper/primary/CollectionElementMapper.xml.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/src/main/resources/mapper/primary/CollectionMapper.xml b/src/main/resources/mapper/primary/CollectionMapper.xml index 055fb4be..5ffd2ffa 100644 --- a/src/main/resources/mapper/primary/CollectionMapper.xml +++ b/src/main/resources/mapper/primary/CollectionMapper.xml @@ -18,4 +18,11 @@ #{createDate}); + diff --git a/src/main/resources/mapper/primary/DesignItemMapper.xml b/src/main/resources/mapper/primary/DesignItemMapper.xml index c6b9689d..e26b90b6 100644 --- a/src/main/resources/mapper/primary/DesignItemMapper.xml +++ b/src/main/resources/mapper/primary/DesignItemMapper.xml @@ -30,4 +30,11 @@ #{createDate}); + diff --git a/src/main/resources/mapper/primary/DesignMapper.xml b/src/main/resources/mapper/primary/DesignMapper.xml index e887f921..50cd460c 100644 --- a/src/main/resources/mapper/primary/DesignMapper.xml +++ b/src/main/resources/mapper/primary/DesignMapper.xml @@ -65,4 +65,11 @@ ORDER BY a.account_id ASC;--> + diff --git a/src/main/resources/mapper/primary/TDesignPythonOutfitDetailMapper.xml b/src/main/resources/mapper/primary/TDesignPythonOutfitDetailMapper.xml index b7b9b67d..ac8f5eca 100644 --- a/src/main/resources/mapper/primary/TDesignPythonOutfitDetailMapper.xml +++ b/src/main/resources/mapper/primary/TDesignPythonOutfitDetailMapper.xml @@ -25,4 +25,8 @@ select * from t_design_python_outfit_detail where is_deleted = 0 + diff --git a/src/main/resources/mapper/primary/TDesignPythonOutfitMapper.xml b/src/main/resources/mapper/primary/TDesignPythonOutfitMapper.xml index 9079c1b0..3717e351 100644 --- a/src/main/resources/mapper/primary/TDesignPythonOutfitMapper.xml +++ b/src/main/resources/mapper/primary/TDesignPythonOutfitMapper.xml @@ -20,4 +20,8 @@ select * from t_design_python_outfit where is_deleted = 0 + diff --git a/src/main/resources/mapper/primary/UserLikeGroupMapper.xml b/src/main/resources/mapper/primary/UserLikeGroupMapper.xml index 463fc854..9babfe9a 100644 --- a/src/main/resources/mapper/primary/UserLikeGroupMapper.xml +++ b/src/main/resources/mapper/primary/UserLikeGroupMapper.xml @@ -14,13 +14,24 @@ insert into t_user_like_group - (account_id,collection_id,`name`,create_date,update_date) + (account_id,collection_id,`name`,create_date,update_date) values( - #{accountId}, - #{collectionId}, - #{name}, - #{createDate}, - #{updateDate}); + #{accountId}, + #{collectionId}, + #{name}, + #{createDate}, + #{updateDate}); +