diff --git a/aida.iml b/aida.iml deleted file mode 100644 index 58ada0c3..00000000 --- a/aida.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/main/java/com/ai/da/service/GenerateService.java b/src/main/java/com/ai/da/service/GenerateService.java index da3c09bb..ccd3cda5 100644 --- a/src/main/java/com/ai/da/service/GenerateService.java +++ b/src/main/java/com/ai/da/service/GenerateService.java @@ -98,4 +98,6 @@ public interface GenerateService extends IService { byte[] downloadVideoOrImage(String url); String createGoogleAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt); + + String toProductAsyncTask(String imagePath, String useModel, String prompt); } diff --git a/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java b/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java index 0f07b208..4726def4 100644 --- a/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java @@ -244,7 +244,9 @@ public class CollectionElementServiceImpl extends ServiceImpl().eq(CollectionElement::getId, sketchBoard.getSketchBoardId()).select(CollectionElement::getLevel3Type)).getLevel3Type(); + } else if ("Library".equals(sketchBoard.getDesignType())){ + level3Type = libraryService.getById(sketchBoard.getSketchBoardId()).getLevel3Type(); + } //判断性别和当前project性别是否一致,不一致则移除 - String level3Type = collectionElementMapper.selectOne(new LambdaQueryWrapper().eq(CollectionElement::getId, sketchBoard.getSketchBoardId()).select(CollectionElement::getLevel3Type)).getLevel3Type(); if (!level3Type.equalsIgnoreCase(designDTO.getModelSex())) { sketchIterator.remove(); } + } //再次判断草图板数量,如果为null,则跳出当前if if (CollectionUtil.isNotEmpty(designDTO.getSketchBoards())) { diff --git a/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java b/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java index d929c231..7a7aab46 100644 --- a/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java @@ -619,6 +619,9 @@ public class GenerateServiceImpl extends ServiceImpl i } String modelName = generateDTO.getModelName(); + if (StringUtil.isNullOrEmpty(modelName)){ + return handleStandardGeneration(generateDTO); + } HashMap modelAndPromptMap = chooseModelAndPrompt(generateDTO, modelName); String useModel = modelAndPromptMap.get(ModelConstants.USE_MODEL); @@ -671,8 +674,162 @@ public class GenerateServiceImpl extends ServiceImpl i // processCreditDeduction(generateDTO.getUserId(), taskId, CreditsEventsEnum.WX_TEXT2IMG); return new PrepareForGenerateVO(Collections.singletonList(taskId), 200); } + public String toProductAsyncTask(String imagePath, String useModel, String prompt) { + if (StringUtil.isNullOrEmpty(imagePath)||StringUtil.isNullOrEmpty(useModel)||StringUtil.isNullOrEmpty(prompt)){ + throw new BusinessException("Parameter Exception"); + } + AuthPrincipalVo userHolder = UserContext.getUserHolder(); + Long userId = userHolder.getId(); - public String createGoogleAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt) { + String uuid = UUID.randomUUID().toString(); + // 生成唯一的任务ID + String taskId = uuid + "-" + userId; + String finalImagePath = null; + try { + finalImagePath = addWhiteBackground(imagePath); + //去掉"data:image/png;base64," + finalImagePath = finalImagePath.replace("data:image/png;base64,", ""); + // 如果白色背景处理失败或不需要,直接获取原图的base64编码 + if (StringUtil.isNullOrEmpty(finalImagePath)) { + finalImagePath = minioUtil.getImageAsBase64(imagePath); + } + } catch (IOException e) { + log.error("Error getting image as base64 taskId: {} ", taskId, e); + throw new BusinessException("Parameter Exception"); + } + + // 初始化Redis中的任务状态为"Executing" + String key = generateResultKey + ":" + taskId; + // 异步处理token获取和API调用 + String projectId = "aida-461108"; + String location = "global"; + String endpoint = String.format( + "https://aiplatform.googleapis.com/v1/projects/%s/locations/%s/publishers/google/models/%s:generateContent", + projectId, location, ModelConstants.NANO_BANANA + ); + + JSONObject requestBody = new JSONObject(); + // 使用 gemini-2.5-flash-image-preview 模型时的请求体格式 + // 创建图片部分 + JSONObject imagePart = new JSONObject(); + JSONObject inlineData = new JSONObject(); + inlineData.set("mimeType", "image/png"); + inlineData.set("data", finalImagePath); + imagePart.set("inlineData", inlineData); + + // 创建文本部分 + JSONObject textPart = new JSONObject(); + textPart.set("text", prompt); + + // 创建内容对象 + JSONObject content = new JSONObject(); + content.set("role", "user"); + content.set("parts", Arrays.asList(imagePart, textPart)); + + // 设置 contents 数组 + requestBody.set("contents", Arrays.asList(content)); + + // 设置 generationConfig + JSONObject generationConfig = new JSONObject(); +// generationConfig.set("temperature", 1); + generationConfig.set("maxOutputTokens", 8192); + generationConfig.set("responseModalities", Arrays.asList("TEXT", "IMAGE")); +// generationConfig.set("topP", 0.95); + JSONObject imageConfig = new JSONObject(); + imageConfig.set("aspectRatio", "9:16"); + generationConfig.set("imageConfig", imageConfig); + requestBody.set("generationConfig", generationConfig); + String jsonBody = requestBody.toString(); + log.info("Google 请求入参:{}", jsonBody); + + GenerateResultVO resultVO = new GenerateResultVO(taskId, null, null, "Pending"); + redisUtil.addToString(key, new Gson().toJson(resultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + CompletableFuture.runAsync(() -> { + try { + // 异步获取token + String tokenValue = null; + try (InputStream inputStream = GenerateServiceImpl.class.getClassLoader() + .getResourceAsStream("aida-461108-b4afaabebb84.json")) { + + GoogleCredentials credentials = GoogleCredentials + .fromStream(inputStream) + .createScoped(Collections.singletonList("https://www.googleapis.com/auth/cloud-platform")); + + credentials.refreshIfExpired(); + tokenValue = credentials.getAccessToken().getTokenValue(); + } + if (tokenValue == null) { + throw new RuntimeException("google token error"); + } + + // 异步发送API请求 + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) // 连接超时时间 + .readTimeout(60, TimeUnit.SECONDS) // 读取超时时间 + .writeTimeout(60, TimeUnit.SECONDS) // 写入超时时间 + .build(); + Request request = new Request.Builder() + .url(endpoint) + .addHeader("Authorization", "Bearer " + tokenValue) + .addHeader("Content-Type", "application/json") + .post(RequestBody.create(MediaType.parse("application/json"), jsonBody)) + .build(); + + try (Response response = client.newCall(request).execute()) { + String result = response.body().string(); + + log.info("Google 响应结果:{}", result); + com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result); + + String base64Data = null; + + //根据模型类别按照api取出结果 + if (ModelConstants.NANO_BANANA.equals(useModel)) { + JSONArray candidates = jsonResponse.getJSONArray("candidates"); + + if (candidates != null && !candidates.isEmpty()) { + com.alibaba.fastjson.JSONObject candidate = candidates.getJSONObject(0); + com.alibaba.fastjson.JSONObject contentResult = candidate.getJSONObject("content"); + JSONArray parts = contentResult.getJSONArray("parts"); + + // 遍历parts数组找到包含inlineData的对象 + for (int i = 0; i < parts.size(); i++) { + com.alibaba.fastjson.JSONObject part = parts.getJSONObject(i); + if (part.containsKey("inlineData")) { + com.alibaba.fastjson.JSONObject inlineDataResult= part.getJSONObject("inlineData"); + base64Data = inlineDataResult.getString("data"); + break; + } + } + } + } + + if (base64Data != null && !base64Data.isEmpty()) { + String resultPath = userId + "/product_image" + "/" + uuid; + String minioPath = minioUtil.base64UploadToPath("data:image/png;base64," + base64Data, userBucket, resultPath); + // 生成成功,更新Redis状态和URL + GenerateResultVO successResultVO = new GenerateResultVO(taskId, null, minioPath, "Success"); + redisUtil.addToString(key, new Gson().toJson(successResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + } else { + // 没有找到图像数据或数据为空,标记为失败 + log.warn("Google generation response does not contain valid image data for taskId: {}", taskId); + GenerateResultVO failResultVO = new GenerateResultVO(taskId, null, null, "Fail"); + redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + } + } + } catch (Exception e) { + log.error("Google generation failed for taskId: {}", taskId, e); + // 生成失败,更新Redis状态 + GenerateResultVO failResultVO = new GenerateResultVO(taskId, null, null, "Fail"); + redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + } + }, asyncTaskExecutor); + return taskId; + } + + + + public String createGoogleAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt) { // 从 resources 加载 JSON 文件 String level1Type = generateDTO.getLevel1Type(); String level2Type = generateDTO.getLevel2Type(); @@ -978,7 +1135,7 @@ public class GenerateServiceImpl extends ServiceImpl i && StringUtil.isNullOrEmpty(generateDTO.getLevel2Type())) { throw new BusinessException("level2Type.cannot.be.empty"); } - if (generateDTO.getLevel1Type().equals(PRINT_BOARD.getRealName())) { + if (generateDTO.getLevel1Type().equals(PRINT_BOARD.getRealName())&&generateDTO.getLevel2Type().equals(CreditsEventsEnum.PATTERN.getName())) { int firstCommaIndex = generateDTO.getText().indexOf(","); String style = generateDTO.getText().substring(0, firstCommaIndex).trim(); //如果style不等于painting style,illustration style,real style中的一种 @@ -1060,7 +1217,7 @@ public class GenerateServiceImpl extends ServiceImpl i throw new RuntimeException(e.getMessage()); } String taskId = result.getOutput().getTaskId(); - log.info("wx text2image 请求生成:{}, taskId:{}", JsonUtils.toJson(result), taskId); + log.info("qwen text2image 请求生成:{}, taskId:{}", JsonUtils.toJson(result), taskId); Generate generate = new Generate(userId, taskId, level1Type, level2Type, prompt, "text(" + gender + ")", "qwen-image", new Date()); save(generate); @@ -3486,59 +3643,85 @@ public class GenerateServiceImpl extends ServiceImpl i /** * 接入flux模型,用于imageToSketch(sketch extract) || relighting || to product image * - * @param func 功能枚举名 - * @param prompt 用户输入 - * @param imagePath 图片minio路径 + * @param func 功能枚举名,指定使用flux模型的具体功能类型 + * @param prompt 用户输入的提示词,如果为空则使用默认提示词 + * @param imagePath 图片minio路径,作为输入图像的base64编码源 + * @param childStyle 是否为儿童风格,影响提示词的构建 * @return 返回taskId,用于异步获取结果 */ public String flux(CreditsEventsEnum func, String prompt, String imagePath, boolean childStyle) { + // Flux API的请求地址 String fluxRequestUrl = "https://api.bfl.ai/v1/flux-kontext-pro"; + + // 如果用户没有提供提示词,根据功能类型设置默认提示词 if (StringUtil.isNullOrEmpty(prompt)) { switch (func) { case RELIGHT_FLUX: + // 重新打光功能的默认提示词 prompt = "a model standing on the beautiful beach, ultra high quality, 8k"; break; case IMAGE_TO_SKETCH_FLUX: + // 图片转线稿功能的默认提示词 prompt = "generate the sketch of the image, simple line, ultra high quality"; break; case TO_PRODUCT_IMAGE_ADVANCED: + // 转产品图功能的默认提示词 prompt = "change the image to real style, ultra high quality, 8k"; + // 如果是儿童风格,添加儿童面部特征描述 if (childStyle) prompt = prompt + ", Children's face"; break; } } else { + // 如果用户提供了提示词,先进行提示词优化处理 prompt = modifyPrompt(prompt, null, func.getName(), null); + // 根据不同功能类型,为提示词添加特定前缀 switch (func) { case PATTERN: + // 图案生成功能,添加图案前缀 prompt = "pattern image, " + prompt; break; case SKETCH_BOARD: + // 线稿板功能,添加线稿描述 prompt = "a single item of sketch of " + prompt + ", clean white background, simple lines"; break; } } + + // 构建Flux API请求体 JSONObject requestBody = new JSONObject(); + // 设置生成提示词 requestBody.set("prompt", prompt); + // 设置随机种子,确保结果的可重现性 requestBody.set("seed", 42); + // 根据功能类型设置图片宽高比 if (func.equals(PATTERN)) { + // 图案生成使用正方形比例 requestBody.set("aspect_ratio", "1:1"); } else { + // 其他功能使用竖屏比例 requestBody.set("aspect_ratio", "9:16"); } + // 设置输出格式为PNG requestBody.set("output_format", "png"); log.info("flux 请求入参:{}", requestBody); + // 提示词不能为空的校验 if (prompt.isEmpty()) throw new BusinessException("test"); + + // 如果提供了输入图片路径,需要将图片转换为base64格式 if (!StringUtil.isNullOrEmpty(imagePath)) { try { String imageAsBase64 = null; + // 对于转产品图功能,先添加白色背景处理 if (func.equals(TO_PRODUCT_IMAGE_ADVANCED)) { imageAsBase64 = addWhiteBackground(imagePath); } + // 如果白色背景处理失败或不需要,直接获取原图的base64编码 if (StringUtil.isNullOrEmpty(imageAsBase64)) { imageAsBase64 = minioUtil.getImageAsBase64(imagePath); } + // 将base64编码的图片添加到请求体中 requestBody.set("input_image", imageAsBase64); } catch (IOException e) { log.error("获取图片的base64格式失败,{}", String.valueOf(e)); @@ -3546,22 +3729,30 @@ public class GenerateServiceImpl extends ServiceImpl i } } + // 发送POST请求到Flux API String resp = sendRequestUtil.sendFluxPost(fluxRequestUrl, requestBody.toString()); JSONObject respObj = JSONUtil.parseObj(resp); log.info("flux 发起生成请求返回结果: {}", respObj); + + // 从响应中提取任务ID String taskId = respObj.getStr("id"); if (StringUtil.isNullOrEmpty(taskId)) { + // 任务创建失败,记录错误信息并抛出异常 requestBody.set("input_image", imagePath); log.error("flux生成任务创建失败,func :{}, requestBody:{}", func.getName(), requestBody); throw new BusinessException("Failed to generate task. Please retry later."); } + // 获取轮询URL,用于后续查询任务状态 String pollingUrl = respObj.getStr("polling_url"); String key = RedisUtil.FLUX_POLLING_URL + taskId; + // 将轮询URL存储到Redis中,设置过期时间 redisUtil.addToString(key, pollingUrl, CommonConstant.GENERATE_RESULT_EXPIRE_TIME); - // 添加到api_generate表中,以便之后对结果查询做补偿 + + // 添加到api_generate表中,以便之后对结果查询做补偿机制 apiGenerateService.addAPIGenerateRecordAsync(UserContext.getUserHolder().getId(), taskId, func.getName(), "flux", "Pending"); + // 返回任务ID,用于异步查询结果 return taskId; } 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 0e44dfd5..077803f6 100644 --- a/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java @@ -157,6 +157,8 @@ public class UserLikeGroupServiceImpl extends ServiceImpl uw = new UpdateWrapper<>(); - uw.eq("id",id); - uw.set("update_date",DateUtil.getByTimeZone(timeZone)); + uw.eq("id", id); + uw.set("update_date", DateUtil.getByTimeZone(timeZone)); - baseMapper.update(null,uw); + baseMapper.update(null, uw); } @Override public Long exportSave(MultipartFile file, Long projectId, String module, Long designItemDetailId) { AuthPrincipalVo userHolder = UserContext.getUserHolder(); - if (Objects.isNull(projectId) && !module.equals("designItemDetail")){ + if (Objects.isNull(projectId) && !module.equals("designItemDetail")) { log.warn("用户 {} 保存 {} 模块的画布时, projectId为空", userHolder.getId(), module); throw new BusinessException("project.id.cannot.be.empty", ResultEnum.PROMPT.getCode()); } QueryWrapper qw = new QueryWrapper<>(); List exportFiles = null; - if (Objects.nonNull(projectId)){ + if (Objects.nonNull(projectId)) { qw.lambda().eq(ExportFile::getProjectId, projectId); qw.lambda().eq(ExportFile::getModule, module); exportFiles = exportFileMapper.selectList(qw); - } else if (Objects.nonNull(designItemDetailId)){ + } else if (Objects.nonNull(designItemDetailId)) { DesignItemDetailCanvas designItemDetailCanvas = designItemDetailService.getDIDCByDesignItemDetailId(designItemDetailId); - if (Objects.nonNull(designItemDetailCanvas) && Objects.nonNull(designItemDetailCanvas.getExportFileId())){ + if (Objects.nonNull(designItemDetailCanvas) && Objects.nonNull(designItemDetailCanvas.getExportFileId())) { qw.lambda().eq(ExportFile::getId, designItemDetailCanvas.getExportFileId()); qw.lambda().eq(ExportFile::getModule, module); exportFiles = exportFileMapper.selectList(qw); @@ -388,36 +390,52 @@ public class UserLikeGroupServiceImpl extends ServiceImpl toProduct(ToProductImageDTO toProductImageDTO) { - // 判断用户当前积分是否够本次生成消耗 - boolean nanoBananaTask = !StringUtil.isNullOrEmpty(toProductImageDTO.getModelName()) - && toProductImageDTO.getModelName().equals(ModelConstants.ADVANCED)||toProductImageDTO.getModelName().equals(ModelConstants.HIGH); - CreditsEventsEnum creditsEventsEnum = nanoBananaTask ? CreditsEventsEnum.TO_PRODUCT_IMAGE_ADVANCED : CreditsEventsEnum.TO_PRODUCT_IMAGE; + // 判断是否使用(高级模型) + boolean advanced = !StringUtil.isNullOrEmpty(toProductImageDTO.getModelName()) + && toProductImageDTO.getModelName().equals(ModelConstants.ADVANCED); + + // 根据模型类型选择对应的积分消耗事件 + CreditsEventsEnum creditsEventsEnum = advanced ? CreditsEventsEnum.TO_PRODUCT_IMAGE_ADVANCED : CreditsEventsEnum.TO_PRODUCT_IMAGE; + + // 预扣除积分,检查用户积分是否足够本次生成消耗 Boolean preDeduction = creditsService.creditsPreDeduction(creditsEventsEnum, toProductImageDTO.getToProductImageVOList().size()); if (!preDeduction) { throw new BusinessException("remaining.credits.insufficient", ResultEnum.WARNING.getCode()); } + // 获取当前登录用户信息 AuthPrincipalVo userHolder = UserContext.getUserHolder(); + + // 获取项目ID并查找对应的用户喜欢组 Long projectId = toProductImageDTO.getProjectId(); UserLikeGroup userLikeGroup = getByProjectId(projectId); Long userLikeGroupId = null; + + // 创建产品图像记录对象,用于记录本次生成任务的基本信息 ToProductImageRecord toProductImageRecord = new ToProductImageRecord(); toProductImageRecord.setProjectId(projectId); if (Objects.nonNull(userLikeGroup)) { @@ -425,224 +443,242 @@ public class UserLikeGroupServiceImpl extends ServiceImpl 180) { throw new BusinessException("Please keep your input text under 200 words. Thanks!"); } } + // 设置记录创建时间并保存原始提示词 toProductImageRecord.setCreateTime(LocalDateTime.now()); if (!StringUtils.isEmpty(toProductImageDTO.getPrompt())) { toProductImageRecord.setPrompt(toProductImageDTO.getPrompt()); } + // 将产品图像记录插入数据库 toProductImageRecordMapper.insert(toProductImageRecord); + // 初始化结果列表 List result = new ArrayList<>(); + // 判断是否为儿童年龄组,用于后续生成不同的提示词 boolean childFlag = !StringUtil.isNullOrEmpty(toProductImageDTO.getAgeGroup()) && toProductImageDTO.getAgeGroup().equals("Child"); + // 循环计数器,用于生成唯一的任务ID int i = 0; // else { // s = "best quality, masterpiece. detailed, high-res, simple background, studio photography, extremely detailed, updo, detailed face, face, close-up, HDR, UHD, 8K realistic, Highly detailed, simple background, Studio lighting"; // } + // 遍历所有需要生成的产品图像元素 for (ToProductImageVO toProductImageVO : toProductImageDTO.getToProductImageVOList()) { String taskId; + // 处理设计服装类型的元素 if (toProductImageVO.getElementType().equals("DesignOutfit")) { + // 生成唯一的任务ID,包含UUID、序号和用户ID taskId = UUID.randomUUID() + "-" + i + "-" + userHolder.getId(); + // 根据元素ID查询设计Python服装信息 TDesignPythonOutfit tDesignPythonOutfit = designPythonOutfitMapper.selectById(toProductImageVO.getElementId()); + // 获取设计项目ID并查询相关的设计项目详情 Long designItemId = tDesignPythonOutfit.getDesignItemId(); QueryWrapper designItemDetailQueryWrapper = new QueryWrapper<>(); designItemDetailQueryWrapper.lambda().eq(DesignItemDetail::getDesignItemId, designItemId); - designItemDetailQueryWrapper.lambda().ne(DesignItemDetail::getType, "Body"); + designItemDetailQueryWrapper.lambda().ne(DesignItemDetail::getType, "Body"); // 排除身体部分 List designItemDetails = designItemDetailService.list(designItemDetailQueryWrapper); + // 将设计项目的类型拼接成字符串(如:Tops,Bottoms) String collect = designItemDetails.stream().map(DesignItemDetail::getType).collect(Collectors.joining(",")); + // 获取设计ID并查询设计信息 Long designId = tDesignPythonOutfit.getDesignId(); Design design = designMapper.selectById(designId); + // 默认产品类型为整体 String productType = "overall"; + // 根据设计的单品/整体属性决定产品类型和提示词构建方式 if (design.getSingleOverall().equals("single")) { + // 单品设计:直接使用服装类型 productType = "single"; sb.append(collect); - }else { + } else { + // 整体设计:根据服装类型和年龄组添加人物描述 if (collect.contains("Tops") && childFlag) { - sb.append("a handsome boy,"); - }else if (collect.contains("Tops") && !childFlag){ - sb.append("a handsome man,"); - }else if (childFlag) { - sb.append("a beautiful girl,"); - }else { - sb.append("a beautiful woman,"); + sb.append("a handsome boy,"); // 儿童上装 - 男孩 + } else if (collect.contains("Tops") && !childFlag) { + sb.append("a handsome man,"); // 成人上装 - 男性 + } else if (childFlag) { + sb.append("a beautiful girl,"); // 儿童其他 - 女孩 + } else { + sb.append("a beautiful woman,"); // 成人其他 - 女性 } // sb.append("wearing ").append(collect); } + // 根据是否有自定义提示词来完善最终的提示词 if (StringUtils.isEmpty(prompt)) { + // 无自定义提示词:使用默认的高质量服装细节描述 sb.append(",high quality clothing details,8K realistic,HDR"); - }else { + } else { + // 有自定义提示词:结合用户提示词和高质量描述 sb.append(",high quality clothing details,").append(prompt).append(",8K realistic,HDR"); } + // 创建产品图像结果对象 ToProductImageResultVO toProductImageResult = new ToProductImageResultVO(); - if (nanoBananaTask){ - if (childFlag){ - sb.append(", Children's face"); + // 根据是否使用flux模型选择不同的生成方式 + if (advanced) { + // 使用flux高级模型 + if (childFlag) { + sb.append(", Children's face"); // 儿童面部特征 } - // 使用Google nanobanana模型 - GenerateThroughImageTextDTO generateDTO = new GenerateThroughImageTextDTO(); - generateDTO.setUserId(userHolder.getId()); - generateDTO.setLevel1Type("Product"); - generateDTO.setLevel2Type("ToProduct"); - generateDTO.setGender("unisex"); - generateDTO.setCollectionElementId(tDesignPythonOutfit.getId()); - generateDTO.setDesignType("DesignOutfit"); - try { - //使用nano banana用这个提示词 - String nanoPrompt = "Change the input image to the real image. Full length portrait, match the clothing size, clothing style, " + - "patterns, and fabric texture from the reference image, replicate garment design details precisely, " + - "maintain original color scheme, high fidelity to reference attire, realistic lighting, detailed fabric rendering."; - taskId = generateService.createGoogleAsyncTask(generateDTO, ModelConstants.NANO_BANANA, nanoPrompt); - } catch (Exception e) { - log.error("Google nanobanana generation failed", e); - throw new BusinessException("Generation failed, please try again"); - } - toProductImageResult.setModelName("nanobanana"); + taskId = generateService.toProductAsyncTask(tDesignPythonOutfit.getDesignUrl(), ModelConstants.NANO_BANANA, advancedPrompt); + toProductImageResult.setModelName(toProductImageDTO.getModelName()); toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); } else { - // 走模型 - if (childFlag){ - sb.append(", (Children's face:1.3)"); + // 使用本地Python模型 + if (childFlag) { + sb.append(", (Children's face:1.3)"); // 儿童面部特征(权重1.3) } + // 调用Python服务生成产品图像 pythonService.toProductImage(tDesignPythonOutfit.getDesignUrl(), taskId, sb.toString(), toProductImageDTO.getImageStrength(), productType); -// toProductImageResult.setModelName("local"); +// toProductImageResult.setModelName("local"); // 注释掉的本地模型标记 } - toProductImageResult.setElementId(tDesignPythonOutfit.getId()); - toProductImageResult.setElementType("DesignOutfit"); - toProductImageResult.setCreateTime(LocalDateTime.now()); - toProductImageResult.setToProductImageRecordId(toProductImageRecord.getId()); -// toProductImageResult.setUrl(productImageUrl); - toProductImageResult.setIsLike(0); - toProductImageResult.setTaskId(taskId); - toProductImageResult.setProjectId(projectId); + // 设置产品图像结果的基本信息 + toProductImageResult.setElementId(tDesignPythonOutfit.getId()); // 关联的设计服装ID + toProductImageResult.setElementType("DesignOutfit"); // 元素类型:设计服装 + toProductImageResult.setCreateTime(LocalDateTime.now()); // 创建时间 + toProductImageResult.setToProductImageRecordId(toProductImageRecord.getId()); // 关联的记录ID +// toProductImageResult.setUrl(productImageUrl); // 生成的图像URL(暂时注释) + toProductImageResult.setIsLike(0); // 默认未点赞 + toProductImageResult.setTaskId(taskId); // 任务ID + toProductImageResult.setProjectId(projectId); // 项目ID if (userLikeGroupId != null) { - toProductImageResult.setUserLikeGroupId(userLikeGroupId); + toProductImageResult.setUserLikeGroupId(userLikeGroupId); // 用户喜欢组ID } - toProductImageResult.setImageStrength(toProductImageDTO.getImageStrength()); - toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); - toProductImageResult.setStatus("Pending"); + toProductImageResult.setImageStrength(toProductImageDTO.getImageStrength()); // 图像强度 + toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); // 结果类型 + toProductImageResult.setStatus("Pending"); // 状态:待处理 + // 将结果插入数据库 toProductImageResultMapper.insert(toProductImageResult); // toProductImageResult.setUrl(minioUtil.getPresignedUrl(toProductImageResult.getUrl(), 24 * 60)); - // 先判断是否需要默认like - if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && toProductImageDTO.getIsDefaultLike()){ - // 满足条件情况下默认添加到like + // 处理默认点赞逻辑 + if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && toProductImageDTO.getIsDefaultLike()) { + // 如果设置了默认点赞,则自动添加到用户喜欢列表 CollectionSort collectionSort = addToProductLike(toProductImageVO.getParentId(), toProductImageResult.getId(), toProductImageDTO.getProjectId()); - // 重新排序 + // 重新排序:根据用户指定的排序位置调整 Integer reSort = collectionSortService.rearrangeChildSort(toProductImageResult.getId(), CollectionType.TO_PRODUCT_IMAGE.getValue(), toProductImageVO.getParentId(), toProductImageVO.getUserLikeSortId()); - // 将生成结果的排序返回 + // 设置排序信息到结果对象中 toProductImageResult.setSort(Objects.isNull(reSort) ? Objects.isNull(collectionSort) ? null : collectionSort.getSort() : reSort); + toProductImageResult.setParentId(toProductImageVO.getParentId()); // 父级ID + toProductImageResult.setUserLikeSortId(Objects.isNull(collectionSort) ? null : collectionSort.getId()); // 排序记录ID + } else if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && Objects.nonNull(toProductImageVO.getParentId())) { + // 不默认点赞但有父级ID的情况 toProductImageResult.setParentId(toProductImageVO.getParentId()); - toProductImageResult.setUserLikeSortId(Objects.isNull(collectionSort) ? null : collectionSort.getId()); - }else if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && Objects.nonNull(toProductImageVO.getParentId())){ - toProductImageResult.setParentId(toProductImageVO.getParentId()); - // 默认不添加到like,但是需要有parentId,所以这里添加到collectionSort表中 + // 注释:原本计划添加到collectionSort表中,但当前未实现 // designService.addCollectionSort(toProductImageResult.getId(), CollectionType.TO_PRODUCT_IMAGE.getValue(), toProductImageDTO.getProjectId(), toProductImageVO.getParentId()); } + // 将处理完的结果添加到返回列表中 result.add(toProductImageResult); - }else { + } else { + // 处理ProductElement类型的元素 + // 根据是否有自定义提示词来构建最终提示词 if (StringUtils.isEmpty(prompt)) { sb.append(",high quality clothing details,8K realistic,HDR"); - }else { + } else { sb.append(",high quality clothing details,").append(prompt).append(",8K realistic,HDR"); } + // 生成唯一的任务ID taskId = UUID.randomUUID() + "-" + i + "-" + userHolder.getId(); + // 查询产品元素信息 ToProductElement toProductElement = toProductElementMapper.selectById(toProductImageVO.getElementId()); + // 创建产品图像结果对象 ToProductImageResultVO toProductImageResult = new ToProductImageResultVO(); - if (nanoBananaTask){ - // 使用Google nanobanana模型 - GenerateThroughImageTextDTO generateDTO = new GenerateThroughImageTextDTO(); - generateDTO.setUserId(userHolder.getId()); - generateDTO.setLevel1Type("Product"); - generateDTO.setLevel2Type("ToProduct"); - generateDTO.setGender("unisex"); - generateDTO.setCollectionElementId(toProductElement.getId()); - generateDTO.setDesignType("ProductElement"); - try { - //使用nano banana用这个提示词 - String nanoPrompt = "Change the input image to the real image. Full length portrait, match the clothing size, clothing style, " + - "patterns, and fabric texture from the reference image, replicate garment design details precisely, " + - "maintain original color scheme, high fidelity to reference attire, realistic lighting, detailed fabric rendering."; - taskId = generateService.createGoogleAsyncTask(generateDTO, ModelConstants.NANO_BANANA, nanoPrompt); - } catch (Exception e) { - log.error("Google nanobanana generation failed", e); - throw new BusinessException("Generation failed, please try again"); - } - toProductImageResult.setModelName("nanobanana"); - toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); + // 根据是否使用高级模型选择不同的图像生成方式 + if (advanced) { + // 使用模型生成图像 + taskId = generateService.toProductAsyncTask(toProductElement.getUrl(), ModelConstants.NANO_BANANA, advancedPrompt); + toProductImageResult.setModelName(toProductImageDTO.getModelName()); // 设置模型名称 + toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); // 设置结果类型 } else { - // 走模型 - if (childFlag){ + // 使用本地Python模型生成图像 + if (childFlag) { + // 如果是儿童年龄组,添加儿童面部特征提示 sb.append(", (Children's face:1.3)"); } - // 走模型 + // 调用Python服务生成产品图像 pythonService.toProductImage(toProductElement.getUrl(), taskId, sb.toString(), toProductImageDTO.getImageStrength(), "overall"); -// toProductImageResult.setModelName("local"); +// toProductImageResult.setModelName("local"); // 本地模型名称(已注释) } - toProductImageResult.setElementId(toProductElement.getId()); - toProductImageResult.setElementType("ProductElement"); - toProductImageResult.setCreateTime(LocalDateTime.now()); - toProductImageResult.setToProductImageRecordId(toProductImageRecord.getId()); -// toProductImageResult.setUrl(productImageUrl); - toProductImageResult.setIsLike(0); - toProductImageResult.setTaskId(taskId); - toProductImageResult.setProjectId(projectId); + // 设置产品图像结果的基本信息 + toProductImageResult.setElementId(toProductElement.getId()); // 关联的产品元素ID + toProductImageResult.setElementType("ProductElement"); // 元素类型:产品元素 + toProductImageResult.setCreateTime(LocalDateTime.now()); // 创建时间 + toProductImageResult.setToProductImageRecordId(toProductImageRecord.getId()); // 关联的记录ID +// toProductImageResult.setUrl(productImageUrl); // 生成的图像URL(暂时注释) + toProductImageResult.setIsLike(0); // 默认未点赞 + toProductImageResult.setTaskId(taskId); // 任务ID + toProductImageResult.setProjectId(projectId); // 项目ID if (userLikeGroupId != null) { - toProductImageResult.setUserLikeGroupId(userLikeGroupId); + toProductImageResult.setUserLikeGroupId(userLikeGroupId); // 用户喜欢组ID } - toProductImageResult.setImageStrength(toProductImageDTO.getImageStrength()); - toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); - toProductImageResult.setStatus("Pending"); + toProductImageResult.setImageStrength(toProductImageDTO.getImageStrength()); // 图像强度 + toProductImageResult.setResultType(CollectionType.TO_PRODUCT_IMAGE.getValue()); // 结果类型 + toProductImageResult.setStatus("Pending"); // 状态:待处理 + // 将结果插入数据库 toProductImageResultMapper.insert(toProductImageResult); // toProductImageResult.setUrl(minioUtil.getPresignedUrl(toProductImageResult.getUrl(), 24 * 60)); - // 先判断是否需要默认like - if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && toProductImageDTO.getIsDefaultLike()){ - // 满足条件情况下默认添加到like + // 处理默认点赞逻辑 + if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && toProductImageDTO.getIsDefaultLike()) { + // 如果设置了默认点赞,则自动添加到用户喜欢列表 CollectionSort collectionSort = addToProductLike(toProductImageVO.getParentId(), toProductImageResult.getId(), toProductImageDTO.getProjectId()); - // 重新排序 + // 重新排序:根据用户指定的排序位置调整 Integer reSort = collectionSortService.rearrangeChildSort(toProductImageResult.getId(), CollectionType.TO_PRODUCT_IMAGE.getValue(), toProductImageVO.getParentId(), toProductImageVO.getUserLikeSortId()); - // 将生成结果的排序返回 + // 设置排序信息到结果对象中 toProductImageResult.setSort(Objects.isNull(reSort) ? Objects.isNull(collectionSort) ? null : collectionSort.getSort() : reSort); + toProductImageResult.setParentId(toProductImageVO.getParentId()); // 父级ID + toProductImageResult.setUserLikeSortId(Objects.isNull(collectionSort) ? null : collectionSort.getId()); // 排序记录ID + } else if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && Objects.nonNull(toProductImageVO.getParentId())) { + // 不默认点赞但有父级ID的情况 toProductImageResult.setParentId(toProductImageVO.getParentId()); - toProductImageResult.setUserLikeSortId(Objects.isNull(collectionSort) ? null : collectionSort.getId()); - }else if (Objects.nonNull(toProductImageDTO.getIsDefaultLike()) && Objects.nonNull(toProductImageVO.getParentId())){ - toProductImageResult.setParentId(toProductImageVO.getParentId()); - // 默认不添加到like,但是需要有parentId,所以这里添加到collectionSort表中 + // 注释:原本计划添加到collectionSort表中,但当前未实现 // designService.addCollectionSort(toProductImageResult.getId(), CollectionType.TO_PRODUCT_IMAGE.getValue(), toProductImageDTO.getProjectId(), toProductImageVO.getParentId()); } + // 将处理完的结果添加到返回列表中 result.add(toProductImageResult); } - i ++; - sb = new StringBuilder("The best quality, masterpiece, real image."); + i++; // 循环计数器递增 + sb = new StringBuilder("The best quality, masterpiece, real image."); // 重置提示词构建器 // 添加需要扣除的积分到预扣除区 creditsService.addRecordToCreditsDeduction(userHolder.getId(), taskId, creditsEventsEnum); - // 添加积分扣除记录到db + // 添加积分扣除记录到数据库 creditsService.preInsert(userHolder.getId(), creditsEventsEnum.getName(), taskId, Boolean.TRUE, null); } - // 更新项目更新时间 + // 更新项目更新时间,记录最后一次操作时间 projectService.modifyProjectUpdateTime(toProductImageDTO.getProjectId()); + // 返回生成的产品图像结果列表 return result; } - private CollectionSort addToProductLike(Long parentId, Long toProductImageResultId, Long projectId){ - if (Objects.nonNull(parentId) && !parentId.equals(0L)){ + private CollectionSort addToProductLike(Long parentId, Long toProductImageResultId, Long projectId) { + if (Objects.nonNull(parentId) && !parentId.equals(0L)) { return productImageLike(new ProductImageLikeDTO(Collections.singletonList(toProductImageResultId), projectId, parentId)); } @@ -679,25 +715,25 @@ public class UserLikeGroupServiceImpl extends ServiceImpl getToProductImageResultList(List taskIdList) { + // 初始化结果列表和状态收集集合 List results = new ArrayList<>(); Set collect = new HashSet<>(); + + // 遍历每个任务ID,处理对应的产品图像生成结果 taskIdList.forEach(taskId -> { - // 查记录 + // 根据任务ID查询产品图像生成结果记录 QueryWrapper qw = new QueryWrapper<>(); qw.lambda().eq(ToProductImageResult::getTaskId, taskId); ToProductImageResult toProductImageResult = toProductImageResultMapper.selectOne(qw); if (Objects.isNull(toProductImageResult)) { throw new BusinessException("source.image.does.not.exist"); } + + // 查询产品图像记录,获取提示词等信息 ToProductImageRecord toProductImageRecord = toProductImageRecordMapper.selectById(toProductImageResult.getToProductImageRecordId()); if (Objects.isNull(toProductImageRecord)) { throw new BusinessException("This task does not exist."); } - // 判断当任务从哪个模型获取结果 - if (!StringUtil.isNullOrEmpty(toProductImageResult.getModelName()) && toProductImageResult.getModelName().equals("flux")){ + + if (!StringUtil.isNullOrEmpty(toProductImageResult.getModelName()) && toProductImageResult.getModelName().equals(ModelConstants.ADVANCED)) { + // 获取项目信息,用于构建文件路径和积分扣除 Project project = projectService.getById(toProductImageResult.getProjectId()); - if (Objects.isNull(project)){ + if (Objects.isNull(project)) { throw new BusinessException("unknown project"); } - String fluxResult; - if (toProductImageResult.getStatus().equals("Success") && !StringUtil.isNullOrEmpty(toProductImageResult.getUrl())){ - fluxResult = toProductImageResult.getUrl(); - }else { - String objectName = project.getAccountId() + "/product_image/" + taskId + ".png"; - fluxResult = generateService.getFluxResult(taskId, objectName); + + // 获取flux模型生成结果 + String redisResult; + if (toProductImageResult.getStatus().equals("Success") && !StringUtil.isNullOrEmpty(toProductImageResult.getUrl())) { + // 如果已经有成功的结果URL,直接使用 + redisResult = toProductImageResult.getUrl(); + } else { + String key = generateResultKey + ":" + taskId; + redisResult = redisUtil.getFromString(key); } - if (StringUtil.isNullOrEmpty(fluxResult)){ + GenerateResultVO cachedResult = new Gson().fromJson(redisResult, GenerateResultVO.class); + + + // 根据flux结果状态进行不同处理 + if (StringUtil.isNullOrEmpty(redisResult)) { + // 如果结果为空,标记为失败状态 toProductImageResult.setStatus("Fail"); toProductImageResultMapper.updateById(toProductImageResult); + collectionSortMapper.delete(new QueryWrapper().lambda().eq(CollectionSort::getRelationId, toProductImageResult.getId())); results.add(new MagicToolResultVO(taskId, "Fail")); - } else if (fluxResult.equals("Fail") || fluxResult.equals("Pending")) { - toProductImageResult.setStatus(fluxResult); + } else if ("Pending".equals(cachedResult.getStatus())||"Fail".equals(cachedResult.getStatus())) { + // 如果结果为失败或待处理状态,更新状态并返回对应结果 + toProductImageResult.setStatus(cachedResult.getStatus()); toProductImageResultMapper.updateById(toProductImageResult); - results.add(new MagicToolResultVO(taskId, fluxResult)); + if (cachedResult.getStatus().equals("Fail")){ + collectionSortMapper.delete(new QueryWrapper().lambda().eq(CollectionSort::getRelationId, toProductImageResult.getId())); + } + results.add(new MagicToolResultVO(taskId, cachedResult.getStatus())); } else { - results.add(processFluxResult(fluxResult, toProductImageResult, taskId, toProductImageRecord.getPrompt())); - // 扣积分 + // 如果结果成功,处理flux结果并构建返回对象 + results.add(processNanoBananaResult(cachedResult.getUrl(), toProductImageResult, taskId, toProductImageRecord.getPrompt())); + // 执行积分扣除操作 Boolean flag = creditsService.taskCreditsDeduction(project.getAccountId(), taskId); if (flag) creditsService.updateChangedCredits(String.valueOf(project.getAccountId()), taskId); } - // 将积分暂扣区的积分移除 - if (toProductImageResult.getStatus().equals("Fail")){ + + // 如果任务失败,将积分预扣除记录移除 + if (toProductImageResult.getStatus().equals("Fail")) { creditsService.deleteCreditsDeduction(project.getAccountId(), taskId); } - // 在这个stream中不再继续往后执行 + + // flux模型处理完成,跳过后续的Redis缓存处理逻辑 return; } + // 非flux模型的处理逻辑:从Redis缓存获取结果 String key = toProductImageResultKey + ":" + taskId; MagicToolResultVO magicToolResultVO = new Gson().fromJson(redisUtil.getFromString(key), MagicToolResultVO.class); + + // 如果从Redis获取到结果且URL不为空,则构建返回对象 if (!Objects.isNull(magicToolResultVO) && !StringUtil.isNullOrEmpty(magicToolResultVO.getUrl())) { String url = magicToolResultVO.getUrl(); + // 检查是否为无效图片(白色图片表示生成失败) if (url.substring(url.lastIndexOf("/") + 1).equals("white_image.jpg")) { magicToolResultVO.setStatus("Invalid"); } else { + // 设置预签名URL和相关属性 magicToolResultVO.setUrl(minioUtil.getPreSignedUrl(url, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); magicToolResultVO.setResultType(toProductImageResult.getResultType()); magicToolResultVO.setElementId(toProductImageResult.getElementId()); @@ -830,16 +903,22 @@ public class UserLikeGroupServiceImpl extends ServiceImpl userLikeQueryWrapper = new QueryWrapper<>(); userLikeQueryWrapper.lambda().eq(UserLike::getDesignOutfitId, tDesignPythonOutfit.getId()); List userLikeList = userLikeMapper.selectList(userLikeQueryWrapper); @@ -850,43 +929,62 @@ public class UserLikeGroupServiceImpl extends ServiceImpl userLikeQueryWrapper = new QueryWrapper<>(); userLikeQueryWrapper.lambda().eq(UserLike::getDesignOutfitId, tDesignPythonOutfit.getId()); List userLikeList = userLikeMapper.selectList(userLikeQueryWrapper); @@ -895,10 +993,80 @@ public class UserLikeGroupServiceImpl extends ServiceImpl userLikeQueryWrapper = new QueryWrapper<>(); + userLikeQueryWrapper.lambda().eq(UserLike::getDesignOutfitId, tDesignPythonOutfit.getId()); + List userLikeList = userLikeMapper.selectList(userLikeQueryWrapper); + if (!CollectionUtils.isEmpty(userLikeList)) { + UserLike userLike = userLikeList.get(0); + Long parentId = collectionSortService.getParentIdByElementIdAndElementType(userLike.getId(), toProductImageResult.getElementType()); + magicToolResultVO.setParentId(parentId); + } + } else if (toProductImageResult.getElementType().equals("ToProductImage")) { + // 处理转产品图像类型:获取转产品图像信息并设置源图片URL + ToProductImageResult toProductImage = toProductImageResultMapper.selectById(toProductImageResult.getElementId()); + magicToolResultVO.setSourceUrl(minioUtil.getPreSignedUrl(toProductImage.getUrl(), 24 * 60)); + + // 直接通过元素ID和类型获取父ID Long parentId = collectionSortService.getParentIdByElementIdAndElementType(toProductImageResult.getElementId(), toProductImageResult.getElementType()); magicToolResultVO.setParentId(parentId); } @@ -911,9 +1079,9 @@ public class UserLikeGroupServiceImpl extends ServiceImpl qw = new QueryWrapper<>(); - if (Objects.nonNull(exportSearchDTO.getProjectId())){ + if (Objects.nonNull(exportSearchDTO.getProjectId())) { qw.lambda().eq(ExportFile::getProjectId, exportSearchDTO.getProjectId()); - } else if (Objects.nonNull(exportSearchDTO.getId())){ + } else if (Objects.nonNull(exportSearchDTO.getId())) { qw.lambda().eq(ExportFile::getId, exportSearchDTO.getId()); } qw.lambda().eq(ExportFile::getModule, exportSearchDTO.getModule()); @@ -932,7 +1100,8 @@ public class UserLikeGroupServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("account_id", authPrincipalVo.getId()); - if (Objects.nonNull(query.getId())){ + if (Objects.nonNull(query.getId())) { queryWrapper.eq("id", query.getId()); } // queryWrapper.isNull("parent_id"); @@ -1775,15 +1943,15 @@ public class UserLikeGroupServiceImpl extends ServiceImpl(); } - }else { + } 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 { + } else { projectIdList.retainAll(historyIdListByClassificationId); } if (CollectionUtil.isEmpty(projectIdList)) { @@ -1795,7 +1963,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl page = projectService.page( @@ -1842,7 +2010,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl CollectionLevel1TypeEnum.COLOR_BOARD.getRealName().equals(element.getLevel1Type())) .collect(Collectors.toList()); moduleChooseVO.setColorBoard(collectionService.resolveColorBoard(collectionElements)); - }else if (module.equals(Module.moodBoard.name())) { + } else if (module.equals(Module.moodBoard.name())) { MoodBoardModuleChooseVO moodBoardModuleChooseVO = new MoodBoardModuleChooseVO(); List collectionElements = allCollectionElements.stream() @@ -1920,7 +2088,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl collectionElements = allCollectionElements.stream() .filter(element -> CollectionLevel1TypeEnum.PRINT_BOARD.getRealName().equals(element.getLevel1Type())) @@ -1941,7 +2109,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl collectionElements = allCollectionElements.stream() .filter(element -> CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName().equals(element.getLevel1Type())) @@ -1974,7 +2142,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl userLikeSortQueryWrapper = new QueryWrapper<>(); userLikeSortQueryWrapper.lambda().eq(CollectionSort::getProjectId, projectDTO.getId()); @@ -2128,7 +2296,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl likedList = generateService.getPoseTransformationResult(null, projectDTO.getId(), true); List list = generateService.getPoseTransformationResult(null, projectDTO.getId(), false); PoseTransferVO vo = new PoseTransferVO(); vo.setLikedList(likedList); vo.setList(list); moduleChooseVO.setPoseTransfer(vo); - }else if (module.equals(Module.patternMaking3D.name())) { + } else if (module.equals(Module.patternMaking3D.name())) { QueryWrapper qw = new QueryWrapper<>(); qw.lambda().eq(ThreeDModule::getProjectId, projectDTO.getId()); List threeDModules = threeDModuleMapper.selectList(qw); if (CollectionUtil.isNotEmpty(threeDModules)) { ThreeDModule threeDModule = threeDModules.get(0); - if (null != threeDModule.getThreeDSimpleId()){ + if (null != threeDModule.getThreeDSimpleId()) { ThreeDModuleVO threeDModuleVO = CopyUtil.copyObject(threeDModule, ThreeDModuleVO.class); if (null != threeDModule.getCollectionElementId()) { CollectionElement collectionElement = collectionElementMapper.selectById(threeDModule.getCollectionElementId()); @@ -2227,7 +2395,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl collectionElements = allCollectionElements.stream() .filter(element -> CollectionLevel1TypeEnum.MODEL.getRealName().equals(element.getLevel1Type())) .collect(Collectors.toList()); @@ -2244,7 +2412,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl qw = new QueryWrapper<>(); qw.lambda().eq(ToProductElement::getProjectId, projectDTO.getId()); List toProductElements = toProductElementMapper.selectList(qw); @@ -2257,15 +2425,15 @@ public class UserLikeGroupServiceImpl extends ServiceImpl toBeDeletedElementIdList = toBeDeletedCollectionElementIds.stream() .map(relationIdToModelMap::get) // 获取对应的Model .filter(Objects::nonNull) // 过滤掉可能为null的情况 @@ -2677,9 +2845,9 @@ public class UserLikeGroupServiceImpl extends ServiceImpl threeDLayoutList = threeDLayoutMapper.selectList(qw); for (ThreeDLayout threeDLayout : threeDLayoutList) { - threeDLayout.setUrl(minioUtil.getPreSignedUrl(threeDLayout.getUrl(), 24* 60)); + threeDLayout.setUrl(minioUtil.getPreSignedUrl(threeDLayout.getUrl(), 24 * 60)); } result.setThreeDLayoutList(threeDLayoutList); @@ -3132,7 +3300,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl qw = new QueryWrapper<>(); qw.lambda().eq(WorkspaceRelStyle::getWorkspaceId, workspace.getId()); List workspaceRelStyles = workspaceRelStyleMapper.selectList(qw); @@ -349,7 +349,7 @@ public class WorkspaceServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper().eq(CollectionElement::getProjectId, projectId) - .eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.MODEL.getRealName()) - .eq(CollectionElement::getLevel3Type, workspaceNew.getSex()); - if (collectionElementMapper.selectCount(queryWrapper) == 0){ - SysFile sysFile = sysFileService.getOneBySex(projectDTO.getStyleId(), projectDTO.getWorkspace().getSex(), projectDTO.getWorkspace().getAgeGroup()); + SysFile sysFile = sysFileService.getOneBySex(projectDTO.getStyleId(), projectDTO.getWorkspace().getSex(), projectDTO.getWorkspace().getAgeGroup()); + if (!checkIfModelExistsInProject(sysFile.getMd5(), projectId)) { CollectionElement collectionElement = new CollectionElement(); collectionElement.setAccountId(userInfo.getId()); collectionElement.setProjectId(projectId); @@ -768,14 +764,14 @@ public class WorkspaceServiceImpl extends ServiceImpl wRSQW = new QueryWrapper<>(); wRSQW.lambda().eq(WorkspaceRelStyle::getWorkspaceId, projectDTO.getWorkspace().getId()); List workspaceRelStyles = workspaceRelStyleMapper.selectList(wRSQW); @@ -789,7 +785,7 @@ public class WorkspaceServiceImpl extends ServiceImpl qw = new QueryWrapper<>(); + qw.lambda().eq(CollectionElement::getProjectId, projectId) + .eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.MODEL.getRealName()) + .eq(CollectionElement::getMd5, md5); + + List collectionElements = collectionElementMapper.selectList(qw); + return collectionElements != null && !collectionElements.isEmpty(); + } + public static List getPNGFiles(String directoryPath) { List pngFiles = new ArrayList<>(); File directory = new File(directoryPath);