diff --git a/src/main/java/com/ai/da/controller/AccountController.java b/src/main/java/com/ai/da/controller/AccountController.java index 12de1981..a16337ce 100644 --- a/src/main/java/com/ai/da/controller/AccountController.java +++ b/src/main/java/com/ai/da/controller/AccountController.java @@ -323,6 +323,12 @@ public class AccountController { return Response.success(accountService.bindWeChat(code)); } + @GetMapping("/bindEmail") + @ApiOperation(value = "绑定邮箱") + public Response bindEmail(@RequestParam("email") String email) { + return Response.success(accountService.bindEmail(email)); + } + @GetMapping("/unbindWeChat") @ApiOperation(value = "解除绑定微信") public Response unbindWeChat() { diff --git a/src/main/java/com/ai/da/mapper/primary/DesignBatchMapper.java b/src/main/java/com/ai/da/mapper/primary/DesignBatchMapper.java new file mode 100644 index 00000000..1c8f2b65 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/DesignBatchMapper.java @@ -0,0 +1,16 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.AccountExtend; +import com.ai.da.mapper.primary.entity.DesignBatch; + +/** + * Mapper 接口 + * + * @author easy-generator + * @since 2022-06-13 + */ +public interface DesignBatchMapper extends CommonMapper { + + +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/DesignBatch.java b/src/main/java/com/ai/da/mapper/primary/entity/DesignBatch.java new file mode 100644 index 00000000..3ad4dbb5 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/DesignBatch.java @@ -0,0 +1,44 @@ +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 io.swagger.models.auth.In; +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("design_batch") +public class DesignBatch implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long accountId; // account_id + + private Long designId; // design_id + + private Long collectionId; // collection_id + + private Integer status; // status + + private LocalDateTime createTime; // create_time + + private LocalDateTime updateTime; // update_time + + private String taskId; // task_id + + private Integer totalNum; // total_num + + private Integer completedNum; // completed_num +} diff --git a/src/main/java/com/ai/da/model/dto/AccountDesignWorksRegisterDTO.java b/src/main/java/com/ai/da/model/dto/AccountDesignWorksRegisterDTO.java index db2dac3b..27320588 100644 --- a/src/main/java/com/ai/da/model/dto/AccountDesignWorksRegisterDTO.java +++ b/src/main/java/com/ai/da/model/dto/AccountDesignWorksRegisterDTO.java @@ -6,4 +6,6 @@ import lombok.Data; @Data public class AccountDesignWorksRegisterDTO extends Account { private String emailVerifyCode; + +// private String invitationCode; } diff --git a/src/main/java/com/ai/da/python/PythonService.java b/src/main/java/com/ai/da/python/PythonService.java index 5cb17cee..f7f47631 100644 --- a/src/main/java/com/ai/da/python/PythonService.java +++ b/src/main/java/com/ai/da/python/PythonService.java @@ -41,6 +41,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; @@ -237,6 +238,9 @@ public class PythonService { int[] sketchNumbers = new int[3]; int designNum = elementVO.getDesignNum(); + Set assembledObjects = new HashSet<>(); // 用于存储已组装的 DesignPythonObject + DesignPythonObject lastAssembledObject = null; // 上一次组装的对象 + for (int i = 0; i < designNum; i++) { CurrentDesignPictureTypeEnum designPictureType = calculateCurrentDesignPictureTypeNew(elementVO, sketchNumbers, systemScale); if (designPictureType == null) break; @@ -256,13 +260,28 @@ public class PythonService { noPrintNum--; break; } -// updatePrintNumbers(designPrintPictureType, pinPrintNum, noPinPrintNum, noPrintNum); DesignPythonItemPrint designPythonItemPrint = getRandomPrint(elementVO, designPrintPictureType); elementVO.setDesignPythonItemPrint(designPythonItemPrint); elementVO.setDesignPrintPictureTypeLayoutList(calculateCurrentDesignPintPictureTypeLayout(elementVO.getModelSex())); DesignPythonObject pythonObject = createDesignPythonObject(elementVO, designPictureType, systemScale, singleOverall, switchCategory, i); + + // 如果当前对象与已组装的对象重复,则跳过当前组装 + if (assembledObjects.contains(pythonObject)) { + if (lastAssembledObject != null && assembledObjects.contains(lastAssembledObject)) { + // 如果当前组装与前一个组装的对象重复,且前一个组装也重复,结束组装 + System.out.println("当前组装的对象与前两个组装的对象重复,结束组装。"); + break; + } + // 否则,跳过当前组装 + continue; + } + + // 将当前对象添加到已组装的集合中,并记录 + assembledObjects.add(pythonObject); + lastAssembledObject = pythonObject; // 更新上一次组装的对象 + objects.add(pythonObject); redisUtil.addProcessId(processId, i + 1); } @@ -3672,29 +3691,44 @@ public class PythonService { throw new BusinessException("Atribute recognition exception!"); } - public JSONObject designBatch(DesignPythonObjects designPythonObjects) { + public String designBatch(DesignPythonObjects designPythonObjects, Long accountId, int designNum, String taskId) { // todo 限流校验 -// AccessLimitUtils.validate("design",5); + // AccessLimitUtils.validate("design",5); + + // 将 designPythonObjects 写入文件 + File file = new File("design_batch_test.txt"); + try (FileWriter writer = new FileWriter(file)) { + String param = JSON.toJSONString(designPythonObjects, SerializerFeature.DisableCircularReferenceDetect); + writer.write(param); + log.info("设计请求参数已写入文件:####{}", file.getAbsolutePath()); + } catch (IOException e) { + log.error("写入文件异常:{}", e.getMessage()); + throw new BusinessException("file.write.exception"); + } + OkHttpClient client = new OkHttpClient().newBuilder() .connectTimeout(30, TimeUnit.SECONDS) - .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒) - .readTimeout(60, TimeUnit.SECONDS)//读取超时(单位:秒) - .writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒) + .pingInterval(5, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) .build(); - MediaType mediaType = MediaType.parse("application/json"); - //关闭FastJson的引用检测 防止出现$ref 现象 - String param = JSON.toJSONString(designPythonObjects, SerializerFeature.DisableCircularReferenceDetect); - log.info("design请求python 参数:####{}", param); - RequestBody body = RequestBody.create(mediaType, param); - Request request = new Request.Builder() - .url(accessPythonIp + ":" + accessPythonPort + "/api/design_batch_generate") -// .url(fastApiPythonAddress + "/api/design") -// .url(accessPythonIp + ":10200/aifda/api/v1.0/generate") - .method("POST", body) - .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==") - .addHeader("Content-Type", "application/json") + // 构建 multipart 表单 + RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) + .addFormDataPart("file", "design_batch_test.txt", + RequestBody.create(MediaType.parse("text/plain"), file)) + .addFormDataPart("tasks_id", taskId) + .addFormDataPart("user_id", String.valueOf(accountId)) + .addFormDataPart("file_name", "design_batch_test" + taskId + ".json") + .addFormDataPart("total", String.valueOf(designNum)) .build(); + + Request request = new Request.Builder() + .url("http://18.167.251.121:9994/api/design_batch_generate") + .method("POST", body) + .addHeader("Content-Type", "multipart/form-data") + .build(); + Response response; String responseBody; try { @@ -3705,15 +3739,13 @@ public class PythonService { throw new BusinessException("design.interface.exception"); } - //去除限流 -// AccessLimitUtils.validateOut("design"); if (response.isSuccessful()) { try { if (Objects.nonNull(response.body())) { responseBody = response.body().string(); JSONObject responseObject = JSON.parseObject(responseBody); log.info("PythonService##responseObject###{}", responseObject); - return responseObject; + return taskId; } throw new BusinessException("design.interface.exception"); } catch (IOException | JSONException e) { @@ -3722,7 +3754,7 @@ public class PythonService { } } log.error("PythonService##design异常response###{}", response); - //生成失败 throw new BusinessException("design.interface.exception"); } + } diff --git a/src/main/java/com/ai/da/service/AccountService.java b/src/main/java/com/ai/da/service/AccountService.java index a792bd74..6ecb4f0a 100644 --- a/src/main/java/com/ai/da/service/AccountService.java +++ b/src/main/java/com/ai/da/service/AccountService.java @@ -48,6 +48,7 @@ public interface AccountService extends IService { * @return */ Boolean bindEmail(AccountBindEmailDTO accountBindEmailDTO); + Boolean bindEmail(String email); /** * 忘记密码 diff --git a/src/main/java/com/ai/da/service/DesignService.java b/src/main/java/com/ai/da/service/DesignService.java index d362d27b..80d13f47 100644 --- a/src/main/java/com/ai/da/service/DesignService.java +++ b/src/main/java/com/ai/da/service/DesignService.java @@ -12,6 +12,8 @@ import com.baomidou.mybatisplus.extension.service.IService; import java.math.BigDecimal; import java.util.List; +import java.util.Map; +import java.util.Objects; /** * 服务类 @@ -106,4 +108,6 @@ public interface DesignService extends IService { DesignCollectionVO getDesignResult(String requestId, List objectSignList); String designCloud(DesignCollectionDTO designDTO); + + void processDesignBatch(Map designBatchResult); } diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index ca71c47d..211fe4a8 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -1217,6 +1217,7 @@ public class AccountServiceImpl extends ServiceImpl impl account.setValidStartTime(Instant.now().toEpochMilli()); account.setCreateDate(new Date()); account.setCredits(BigDecimal.valueOf(0)); + account.setInvitationCode(accountDesignWorksRegisterDTO.getInvitationCode()); accountMapper.insert(account); AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); response.setEmail(account.getUserEmail()); @@ -2424,19 +2425,6 @@ public class AccountServiceImpl extends ServiceImpl impl response.setAccountExtendList(accountExtends); } response.setLanguage(Language.valueOf(account.getLanguage()).name()); - SubscriptionInfo subscriptionInfo = stripeService.getLatestSubscriptionInfoByAccountId(accountId); - if (!Objects.isNull(subscriptionInfo)) { - response.setSubscriptionId(subscriptionInfo.getSubscriptionId()); - response.setSubscriptionType(subscriptionInfo.getType()); - response.setStatus(subscriptionInfo.getStatus()); - response.setExpireTime(String.valueOf(subscriptionInfo.getCurrentPeriodEnd())); - response.setAutoRenewal(subscriptionInfo.getStatus().equals("active")); - } - - Affiliate affiliate = affiliateService.getByAccountId(accountId); - if (!Objects.isNull(affiliate) && affiliate.getStatus().equals("Active")) { - response.setAffiliate(true); - } return response; } @@ -2539,4 +2527,13 @@ public class AccountServiceImpl extends ServiceImpl impl accountExtendMapper.delete(qw); return Boolean.TRUE; } + + @Override + public Boolean bindEmail(String email) { + AuthPrincipalVo userHolder = UserContext.getUserHolder(); + Account account = accountMapper.selectById(userHolder.getId()); + account.setUserEmail(email); + accountMapper.updateById(account); + return Boolean.TRUE; + } } diff --git a/src/main/java/com/ai/da/service/impl/DesignServiceImpl.java b/src/main/java/com/ai/da/service/impl/DesignServiceImpl.java index 5f70f836..05275007 100644 --- a/src/main/java/com/ai/da/service/impl/DesignServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/DesignServiceImpl.java @@ -8,6 +8,7 @@ import com.ai.da.common.constant.CommonConstant; 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.DesignBatchMapper; import com.ai.da.mapper.primary.DesignMapper; import com.ai.da.mapper.primary.GenerateDetailMapper; import com.ai.da.mapper.primary.TDesignPythonOutfitMapper; @@ -110,6 +111,9 @@ public class DesignServiceImpl extends ServiceImpl impleme @Resource private RedisUtil redisUtil; + @Resource + private DesignBatchMapper designBatchMapper; + private final ConcurrentHashMap> designContext = new ConcurrentHashMap<>(); @@ -1623,14 +1627,6 @@ public class DesignServiceImpl extends ServiceImpl impleme collectionId = collectionService.saveCollection(userInfo.getId(), designDTO.getTimeZone(), designDTO.getMoodTemplateId(), designDTO.getMoodboardPostion()); }else { collectionId = collectionIdParam; -// Collection byId = collectionService.getById(collectionIdParam); -// if (!designDTO.getMoodboardPostion().equals(byId.getMoodboardPosition())) { -// byId.setMoodboardPosition(designDTO.getMoodboardPostion()); -// } -// if (!designDTO.getMoodTemplateId().equals(byId.getMoodTemplateId())) { -// byId.setMoodTemplateId(designDTO.getMoodTemplateId()); -// } -// collectionService.updateById(byId); } List elementIds = getElementId(elementVO); //批量关联element 到 collection @@ -1662,7 +1658,20 @@ public class DesignServiceImpl extends ServiceImpl impleme startTime = System.currentTimeMillis(); String requestId = UUID.randomUUID().toString(); pythonObjects.setRequestId(requestId); - JSONObject responseJSONObject = pythonService.designBatch(pythonObjects); + AuthPrincipalVo userHolder = UserContext.getUserHolder(); + String taskId = pythonService.designBatch(pythonObjects, userHolder.getId(), elementVO.getDesignNum(), requestId); + + DesignBatch designBatch = new DesignBatch(); + + designBatch.setAccountId(userInfo.getId()); + designBatch.setDesignId(designId); + designBatch.setCollectionId(collectionId); + designBatch.setTaskId(taskId); + designBatch.setCreateTime(LocalDateTime.now()); + designBatch.setStatus(0); + designBatch.setTotalNum(elementVO.getDesignNum()); + designBatchMapper.insert(designBatch); + endTime = System.currentTimeMillis(); totalTimeInSeconds = (endTime - startTime) / 1000; log.info("design python端运行时间:" + totalTimeInSeconds + " 秒"); @@ -1688,11 +1697,181 @@ public class DesignServiceImpl extends ServiceImpl impleme context.put("requestIdList", elementVO.getRequestIdList()); // 将上下文存入全局设计上下文中 - designContext.put(requestId, context); + designContext.put(taskId, context); + return taskId; + } + + @Override + public void processDesignBatch(Map designBatchResult) { + Object progress = designBatchResult.get("progress"); + if (progress instanceof String) { + if (progress.equals("0/100")) { + return; + } + if (progress.equals("ok")) { + String taskId = (String) designBatchResult.get("task_id"); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(DesignBatch::getTaskId, taskId); + List designBatches = designBatchMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(designBatches)) { + DesignBatch designBatch = designBatches.get(0); + designBatch.setStatus(1); + designBatchMapper.updateById(designBatch); + } + } + }else { + String taskId = (String) designBatchResult.get("task_id"); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(DesignBatch::getTaskId, taskId); + List designBatches = designBatchMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(designBatches)) { + DesignBatch designBatch = designBatches.get(0); + if (designBatch.getCompletedNum() == null) { + designBatch.setCompletedNum(1); + }else { + designBatch.setCompletedNum(designBatch.getCompletedNum() + 1); + } + designBatchMapper.updateById(designBatch); + } + + Integer i = (Integer) progress; + Map context; + synchronized (designContext) { + context = designContext.get(taskId); + if (context == null) { + log.error("上下文数据缺失,无法完成操作"); + return; + } + + DesignPythonObjects pythonObjects = (DesignPythonObjects) context.get("pythonObjects"); + Long designId = (Long) context.get("designId"); + Long collectionId = (Long) context.get("collectionId"); + AuthPrincipalVo userInfo = (AuthPrincipalVo) context.get("userInfo"); + String timeZone = (String) context.get("timeZone"); + String singleOverall = (String) context.get("singleOverall"); + + DesignPythonObject item = pythonObjects.getObjects().get(i); + DesignItem designItem = new DesignItem(); + designItem.setAccountId(userInfo.getId()); + designItem.setCollectionId(collectionId); + designItem.setDesignId(designId); + designItem.setCreateDate(DateUtil.getByTimeZone(timeZone)); + //生成的八张图片 + designItem.setDesignUrl(item.getBasic().getSave_name()); + designItem.setHasLike((byte) 0); + //生成designItem + Long designItemId = designItemService.saveOne(designItem); + // python design返回入库及封装 + JSONObject outfit = (JSONObject) designBatchResult.get("result"); + if (null == outfit) { + return; + } + TDesignPythonOutfit designPythonOutfit = new TDesignPythonOutfit(); + designPythonOutfit.setDesignItemId(designItemId); + designPythonOutfit.setUserId(userInfo.getId()); + designPythonOutfit.setDesignId(designId); + designPythonOutfit.setCollectionId(collectionId); + String synthesisUrl = outfit.getString("synthesis_url"); + if (!StringUtils.isEmpty(synthesisUrl)) { + designPythonOutfit.setDesignUrl(synthesisUrl); + } else { + throw new BusinessException("design.interface.exception"); + } + designPythonOutfitService.save(designPythonOutfit); + + JSONArray layers = outfit.getJSONArray("layers"); + List list = new ArrayList<>(); + DesignCollectionItemVO designCollectionItemVO = new DesignCollectionItemVO(); + for (int i1 = 0; i1 < layers.size(); i1++) { + JSONObject jsonObject = layers.getJSONObject(i1); + TDesignPythonOutfitDetail designPythonOutfitDetail = new TDesignPythonOutfitDetail(); + designPythonOutfitDetail.setDesignId(designId); + designPythonOutfitDetail.setDesignPythonOutfitId(designPythonOutfit.getId()); + designPythonOutfitDetail.setPosition(jsonObject.getString("position")); + designPythonOutfitDetail.setImageSize(jsonObject.getString("image_size")); + designPythonOutfitDetail.setImageUrl(jsonObject.getString("image_url")); + if (singleOverall.equals(SingleOverallEnum.SINGLE.getRealName())) { + designCollectionItemVO.setDesignItemUrl(designItem.getDesignUrl()); + } + designPythonOutfitDetail.setImageCategory(jsonObject.getString("image_category")); + designPythonOutfitDetail.setMaskUrl(jsonObject.getString("mask_url")); + designPythonOutfitDetail.setUserId(userInfo.getId()); + designPythonOutfitDetail.setPriority(Integer.parseInt(jsonObject.getString("priority"))); + designPythonOutfitDetail.setCreateDate(LocalDateTime.now()); + list.add(designPythonOutfitDetail); + } + designPythonOutfitDetailService.saveBatch(list); + designCollectionItemVO.setDesignItemId(designItemId); + designCollectionItemVO.setDesignItemUrl(designItem.getDesignUrl()); + designCollectionItemVO.setDesignOutfitId(designPythonOutfit.getId()); + String designUrl = designPythonOutfit.getDesignUrl(); + if (!StringUtils.isEmpty(designUrl) && designUrl.contains("/")) { + int firstIndex = designUrl.indexOf("/"); + designCollectionItemVO.setDesignOutfitUrl(minioUtil.getPreSignedUrl(designUrl.substring(0, firstIndex) + "/" + designUrl.substring(firstIndex + 1), 24 * 60)); + } + //response +// designCollectionItems.add(designCollectionItemVO); + + List designItemDetails = Lists.newArrayList(); + Map typePriority = list.stream().collect(Collectors.toMap(d -> d.getImageCategory().split("_")[0], + d -> Math.abs(d.getPriority()), + (existing, replacement) -> replacement)); + Map typeAndUndividedLayer = designItemService.setTypeAndUndividedLayer(layers); + for (DesignPythonItem detail : item.getItems()) { + if (null == detail) { + continue; + } + DesignItemDetail designItemDetail = CopyUtil.copyObject(detail, DesignItemDetail.class); + designItemDetail.setAccountId(userInfo.getId()); + designItemDetail.setDesignId(designId); + designItemDetail.setDesignItemId(designItemId); + designItemDetail.setCollectionElementId(detail.getElementId()); + designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone)); + designItemDetail.setUndividedLayer(typeAndUndividedLayer.get(designItemDetail.getType().toLowerCase())); + if (SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType())) { + designItemDetail.setPath(detail.getBody_path()); + //BODY不关联businessId + designItemDetail.setBusinessId(0L); + } + designItemDetail.setIconPath(detail.getIcon()); + designItemDetail.setPriority(typePriority.get(detail.getType().toLowerCase())); + if (!detail.getType().equals("Body")){ + DesignPythonItemPrint printObject = detail.getPrint().getOverall(); +// designItemDetail.setPrintPath(Objects.isNull(printObject) ? "" : printObject.getPath()); + designItemDetail.setPrintPath(CollectionUtils.isEmpty(printObject.getPrint_path_list()) ? "" : printObject.getPrint_path_list().get(0)); + } + designItemDetailService.save(designItemDetail); + if (!SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType()) && !StringUtil.isNullOrEmpty(designItemDetail.getPrintPath())) { + DesignItemDetailPrint print = new DesignItemDetailPrint(); + print.setDesignItemDetailId(designItemDetail.getId()); + print.setPrintType("print"); + print.setPath(designItemDetail.getPrintPath()); + print.setSingleOrOverall("overall"); + print.setPosition("[0.0,0.0]"); +// print.setScale(1d); + // todo mark 将print默认scale置为0.3 + print.setScale(0.3d); + print.setAngle(0.0); + print.setPriority(1); + QueryWrapper getPrintboardLevel2TypeQw = new QueryWrapper<>(); + getPrintboardLevel2TypeQw.lambda().eq(CollectionElement::getUrl, print.getPath()); + getPrintboardLevel2TypeQw.lambda().orderByDesc(CollectionElement::getCreateDate); + getPrintboardLevel2TypeQw.last("limit 1"); + CollectionElement one = collectionElementService.getOne(getPrintboardLevel2TypeQw); + print.setLevel2Type(one.getLevel2Type()); + print.setCreateDate(LocalDateTime.now()); + designItemDetailPrintService.save(print); + } + } + } + +// for (int i = 0; i < pythonObjects.getObjects().size(); i++) { +// +// } +// response.setProcessId(pythonObjects.getProcess_id()); + return; + } - //保存python返回信息;保存designItem和detail -// return savePythonDesignItemAndDetail(pythonObjects, designId, collectionId, userInfo, designDTO.getTimeZone(), responseJSONObject, designDTO.getSingleOverall()); - return requestId; } }