diff --git a/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java b/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java index b6565c86..5442ae06 100644 --- a/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java +++ b/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java @@ -12,26 +12,26 @@ public class MQConfig { // public static final String GENERATE_QUEUE = "generate-queue-test"; // ================================================================== // public static final String GENERATE_QUEUE = "generate-queue-local"; - public static final String GENERATE_QUEUE = "generate-queue-dev"; -// public static final String GENERATE_QUEUE = "generate-queue-prod"; +// public static final String GENERATE_QUEUE = "generate-queue-dev"; + public static final String GENERATE_QUEUE = "generate-queue-prod"; // // public static final String SR_QUEUE = "SR-queue-local"; - public static final String SR_QUEUE = "SR-queue-dev"; -// public static final String SR_QUEUE = "SR-queue-prod"; +// public static final String SR_QUEUE = "SR-queue-dev"; + public static final String SR_QUEUE = "SR-queue-prod"; // // public static final String SR_RESULT_QUEUE = "SuperResolution-local"; - public static final String SR_RESULT_QUEUE = "SuperResolution-dev"; -// public static final String SR_RESULT_QUEUE = "SuperResolution-prod"; +// public static final String SR_RESULT_QUEUE = "SuperResolution-dev"; + public static final String SR_RESULT_QUEUE = "SuperResolution-prod"; // // public static final String GENERATE_RESULT_QUEUE = "GenerateImage-local"; - public static final String GENERATE_RESULT_QUEUE = "GenerateImage-dev"; -// public static final String GENERATE_RESULT_QUEUE = "GenerateImage-prod"; +// public static final String GENERATE_RESULT_QUEUE = "GenerateImage-dev"; + public static final String GENERATE_RESULT_QUEUE = "GenerateImage-prod"; - public static final String TO_PRODUCT_IMAGE_RESULT_QUEUE = "ToProductImage-dev"; -// public static final String TO_PRODUCT_IMAGE_RESULT_QUEUE = "ToProductImage-prod"; +// public static final String TO_PRODUCT_IMAGE_RESULT_QUEUE = "ToProductImage-dev"; + public static final String TO_PRODUCT_IMAGE_RESULT_QUEUE = "ToProductImage-prod"; - public static final String RELIGHT_RESULT_QUEUE = "Relight-dev"; -// public static final String RELIGHT_RESULT_QUEUE = "Relight-prod"; +// public static final String RELIGHT_RESULT_QUEUE = "Relight-dev"; + public static final String RELIGHT_RESULT_QUEUE = "Relight-prod"; public MQConfig() { } 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 df7d8677..69f2ffd9 100644 --- a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java +++ b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java @@ -49,7 +49,7 @@ public class MyTaskScheduler { // 定时任务,每十五天执行一次 // @Scheduled(cron = "0 0 0 ? * MON") -// @Scheduled(cron = "0 0 0 */15 * ?") + @Scheduled(cron = "0 0 0 */15 * ?") public void checkExpiry() { // 检测正式用户是否快要过期 QueryWrapper qw = new QueryWrapper<>(); @@ -83,7 +83,7 @@ public class MyTaskScheduler { } } } -// @Scheduled(cron = "0 0 8 * * ?") + @Scheduled(cron = "0 0 8 * * ?") public void sendTrialOrderExcelToManagements() { // 获取前一天日期 LocalDate yesterday = LocalDate.now().minusDays(1); diff --git a/src/main/java/com/ai/da/common/task/AccountTask.java b/src/main/java/com/ai/da/common/task/AccountTask.java index 58d488cd..8027cfb8 100644 --- a/src/main/java/com/ai/da/common/task/AccountTask.java +++ b/src/main/java/com/ai/da/common/task/AccountTask.java @@ -24,7 +24,7 @@ public class AccountTask { accountService.refreshCreditsWeekly(); } -// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes + @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes public void getPaidUser(){ // 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单 accountService.extendValidityForCC(); @@ -38,7 +38,7 @@ public class AccountTask { // 2、将到期用户置为游客 for(Account account : accountList){ - log.info("参与活动的用户到期,置为游客"); + log.info("参与活动的用户{} : {} 于 {} 账号有效期到期,置为游客",account.getId(),account.getUserEmail(),account.getValidEndTime()); accountService.toVisitor(account); } } @@ -53,7 +53,7 @@ public class AccountTask { // 2、将到期用户置为游客 for(Account account : accountList){ - log.info("用户有效期到期,置为游客"); + log.info("用户{} : {} 于 {}账号有效期到期,置为游客", account.getId(), account.getUserEmail(),account.getValidEndTime()); accountService.toVisitor(account); } } 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 ffb0f424..66ba1ab3 100644 --- a/src/main/java/com/ai/da/common/utils/RedisUtil.java +++ b/src/main/java/com/ai/da/common/utils/RedisUtil.java @@ -7,10 +7,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -154,6 +151,8 @@ public class RedisUtil { return redisTemplate.keys(key); } + public Long getSize(String key){return redisTemplate.opsForSet().size(key);} + public List getMultiValue(Set keys){ return redisTemplate.opsForValue().multiGet(keys); } @@ -216,6 +215,19 @@ public class RedisUtil { return redisTemplate.opsForValue().increment(key, 0); } + public Long getViewCount(String key) { + Object value = redisTemplate.opsForValue().get(key); + if (value instanceof Integer) { + return Long.valueOf((Integer) value); + } else if (value instanceof Long) { + return (Long) value; + } else if (value instanceof String) { + return Long.valueOf((String) value); + } else { + throw new IllegalArgumentException("Unexpected value type"); + } + } + public final static String PERSONAL_HOMEPAGE_VIEW_KEY = "PersonalHomepage:view:"; public void increasePersonalHomepageViewCount(Long accountId) { @@ -228,5 +240,4 @@ public class RedisUtil { return redisTemplate.opsForValue().increment(key, 0); } - } diff --git a/src/main/java/com/ai/da/controller/DesignDetailController.java b/src/main/java/com/ai/da/controller/DesignDetailController.java index 1e06e825..994b0b2c 100644 --- a/src/main/java/com/ai/da/controller/DesignDetailController.java +++ b/src/main/java/com/ai/da/controller/DesignDetailController.java @@ -82,17 +82,16 @@ public class DesignDetailController { } @ApiOperation(value = "mask数据兼容") - @PostMapping("/convertWithoutGradient") + @GetMapping("/convertWithoutGradient") public Response convertHistoryMaskWithoutGradient(){ designItemService.convertHistoryMaskWithoutGradient(); return Response.success("success"); } - @Resource - private UserLikeService userLikeService; - @ApiOperation(value = "获取历史like中包含有渐变色的design") - @PostMapping("/getHistoryLikeWithGradient") - public Response>> getHistoryLikeWithGradient(){ - return Response.success(userLikeService.getHistoryLikeWithGradient()); + @ApiOperation(value = "mask数据库路径更新") + @GetMapping("/updateMaskUrl") + public Response updateMaskUrl(){ + designItemService.updateMaskUrl(); + return Response.success("success"); } } diff --git a/src/main/java/com/ai/da/controller/GenerateController.java b/src/main/java/com/ai/da/controller/GenerateController.java index caa80dcc..17fc811b 100644 --- a/src/main/java/com/ai/da/controller/GenerateController.java +++ b/src/main/java/com/ai/da/controller/GenerateController.java @@ -2,7 +2,9 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; import com.ai.da.model.dto.GenerateLikeDTO; +import com.ai.da.model.dto.GenerateModifyDTO; import com.ai.da.model.dto.GenerateThroughImageTextDTO; +import com.ai.da.model.dto.ImageToSketchDTO; import com.ai.da.model.vo.*; import com.ai.da.service.GenerateService; import io.swagger.annotations.Api; @@ -83,5 +85,17 @@ public class GenerateController { return Response.success(generateResult); } + @ApiOperation(value = "imageToSketch") + @PostMapping("/imageToSketch") + public Response imageToSketch(@Valid @RequestBody ImageToSketchDTO imageToSketchDTO) { + return Response.success(generateService.imageToSketch(imageToSketchDTO)); + } + + // modifySketch + @ApiOperation(value = "modifySketch") + @PostMapping("/modifySketch") + public Response modifySketch(@Valid @RequestBody GenerateModifyDTO generateModifyDTO) { + return Response.success(generateService.modifySketch(generateModifyDTO)); + } } diff --git a/src/main/java/com/ai/da/controller/SavedCollectionController.java b/src/main/java/com/ai/da/controller/SavedCollectionController.java index 228646dc..76addf89 100644 --- a/src/main/java/com/ai/da/controller/SavedCollectionController.java +++ b/src/main/java/com/ai/da/controller/SavedCollectionController.java @@ -104,9 +104,9 @@ public class SavedCollectionController { } List groupIds = page.getRecords().stream().map(UserLikeGroup::getId).collect(Collectors.toList()); List groupDetails = userLikeService.getGroupDetails(groupIds); - if (CollectionUtils.isEmpty(groupDetails)) { - throw new BusinessException("groupDetails.not.found"); - } +// if (CollectionUtils.isEmpty(groupDetails)) { +// throw new BusinessException("groupDetails.not.found"); +// } Map> groupDetailMap = groupDetails.stream() .collect(Collectors.groupingBy(UserLikeVO::getUserLikeGroupId)); @@ -117,13 +117,17 @@ public class SavedCollectionController { userLikeGroupVO.setUpdateDate(group.getUpdateDate().getTime()); userLikeGroupVO.setAuthor(account.getUserName()); //count 和detail - List details = groupDetailMap.get(group.getId()); - for (UserLikeVO detail : details) { - TDesignPythonOutfit tDesignPythonOutfit = designPythonOutfitMapper.selectById(detail.getDesignOutfitId()); - detail.setUrl(minioUtil.getPreSignedUrl(tDesignPythonOutfit.getDesignUrl(), 24 * 60)); + if (groupDetailMap.keySet().contains(group.getId())) { + List details = groupDetailMap.get(group.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); } - userLikeGroupVO.setGroupDetails(details); - userLikeGroupVO.setSketchCount(CollectionUtils.isEmpty(details) ? 0 : details.size()); if (userLikeGroupVO.getOriginal() == 0) { userLikeGroupVO.setOriginalAccountName(accountService.getById(userLikeGroupVO.getOriginalAccountId()).getUserName()); Portfolio byId = portfolioService.getByIdAll(userLikeGroupVO.getOriginalPortfolioId()); 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 ecdf8b45..4ec7fe8e 100644 --- a/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitDetailMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/TDesignPythonOutfitDetailMapper.java @@ -4,6 +4,8 @@ import com.ai.da.common.config.mybatis.plus.CommonMapper; import com.ai.da.mapper.primary.entity.TDesignPythonOutfitDetail; import com.ai.da.model.vo.TDesignPythonOutfitDetailVO; import com.baomidou.mybatisplus.core.metadata.IPage; +import io.lettuce.core.dynamic.annotation.Param; +import org.apache.ibatis.annotations.Delete; import java.util.List; @@ -24,4 +26,7 @@ public interface TDesignPythonOutfitDetailMapper extends CommonMapper selectTDesignPythonOutfitDetailPage(IPage page, TDesignPythonOutfitDetailVO tDesignPythonOutfitDetail); + @Delete("DELETE FROM t_design_python_outfit_detail WHERE design_python_outfit_id = #{designPythonOutfitId}") + void deleteByDesignPythonOutfitIdPhysical(@Param("designPythonOutfitId") Long designPythonOutfitId); + } diff --git a/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java b/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java index 5632606a..34e7a0d1 100644 --- a/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/UserLikeMapper.java @@ -14,8 +14,4 @@ import java.util.Map; */ public interface UserLikeMapper extends CommonMapper { - List> getHistoryLikeWithoutGradient(); - - List> getHistoryLikeWithGradient(); - } diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Generate.java b/src/main/java/com/ai/da/mapper/primary/entity/Generate.java index 6d1148db..7a3157ab 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/Generate.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/Generate.java @@ -72,6 +72,19 @@ public class Generate { */ private String seed; + /** + * 1 -> 粗 + * 2 -> 中 + * 3 -> 细 + * custom -> 自定义 + */ + private String sketchStyle; + + /** + * sketch 风格参考图的collection_element_id + */ + private Long styleImageElementId; + /** * 创建时间 */ diff --git a/src/main/java/com/ai/da/model/dto/GenerateModifyDTO.java b/src/main/java/com/ai/da/model/dto/GenerateModifyDTO.java new file mode 100644 index 00000000..5cc4a77f --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/GenerateModifyDTO.java @@ -0,0 +1,18 @@ +package com.ai.da.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("修改imageToSketch提取出的sketch") +@Data +public class GenerateModifyDTO { + @ApiModelProperty("需要保存的图片的base64格式") + private String base64; + + @ApiModelProperty("sketch所属性别") + private String gender; + + @ApiModelProperty("sketch所属分类") + private String category; +} diff --git a/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java b/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java index 6320dd5d..8dbeca50 100644 --- a/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java +++ b/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java @@ -25,7 +25,7 @@ public class GenerateThroughImageTextDTO { @ApiModelProperty("text image text-image") String generateType; - @ApiModelProperty("图片是update,还是从library中选择 collection || library") + @ApiModelProperty("图片来源:update,从library中选择,从toProductImage结果中选择 collection || library || productImage") String designType; @NotBlank(message = "level1Type cannot be empty!") diff --git a/src/main/java/com/ai/da/model/dto/ImageToSketchDTO.java b/src/main/java/com/ai/da/model/dto/ImageToSketchDTO.java new file mode 100644 index 00000000..983172c9 --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/ImageToSketchDTO.java @@ -0,0 +1,22 @@ +package com.ai.da.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("image to sketch") +@Data +public class ImageToSketchDTO { + + @ApiModelProperty("上传图片的collection_element_id") + private Long elementId; + + @ApiModelProperty("sketch线条风格 1->粗, 2->中, 3->细,传数字,自定义风格时,传空 ") + private String style; + + @ApiModelProperty("自定义线条风格,上传图片的collection_element_id") + private Long styleImageId; + + @ApiModelProperty("性别") + private String gender; +} diff --git a/src/main/java/com/ai/da/model/enums/SketchGenerateType.java b/src/main/java/com/ai/da/model/enums/SketchGenerateType.java new file mode 100644 index 00000000..ea92b547 --- /dev/null +++ b/src/main/java/com/ai/da/model/enums/SketchGenerateType.java @@ -0,0 +1,18 @@ +package com.ai.da.model.enums; + +public enum SketchGenerateType implements IEnumDisplay{ + GENERATE("generate"), + + EXTRACT("extract"),; + + private String value; + + SketchGenerateType(String value) { + this.value = value; + } + + @Override + public String getValue() { + return value; + } +} diff --git a/src/main/java/com/ai/da/model/enums/SketchStyle.java b/src/main/java/com/ai/da/model/enums/SketchStyle.java new file mode 100644 index 00000000..475b3a01 --- /dev/null +++ b/src/main/java/com/ai/da/model/enums/SketchStyle.java @@ -0,0 +1,20 @@ +package com.ai.da.model.enums; + +public enum SketchStyle implements IEnumDisplay{ + + THICK("1"), + + MEDIUM("2"), + + THIN("3"); + + private String value; + + SketchStyle(String value) { + this.value = value; + } + @Override + public String getValue() { + return value; + } +} diff --git a/src/main/java/com/ai/da/model/vo/GenerateResultVO.java b/src/main/java/com/ai/da/model/vo/GenerateResultVO.java index 4a5f1453..4c82f674 100644 --- a/src/main/java/com/ai/da/model/vo/GenerateResultVO.java +++ b/src/main/java/com/ai/da/model/vo/GenerateResultVO.java @@ -28,9 +28,10 @@ public class GenerateResultVO { this.status = status; } - public GenerateResultVO(Long id, String url, String status) { + public GenerateResultVO(Long id, String url, String status, String category) { this.id = id; this.url = url; this.status = status; + this.category = category; } } diff --git a/src/main/java/com/ai/da/python/PythonService.java b/src/main/java/com/ai/da/python/PythonService.java index da9b19b6..e6f29713 100644 --- a/src/main/java/com/ai/da/python/PythonService.java +++ b/src/main/java/com/ai/da/python/PythonService.java @@ -63,8 +63,6 @@ public class PythonService { private String accessPythonIp; @Value("${access.python.port:''}") private String accessPythonPort; - @Value("${access.python.address}") - private String fastApiPythonAddress; @Value("${minio.bucketName.gradient}") private String gradientBucketName; @Value("${access.python.generate_sr_port}") @@ -2663,8 +2661,6 @@ public class PythonService { minioPath = minioUtil.base64UploadToPath(colorImg, gradientBucketName, null); designSingleItem.getGradient().setColorImg(null); gradientString = JSONObject.toJSONString(designSingleItem.getGradient()); - - // todo 当渐变色不为空时,是否需要将颜色置为 0 0 0 } PrintToPython printToPython = resolveDesignSinglePrint(designSingleItem.getPrintObject().getPrints()); @@ -3470,4 +3466,64 @@ public class PythonService { //生成失败 throw new BusinessException("relightImage.interface.exception"); } + + public String imageToSketch(String imagePath, String bucket, String objectName, String styleCode, String styleImageUrl){ + OkHttpClient client = new OkHttpClient().newBuilder() + .connectTimeout(30, TimeUnit.SECONDS) + .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒) + .readTimeout(60, TimeUnit.SECONDS)//读取超时(单位:秒) + .writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒) + .build(); + MediaType paramMap = MediaType.parse("application/json"); + //关闭FastJson的引用检测 防止出现$ref 现象 + Map map = new HashMap<>(); + map.put("image_url", imagePath); + map.put("style_image_url", styleImageUrl); + map.put("default_style", styleCode); + map.put("sketch_bucket", bucket); + map.put("sketch_name", objectName); + + String param = JSON.toJSONString(map, SerializerFeature.WriteNullStringAsEmpty); + log.info("ImageToSketch请求python 参数:####{}", param); + RequestBody body = RequestBody.create(paramMap, param); + Request request = new Request.Builder() + .url(accessPythonIp + ":" + accessPythonPort + "/api/image2sketch") + .method("POST", body) + .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==") + .addHeader("Content-Type", "application/json") + .build(); + Response response; + + try { + response = client.newCall(request).execute(); + } catch (IOException ioException) { + log.error("PythonService##ImageToSketch异常###{}", ExceptionUtil.getThrowableList(ioException)); + throw new BusinessException("generate.interface.error"); + } + int responseCode = response.code(); + String bodyString; + try { + bodyString = response.body().string(); + if (responseCode != HttpURLConnection.HTTP_OK) { + // 基本不会有除200以外的code + log.info("ImageToSketch 失败。 Response code {}", responseCode); + throw new BusinessException("ImageToSketch 失败。 Response code " + responseCode); + } + JSONObject jsonObject = JSON.parseObject(bodyString); + if (response.isSuccessful() && jsonObject.get("msg").equals("OK!")) { + String sketchResult = jsonObject.get("data").toString(); + log.info("ImageToSketch 结果 : {}", sketchResult); + return sketchResult; + }else { + log.info("ImageToSketch 失败。 Response code {}", responseCode); + throw new BusinessException("ImageToSketch 失败。 Response code " + responseCode); + } + } catch (IOException e) { + log.error("ImageToSketch 失败; error message => {}", e.getMessage()); + response.close(); + throw new BusinessException("generate.interface.error"); + } finally { + response.close(); + } + } } diff --git a/src/main/java/com/ai/da/service/DesignItemService.java b/src/main/java/com/ai/da/service/DesignItemService.java index 5a0935f6..fcc1e78b 100644 --- a/src/main/java/com/ai/da/service/DesignItemService.java +++ b/src/main/java/com/ai/da/service/DesignItemService.java @@ -62,4 +62,6 @@ public interface DesignItemService extends IService { Long getCountByUserAndTime(String startTime, String endTime, List accountIds); void convertHistoryMaskWithoutGradient(); + + void updateMaskUrl(); } diff --git a/src/main/java/com/ai/da/service/GenerateService.java b/src/main/java/com/ai/da/service/GenerateService.java index f1f219aa..1bb28186 100644 --- a/src/main/java/com/ai/da/service/GenerateService.java +++ b/src/main/java/com/ai/da/service/GenerateService.java @@ -3,7 +3,9 @@ package com.ai.da.service; import com.ai.da.mapper.primary.entity.Generate; import com.ai.da.mapper.primary.entity.GenerateDetail; import com.ai.da.model.dto.GenerateLikeDTO; +import com.ai.da.model.dto.GenerateModifyDTO; import com.ai.da.model.dto.GenerateThroughImageTextDTO; +import com.ai.da.model.dto.ImageToSketchDTO; import com.ai.da.model.vo.*; import com.baomidou.mybatisplus.extension.service.IService; @@ -41,4 +43,8 @@ public interface GenerateService extends IService { void processRelightResult(String taskId, String url, String category); List> getCountByUserAndTime(String startTime, String endTime, List accountIdList); + + GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO); + + CollectionElementVO modifySketch(GenerateModifyDTO generateModifyDTO); } diff --git a/src/main/java/com/ai/da/service/ITDesignPythonOutfitDetailService.java b/src/main/java/com/ai/da/service/ITDesignPythonOutfitDetailService.java index c11bb759..0802ee98 100644 --- a/src/main/java/com/ai/da/service/ITDesignPythonOutfitDetailService.java +++ b/src/main/java/com/ai/da/service/ITDesignPythonOutfitDetailService.java @@ -36,7 +36,9 @@ public interface ITDesignPythonOutfitDetailService extends IService offset); - void deleteByDesignPythonOutfitId(Long designPythonOutfitId); + void deleteByDesignPythonOutfitIdLogical(Long designPythonOutfitId); + + void deleteByDesignPythonOutfitIdPhysical(Long designPythonOutfitId); void setDesignPythonOutfitDetailPriority(List details); diff --git a/src/main/java/com/ai/da/service/UserLikeService.java b/src/main/java/com/ai/da/service/UserLikeService.java index 0be8c536..8847367c 100644 --- a/src/main/java/com/ai/da/service/UserLikeService.java +++ b/src/main/java/com/ai/da/service/UserLikeService.java @@ -26,6 +26,4 @@ public interface UserLikeService extends IService { void updateDate(Long designItemId,String timeZone); List getUserLikeList(Long id); - - List> getHistoryLikeWithGradient(); } diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index d135060b..6a82b081 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -1,1588 +1,1587 @@ -package com.ai.da.service.impl; - -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.AuthenticationOperationTypeEnum; -import com.ai.da.common.enums.CreditsEventsEnum; -import com.ai.da.common.enums.LoginTypeEnum; -import com.ai.da.common.response.ResultEnum; -import com.ai.da.common.security.jwt.JWTTokenHelper; -import com.ai.da.common.utils.*; -import com.ai.da.mapper.primary.AccountMapper; -import com.ai.da.mapper.primary.QuestionnaireMapper; -import com.ai.da.mapper.primary.TrialOrderMapper; -import com.ai.da.mapper.primary.entity.*; -import com.ai.da.model.dto.*; -import com.ai.da.model.enums.AutoApproved; -import com.ai.da.model.enums.Language; -import com.ai.da.model.vo.*; -import com.ai.da.service.*; -import com.alibaba.fastjson.JSON; -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.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import io.netty.util.internal.StringUtil; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Assert; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.sql.DataSource; -import java.math.BigDecimal; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.text.SimpleDateFormat; -import java.time.*; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import java.util.*; -import java.util.stream.Collectors; - -/** - * 服务实现类 - * - * @author easy-generator - * @since 2022-07-06 - */ -@Slf4j -@Service -public class AccountServiceImpl extends ServiceImpl implements AccountService { - @Resource - private AccountMapper accountMapper; - - @Resource - private JWTTokenHelper jwtTokenHelper; - - @Resource - private AccountLoginLogService accountLoginLogService; - - @Resource - private LibraryService libraryService; - - @Resource - private UserLikeGroupService userLikeGroupService; - - @Resource - private TrialOrderMapper trialOrderMapper; - - @Resource - private QuestionnaireMapper questionnaireMapper; - - @Resource - private CreditsService creditsService; - - @Resource - private MinioUtil minioUtil; - - @Value("${minio.bucketName.users}") - private String userBucket; - - @Resource - private RedisUtil redisUtil; - - @Override - @Transactional(rollbackFor = Exception.class) - public AccountPreLoginVO preLogin(AccountPreLoginDTO accountDTO) { - log.info("aida预先登入accountDTO###{}", JSON.toJSONString(accountDTO)); - Account account = getOneByEmail(accountDTO.getEmail()); - //用户有效期校验 - validateUserValidaExpire(account); - if ("Third-000000".equals(account.getUserPassword())) { - account.setUserPassword(accountDTO.getPassword()); - accountMapper.updateById(account); - } else { - if (!account.getUserPassword().equals(accountDTO.getPassword())) { - throw new BusinessException("password.error", ResultEnum.PROMPT.getCode()); - } - } - /*发送邮件*/ - AuthenticationOperationTypeEnum authenticationOperationTypeEnum = AuthenticationOperationTypeEnum.of(accountDTO.getOperationType()); - log.info(account.getUserEmail()); - log.info(accountDTO.getEmail()); - if (!account.getUserEmail().equals(accountDTO.getEmail())) { - throw new BusinessException("email.error", ResultEnum.PROMPT.getCode()); - } - if (Objects.isNull(authenticationOperationTypeEnum)) { - throw new BusinessException("unknown.authentication.operation.type"); - } - String randomVerifyCode = RandomsUtil.generateVerifyCode(100000L, 999999L); - LocalCacheUtils.setVerifyCodeCache( - accountDTO.getOperationType() + "_" + accountDTO.getEmail(), randomVerifyCode); - Boolean result = Boolean.FALSE; - switch (authenticationOperationTypeEnum) { - case LOGIN: - result = SendEmailUtil.send(accountDTO.getEmail(), null, - SendEmailUtil.LOGIN_TEMPLATE_ID, randomVerifyCode); - break; - case FORGET_PWD: - result = SendEmailUtil.send(accountDTO.getEmail(), null, - SendEmailUtil.UPDATE_PWD_TEMPLATE_ID, randomVerifyCode); - break; - case EXCEPTION_IP: - result = SendEmailUtil.send(accountDTO.getEmail(), accountDTO.getIp(), - SendEmailUtil.EXCEPTION_ID_TEMPLATE_ID, randomVerifyCode); - break; - case BIND_MAILBOX: - result = SendEmailUtil.send(accountDTO.getEmail(), null, - SendEmailUtil.BIND_MAILBOX_TEMPLATE_ID, randomVerifyCode); - break; - default: - } - if (!result) { - throw new BusinessException("failed.to.send.mail"); - } - return new AccountPreLoginVO(account.getId()); - } - - @Resource - private PortfolioService portfolioService; - - @Transactional(rollbackFor = Exception.class) - @Override - public AccountLoginVO login(AccountLoginDTO accountLoginDTO, HttpServletRequest request) { -// Assert.isTrue(StringUtils.isNotBlank(accountLoginDTO.getEmail()), "Please input a email !"); -// Assert.isTrue(StringUtils.isNotBlank(accountLoginDTO.getEmailVerifyCode()), "Please input the email verification code !"); - log.info("aida确认登入###accountLoginDTO###{}", JSON.toJSONString(accountLoginDTO)); - Account accountExist = getOneByEmail(accountLoginDTO.getEmail().trim()); - LoginTypeEnum accountType = LoginTypeEnum.of(accountLoginDTO.getLoginType()); - if (Objects.isNull(accountType)) { - throw new BusinessException("unknown.login.type"); - } - if (!accountType.equals(LoginTypeEnum.EMAIL)) { - throw new BusinessException("error.login.type"); - } - //用户有效期校验 - validateUserValidaExpire(accountExist); - - Account account = null; - switch (accountType) { - case PASSWORD: -// Assert.isTrue(StringUtils.isNotBlank(accountLoginDTO.getPassword()), "Please input a password !"); -// account = getOneByUserName(accountLoginDTO.getUserName()); -// Assert.isTrue(Objects.nonNull(account), "User does not exist!"); -// Assert.isTrue(account.getUserPassword().equals(accountLoginDTO.getPassword()), "Password error !"); - // 走不到这边 - break; - case EMAIL: - account = getOneByEmail(accountLoginDTO.getEmail().trim()); - //校验邮箱验证码 - String verifyCode = LocalCacheUtils.getVerifyCodeCache(AuthenticationOperationTypeEnum.LOGIN.name() + "_" + accountLoginDTO.getEmail()); - if (StringUtils.isBlank(verifyCode)) { - throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); - } - if (!"921314".equals(accountLoginDTO.getEmailVerifyCode())) { - if (!verifyCode.equals(accountLoginDTO.getEmailVerifyCode())) { - throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); - } - } - break; - default: - } - AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); - response.setEmail(account.getUserEmail()); - String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); - if (StringUtils.isNotBlank(token)) { - //用户已登入 - response.setToken(token); - } else { - response.setToken(createAccountToken(account)); - } - response.setUserId(account.getId()); - response.setSystemUser(account.getSystemUser()); - // 设置头像 - String avatar; - if (StringUtil.isNullOrEmpty(account.getAvatar())){ - avatar = CommonConstant.DEFAULT_AVATAR; - }else { - avatar = account.getAvatar(); - } - response.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); - response.setFolloweeCount(portfolioService.getFolloweeCount(account.getId())); - response.setFollowerCount(portfolioService.getFollowerCount(account.getId())); - //判断是否常用ip 不是则发邮件提示 - calculateExceptionIp(RequestInfoUtil.getIpAddress(request), account); - return response; - } - - private void validateUserValidaExpire(Account account) { - Long currentTime = new Date().getTime(); - if (Objects.nonNull(account.getValidStartTime())) { - if (currentTime < account.getValidStartTime()) { - throw new BusinessException("user.expired"); - } - } - if (Objects.nonNull(account.getValidEndTime())) { - if (currentTime > account.getValidEndTime()) { - throw new BusinessException("user.expired"); - } - } - } - - private void calculateExceptionIp(String ip, Account account) { - //必须先绑定邮箱才可以发有异常ip邮件提醒 - if (StringUtils.isNotBlank(account.getUserEmail())) { - List accountLoginLogs = accountLoginLogService.getByUserId(account.getId()); - if (CollectionUtil.isNotEmpty(accountLoginLogs)) { - List existIps = accountLoginLogs.stream().map(AccountLoginLog::getIp).collect(Collectors.toList()); - if (!existIps.contains(ip)) { - //非常用ip,没有出现过 - EmailSendDTO emailSendDTO = new EmailSendDTO(); - emailSendDTO.setEmail(account.getUserEmail()); - emailSendDTO.setOperationType(AuthenticationOperationTypeEnum.EXCEPTION_IP.name()); - emailSendDTO.setIp(ip); - sendEmail(emailSendDTO); - } - } - } - //保存登入日志 - accountLoginLogService.saveLoginLog(ip, account.getId()); - } - - private String createAccountToken(Account account) { - AuthPrincipalVo principal = new AuthPrincipalVo(); - principal.setId(account.getId()); - principal.setUsername(account.getUserName()); - principal.setLanguage(account.getLanguage()); - principal.setCountry(account.getCountry()); - String token2 = jwtTokenHelper.createToken(principal); - LocalCacheUtils.setTokenCache(String.valueOf(account.getId()), token2); - return token2; - } - - @Override - public Boolean bindEmail(AccountBindEmailDTO accountBindEmailDTO) { - Account account = baseMapper.selectById(accountBindEmailDTO.getUserId()); - if (Objects.isNull(account)) { - throw new BusinessException("userName.does.not.exist", ResultEnum.PROMPT.getCode()); - } - if (StringUtils.isNotBlank(account.getUserEmail())) { - throw new BusinessException("user.has.bound.mailbox"); - } - //校验邮箱验证码 - String verifyCode = LocalCacheUtils.getVerifyCodeCache(AuthenticationOperationTypeEnum.BIND_MAILBOX.name() + "_" + accountBindEmailDTO.getUserEmail()); - if (StringUtils.isBlank(verifyCode)) { - throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); - } - if (!verifyCode.equals(accountBindEmailDTO.getEmailVerifyCode())) { - throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); - } - //绑定 - updatePwdByUserId(accountBindEmailDTO.getUserEmail(), accountBindEmailDTO.getUserId()); - return Boolean.TRUE; - } - - @Transactional(rollbackFor = Exception.class) - @Override - public Boolean forgetPwd(AccountRegisterDTO accountDTO) { -// Account emailAccount = getOneByEmail(accountDTO.getEmail()); - //校验邮箱验证码 - if (accountDTO.getVerifyEmail()) { - String verifyCode = LocalCacheUtils.getVerifyCodeCache(AuthenticationOperationTypeEnum.FORGET_PWD.name() + "_" + accountDTO.getEmail()); - if (StringUtils.isBlank(verifyCode)) { - throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); - } - if (!verifyCode.equals(accountDTO.getEmailVerifyCode())) { - throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); - } - } else { - updatePwdByEmail(accountDTO.getPassword(), accountDTO.getEmail()); - } - return Boolean.TRUE; - } - - private void updatePwdByEmail(String pwd, String email) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().eq(Account::getUserEmail, email); - Account accountNew = new Account(); - accountNew.setUserPassword(pwd); - accountMapper.update(accountNew, queryWrapper); - } - - private void updatePwdByUserId(String email, Long userId) { - Account accountNew = new Account(); - accountNew.setUserEmail(email); - accountNew.setId(userId); - accountMapper.updateById(accountNew); - } - - - private Account getOneByEmail(String email) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("BINARY user_email", email); - List accountList = accountMapper.selectList(queryWrapper); - log.info(accountList.toString()); - if (CollectionUtil.isEmpty(accountList)) { - throw new BusinessException("email.does.not.exist", ResultEnum.PROMPT.getCode()); - } - return accountList.get(0); - } - - // 忽略大小写 - private Account getAccountByEmail(String email) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("user_email", email); - List accountList = accountMapper.selectList(queryWrapper); - log.info(accountList.toString()); - if (CollectionUtil.isEmpty(accountList)) { - throw new BusinessException("email.does.not.exist", ResultEnum.PROMPT.getCode()); - } - return accountList.get(0); - } - - private Account getOneByUserName(String userName) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().eq(Account::getUserName, userName); - queryWrapper.lambda().last("limit 1"); - List accountList = accountMapper.selectList(queryWrapper); - if (CollectionUtil.isEmpty(accountList)) { - throw new BusinessException("userName.does.not.exist", ResultEnum.PROMPT.getCode()); - } - return accountList.get(0); - } - - private Account getOneByUserId(Long userId) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("id", userId); - return accountMapper.selectOne(queryWrapper); - } - - - @Override - public Boolean sendEmail(EmailSendDTO emailSendDTO) { - AuthenticationOperationTypeEnum authenticationOperationTypeEnum = AuthenticationOperationTypeEnum.of(emailSendDTO.getOperationType()); - if (Objects.isNull(authenticationOperationTypeEnum)) { - throw new BusinessException("unknown.authentication.operation.type"); - } - Account emailAccount = getOneByEmail(emailSendDTO.getEmail()); - String randomVerifyCode = RandomsUtil.generateVerifyCode(100000L, 999999L); - LocalCacheUtils.setVerifyCodeCache( - emailSendDTO.getOperationType() + "_" + emailSendDTO.getEmail(), randomVerifyCode); - Boolean result = Boolean.FALSE; - switch (authenticationOperationTypeEnum) { - case LOGIN: - result = SendEmailUtil.send(emailSendDTO.getEmail(), null, - SendEmailUtil.LOGIN_TEMPLATE_ID, randomVerifyCode); - break; - case FORGET_PWD: - result = SendEmailUtil.send(emailSendDTO.getEmail(), null, - SendEmailUtil.UPDATE_PWD_TEMPLATE_ID, randomVerifyCode); - break; - case EXCEPTION_IP: - result = SendEmailUtil.send(emailSendDTO.getEmail(), emailSendDTO.getIp(), - SendEmailUtil.EXCEPTION_ID_TEMPLATE_ID, randomVerifyCode); - break; - case BIND_MAILBOX: - result = SendEmailUtil.send(emailSendDTO.getEmail(), null, - SendEmailUtil.BIND_MAILBOX_TEMPLATE_ID, randomVerifyCode); - break; - default: - } - if (!result) { - throw new BusinessException("failed.to.send.mail"); - } - return Boolean.TRUE; - } - - @Override - public Boolean logout(AccountLogoutDTO accountLogoutDTO) { - //jwt本身失效比较难做 统一用缓存实现 删除缓存就失效 - String token = LocalCacheUtils.getTokenCache(String.valueOf(accountLogoutDTO.getUserId())); - if (StringUtils.isNotBlank(token)) { - LocalCacheUtils.delTokenCache(String.valueOf(accountLogoutDTO.getUserId())); - } - return Boolean.TRUE; - } - - @Override - public Boolean isLogin(AccountLogoutDTO accountLogoutDTO) { - String token = LocalCacheUtils.getTokenCache(String.valueOf(accountLogoutDTO.getUserId())); - if (StringUtils.isNotBlank(token)) { - return Boolean.TRUE; - } - return Boolean.FALSE; - } - - @Override - public Boolean addUser(AccountAddDTO accountAddDTO) { - Account account; - account = CopyUtil.copyObject(accountAddDTO,Account.class); -// account.setUserEmail(accountAddDTO.getUserEmail()); -// account.setUserName(accountAddDTO.getUserName()); -// account.setIsTrial(accountAddDTO.getIsTrial()); - account.setValidStartTime(Long.valueOf(accountAddDTO.getValidStartTime())); - account.setValidEndTime(toDayEnd(Long.parseLong(accountAddDTO.getValidEndTime()))); - account.setUserPassword("Third-000000"); - account.setLanguage(Language.ENGLISH.name()); - account.setCreateDate(new Date()); - account.setIsTrial(0); - account.setIsBeginner(1); - return accountMapper.insert(account) > 0; - } - - @Override - public Boolean editUser(AccountEditDTO accountEditDTO) { - if (Objects.isNull(accountEditDTO) || ObjectUtils.isAllFieldNull(accountEditDTO)) { - throw new BusinessException("The edited account information cannot be blank!"); - } - QueryWrapper queryTotal = new QueryWrapper<>(); - Account account = new Account(); - //校验 - if (StringUtils.isNotBlank(accountEditDTO.getNewEmail())) { - Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldEmail()), "oldEmail cannot be empty!"); - queryTotal.eq("user_email", accountEditDTO.getOldEmail()); - Account accountSelect = accountMapper.selectOne(queryTotal); - Assert.notNull(accountSelect, "oldEmail does not exist!"); - - account.setUserEmail(accountEditDTO.getNewEmail()); - } - if (StringUtils.isNotBlank(accountEditDTO.getNewUserName())) { - Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldUserName()), "oldUserName cannot be empty!"); - queryTotal.eq("user_name", accountEditDTO.getOldUserName()); - Account accountSelect = accountMapper.selectOne(queryTotal); - Assert.notNull(accountSelect, "oldUserName does not exist!"); - - account.setUserName(accountEditDTO.getNewUserName()); - } - if (StringUtils.isNotBlank(accountEditDTO.getNewValidStartTime())) { - Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldUserName()), "oldUserName cannot be empty!"); - queryTotal.eq("user_name", accountEditDTO.getOldUserName()); - Account accountSelect = accountMapper.selectOne(queryTotal); - Assert.notNull(accountSelect, "oldUserName does not exist!"); - - account.setValidStartTime(Long.valueOf(accountEditDTO.getNewValidStartTime())); - } - if (StringUtils.isNotBlank(accountEditDTO.getNewValidEndTime())) { - Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldUserName()), "oldUserName cannot be empty!"); - queryTotal.eq("user_name", accountEditDTO.getOldUserName()); - Account accountSelect = accountMapper.selectOne(queryTotal); - Assert.notNull(accountSelect, "oldUserName does not exist!"); - - account.setValidEndTime(toDayEnd(Long.parseLong(accountEditDTO.getNewValidEndTime()))); - } - Account accountSelect = accountMapper.selectOne(queryTotal); - Assert.notNull(accountSelect, "oldAccount does not exist!"); - accountMapper.update(account, queryTotal); - return null; - } - - @Override - public String getUserLanguage() { - AuthPrincipalVo userInfo = UserContext.getUserHolder(); - return Language.valueOf(userInfo.getLanguage()).name(); - } - - @Override - public String changeUserLanguage(String language) { - AuthPrincipalVo userInfo = UserContext.getUserHolder(); - Account account = accountMapper.selectById(userInfo.getId()); - account.setLanguage(language); - accountMapper.updateById(account); - String accountToken = createAccountToken(account); - return accountToken; - } - - @Override - public Boolean trialUserLogout() { - AuthPrincipalVo userInfo = UserContext.getUserHolder(); - Account account = accountMapper.selectById(userInfo.getId()); - if (account.getIsTrial() != 1) { - throw new BusinessException("用户为正式用户"); - } - libraryService.deleteTrialData(userInfo.getId()); - userLikeGroupService.deleteTrialData(userInfo.getId()); - return Boolean.TRUE; - } - - @Override - public Boolean completeGuidance() { - AuthPrincipalVo userInfo = UserContext.getUserHolder(); - Account account = accountMapper.selectById(userInfo.getId()); - account.setIsBeginner(0); - accountMapper.updateById(account); - return Boolean.TRUE; - } - - @Override - public Boolean addTrialUser(AccountTrialDTO accountTrialDTO, HttpServletRequest request) { - // 获取用户申请试用IP - String ipAddress = RequestInfoUtil.getIpAddress(request); - boolean link = false; - if (StringUtils.isNotBlank(accountTrialDTO.getRef())) { - link = true; - } - // 先检测试用订单 - QueryWrapper trialOrderQueryWrapper = new QueryWrapper<>(); - trialOrderQueryWrapper.eq("BINARY email", accountTrialDTO.getEmail()); -// trialOrderQueryWrapper.lambda().eq(TrialOrder::getIp, ipAddress); -// trialOrderQueryWrapper.lambda().and(wrapper -> -// wrapper.eq(TrialOrder::getEmail, accountTrialDTO.getEmail()) -// .or() // OR -// .like(TrialOrder::getUserName, accountTrialDTO.getUserName())); - List trialOrders = trialOrderMapper.selectList(trialOrderQueryWrapper); - if (CollectionUtil.isNotEmpty(trialOrders)) { - throw new BusinessException("You have submitted a trial application, please wait for approval."); - } - // 先检测用户名和邮箱 - QueryWrapper qw = new QueryWrapper<>(); - qw.eq("BINARY user_email", accountTrialDTO.getEmail()); - List accountList = accountMapper.selectList(qw); - if (CollectionUtil.isNotEmpty(accountList) && !accountList.get(0).getSystemUser().equals(0)) { - if (accountList.get(0).getIsTrial() == 1) { - throw new BusinessException("The email has already been registered", ResultEnum.PROMPT.getCode()); - } else { - Account account = accountList.get(0); - if (null == account.getValidEndTime() || account.getValidEndTime() > System.currentTimeMillis()) { - throw new BusinessException("The email has already been registered", ResultEnum.PROMPT.getCode()); - } - } - } - // 接收到数据后要形成一条使用订单信息 - TrialOrder trialOrder = CopyUtil.copyObject(accountTrialDTO, TrialOrder.class); - trialOrder.setCreateTime(LocalDateTime.now()); - trialOrder.setStatus(0); - trialOrder.setIp(ipAddress); - trialOrderMapper.insert(trialOrder); -// SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,1); -// SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,1); -// SendEmailUtil.sendCustomEmail("kaicpang.pang@connect.polyu.hk", null, trialOrder,1); - // 判断当前的试用订单是否自动批准 - if (AutoApproved.getStatus()) { - // 改变试用订单状态,新增试用用户 - trialOrder.setStatus(1); - trialOrder.setUpdateTime(LocalDateTime.now()); - trialOrderMapper.updateById(trialOrder); - Account account = new Account(); - if (CollectionUtil.isNotEmpty(accountList)) { - account = CopyUtil.copyObject(accountList.get(0), Account.class); - account.setIsTrial(1); - account.setIsBeginner(1); - account.setSystemUser(3); - account.setValidStartTime(System.currentTimeMillis()); - if (link) { - account.setValidEndTime(toDayEnd(Instant.now().plus(14, ChronoUnit.DAYS).toEpochMilli())); - } else { - account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); - } - accountMapper.updateById(account); - } else { - account.setUserName(trialOrder.getUserName()); - account.setUserPassword("Third-000000"); - account.setUserEmail(trialOrder.getEmail()); - account.setLanguage(Language.ENGLISH.name()); - account.setValidStartTime(System.currentTimeMillis()); - if (link) { - account.setValidEndTime(toDayEnd(Instant.now().plus(14, ChronoUnit.DAYS).toEpochMilli())); - } else { - account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); - } - account.setCreateDate(new Date()); - account.setIsTrial(1); - account.setIsBeginner(1); - account.setSystemUser(3); - account.setCredits(BigDecimal.valueOf(100)); - accountMapper.insert(account); - } - // 发送邮件提醒用户试用用户已创建 -// SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,2); -// SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,2); -// SendEmailUtil.sendCustomEmail("kaicpang.pang@connect.polyu.hk", null, trialOrder,2); - if (trialOrder.getCountry().equals("China")) { - SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), link); - } else { - SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), link); - } - } - return Boolean.TRUE; - } - - @Override - public IPage trialOrderList(TrialOrderDTO trialOrderDTO) { - QueryWrapper qw = new QueryWrapper<>(); - qw.lambda().eq(trialOrderDTO.getStatus() != null, TrialOrder::getStatus, trialOrderDTO.getStatus()); - return trialOrderMapper.selectPage(new Page<>(trialOrderDTO.getPage(), trialOrderDTO.getSize()), qw); - } - - @Override - public Boolean trialOrderApproval(List ids) { - for (Long id : ids) { - TrialOrder trialOrder = trialOrderMapper.selectById(id); - trialOrder.setStatus(1); - trialOrder.setUpdateTime(LocalDateTime.now()); - trialOrderMapper.updateById(trialOrder); - - QueryWrapper qw = new QueryWrapper<>(); - qw.eq("BINARY user_email", trialOrder.getEmail()); - List accountList = accountMapper.selectList(qw); - - Account account = new Account(); - if (CollectionUtil.isNotEmpty(accountList)) { - account = CopyUtil.copyObject(accountList.get(0), Account.class); - account.setIsTrial(1); - account.setIsBeginner(1); - account.setValidStartTime(System.currentTimeMillis()); - account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); - accountMapper.updateById(account); - } else { - account.setUserName(trialOrder.getUserName()); - account.setUserPassword("Third-000000"); - account.setUserEmail(trialOrder.getEmail()); - account.setLanguage(Language.ENGLISH.name()); - account.setValidStartTime(System.currentTimeMillis()); - account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); - account.setCreateDate(new Date()); - account.setIsTrial(1); - account.setIsBeginner(1); - account.setSystemUser(1); - accountMapper.insert(account); - } - // 发送邮件提醒用户试用用户已创建 -// SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,2, trialOrder.getCountry()); -// SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,2, trialOrder.getCountry()); -// SendEmailUtil.sendCustomEmail("kaicpang.pang@connect.polyu.hk", null, trialOrder,2, trialOrder.getCountry()); - if (trialOrder.getCountry().equals("China")) { - SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), false); - } else { - SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), false); - } - } - return Boolean.TRUE; - } - - @Override - public Boolean getIsAutoApproval() { - return AutoApproved.getStatus(); - } - - @Override - public Boolean switchIsAutoApproval() { - AutoApproved.setStatus(!AutoApproved.getStatus()); - return Boolean.TRUE; - } - - @Override - public Boolean trialOrderRefuse(List ids) { - for (Long id : ids) { - TrialOrder trialOrder = trialOrderMapper.selectById(id); - trialOrder.setStatus(2); - trialOrder.setUpdateTime(LocalDateTime.now()); - trialOrderMapper.updateById(trialOrder); - } - return Boolean.TRUE; - } - - @Override - public Long getExpiredTime() { - AuthPrincipalVo userInfo = UserContext.getUserHolder(); - return accountMapper.selectById(userInfo.getId()).getValidEndTime(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean addNoLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO) { - // 构建查询条件,查找已注册的账户数量 - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().isNotNull(Account::getBrowserIdentifiers); - queryWrapper.lambda().like(Account::getUserName, "PolyU-SFT-"); - List existingAccounts = accountMapper.selectList(queryWrapper); - - // 检查注册账户数量是否超过限制 - if (existingAccounts.size() >= 100) { - throw new BusinessException("The number of registered accounts exceeds the limit"); - } - - // 检查浏览器标识是否已经被注册 - queryWrapper.clear(); - queryWrapper.lambda().eq(Account::getBrowserIdentifiers, noLoginRequiredDTO.getBrowserIdentifiers()); - if (!accountMapper.selectList(queryWrapper).isEmpty()) { - throw new BusinessException("This browser has already been registered"); - } - - // 创建新账户 - Account newAccount = new Account(); - newAccount.setUserName("PolyU-SFT-" + String.format("%03d", existingAccounts.size() + 1)); - newAccount.setUserPassword("Third-000000"); - newAccount.setValidStartTime(System.currentTimeMillis()); - newAccount.setValidEndTime(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000); - newAccount.setCreateDate(new Date()); - newAccount.setIsBeginner(1); - newAccount.setIsTrial(0); - newAccount.setBrowserIdentifiers(noLoginRequiredDTO.getBrowserIdentifiers()); - newAccount.setLanguage(Language.ENGLISH.name()); - - // 插入新账户 - newAccount.setSystemUser(1); - accountMapper.insert(newAccount); - - return Boolean.TRUE; - } - - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean deleteNoLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO) { - // 删除将被注销的用户 - QueryWrapper queryWrapperDelete = new QueryWrapper<>(); - queryWrapperDelete.lambda().eq(Account::getBrowserIdentifiers, noLoginRequiredDTO.getBrowserIdentifiers()); - List accountList = accountMapper.selectList(queryWrapperDelete); - if (CollectionUtil.isNotEmpty(accountList)) { - Account accountDelete = accountList.get(0); - String userName = accountDelete.getUserName(); - // 查询当前浏览器标识下的所有用户,并按照用户名编号降序排序 - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().isNotNull(Account::getBrowserIdentifiers); - queryWrapper.lambda().orderByDesc(Account::getUserName); - List accounts = accountMapper.selectList(queryWrapper); - - // 如果存在用户,将将被注销的用户的浏览器标识更新为用户名编号最大的用户的浏览器标识 - if (!accounts.isEmpty()) { - Account userToBeUpdate = accounts.get(0); - //jwt本身失效比较难做 统一用缓存实现 删除缓存就失效 - String token = LocalCacheUtils.getTokenCache(String.valueOf(accountDelete.getId())); - if (StringUtils.isNotBlank(token)) { - LocalCacheUtils.delTokenCache(String.valueOf(accountDelete.getId())); - } - if (!userName.equals(userToBeUpdate.getUserName())) { - accountMapper.deleteById(accountDelete); - userToBeUpdate.setUserName(userName); - accountMapper.updateById(userToBeUpdate); - } else { - accountMapper.deleteById(accountDelete); - } - } - } - - return Boolean.TRUE; - } - - - @Override - public AccountLoginVO noLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { - String id = noLoginRequiredDTO.getId(); - if (!isStringInRange(id)) { - throw new BusinessException("Illegal serial number!"); - } - // 获取真实 IP 地址,考虑了经过代理的情况 - String ipAddress = request.getHeader("X-Forwarded-For"); - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("WL-Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getRemoteAddr(); - } - String browserIdentifiers = ipAddress + "," + id; - QueryWrapper qw = new QueryWrapper<>(); - qw.lambda().eq(Account::getUserName, "PolyU-SFT-" + id); - qw.lambda().eq(Account::getBrowserIdentifiers, browserIdentifiers); - List accountList = accountMapper.selectList(qw); - if (CollectionUtil.isEmpty(accountList)) { - throw new BusinessException("Machine not registered or machine identification has changed, login free has failed, please contact us at help@aida.com.hk."); - } - Account account = accountList.get(0); - AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); - String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); - if (StringUtils.isNotBlank(token)) { - //用户已登入 - response.setToken(token); - } else { - response.setToken(createAccountToken(account)); - } - response.setUserId(account.getId()); - return response; - } - - @Override - public Boolean existNoLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { - String id = noLoginRequiredDTO.getId(); - // 获取真实 IP 地址,考虑了经过代理的情况 - String ipAddress = request.getHeader("X-Forwarded-For"); - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("WL-Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getRemoteAddr(); - } - String browserIdentifiers = ipAddress + "," + id; - QueryWrapper qw = new QueryWrapper<>(); - qw.lambda().eq(Account::getUserName, "PolyU-SFT-" + id); - List accountList = accountMapper.selectList(qw); - if (!CollectionUtil.isEmpty(accountList)) { - throw new BusinessException(""); - } - return Boolean.TRUE; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public String addNoLoginRequiredNew(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { - // 验证机房注册序列号(001-100) - String id = noLoginRequiredDTO.getId(); - if (!isStringInRange(id)) { - throw new BusinessException("Illegal serial number."); - } - // 获取真实 IP 地址,考虑了经过代理的情况 - String ipAddress = request.getHeader("X-Forwarded-For"); - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("WL-Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getRemoteAddr(); - } - String browserIdentifiers = ipAddress + "," + id; - // 构建查询条件,查找已注册的账户数量 - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().eq(Account::getUserName, "PolyU-SFT-" + id); -// queryWrapper.lambda().eq(Account::getBrowserIdentifiers, browserIdentifiers); - List existingAccounts = accountMapper.selectList(queryWrapper); - - // 检查序列号是否被注册 - if (CollectionUtil.isNotEmpty(existingAccounts)) { - throw new BusinessException("The serial number has already been registered."); - } - - // 检查机器是否已经注册了别的序列号 - queryWrapper.clear(); - queryWrapper.lambda().like(Account::getBrowserIdentifiers, ipAddress); - List accountList = accountMapper.selectList(queryWrapper); - if (CollectionUtil.isNotEmpty(accountList)) { - throw new BusinessException("This machine has already been registered with serial number " + accountList.get(0).getUserName().split("-")[2]); - } - - // 创建新账户 - Account newAccount = new Account(); - newAccount.setUserName("PolyU-SFT-" + id); - newAccount.setUserPassword("Third-000000"); - newAccount.setValidStartTime(System.currentTimeMillis()); - newAccount.setValidEndTime(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000); - newAccount.setCreateDate(new Date()); - newAccount.setIsBeginner(1); - newAccount.setIsTrial(0); - newAccount.setBrowserIdentifiers(browserIdentifiers); - newAccount.setLanguage(Language.ENGLISH.name()); - - // 插入新账户 - newAccount.setSystemUser(1); - accountMapper.insert(newAccount); - - return "\n" + - "                        \n" + - "                        \n" + - "                            \n" + - "                            \n" + - "                            Document\n" + - " \n" + - "                        \n" + - "                        \n" + - "                        \n" + - "                            \n" + - "                        "; - } - - public static boolean isStringInRange(String input) { - // 去除字符串两端的空格 - input = input.trim(); - - // 使用正则表达式检查是否是三位数字 - if (input.matches("\\d{3}")) { - // 将字符串转换为整数 - int number = Integer.parseInt(input); - - // 检查是否在指定范围内 - return number >= 1 && number <= 100; - } - - return false; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean deleteNoLoginRequiredNew(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { - // 获取真实 IP 地址,考虑了经过代理的情况 - String ipAddress = request.getHeader("X-Forwarded-For"); - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("WL-Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getRemoteAddr(); - } - // 删除将被注销的用户 - QueryWrapper queryWrapperDelete = new QueryWrapper<>(); - if (StringUtils.isNotBlank(noLoginRequiredDTO.getId()) && noLoginRequiredDTO.getDeleteById()) { - // 验证机房注册序列号(001-100) - String id = noLoginRequiredDTO.getId(); - if (!isStringInRange(id)) { - throw new BusinessException("Illegal serial number."); - } - queryWrapperDelete.lambda().eq(Account::getUserName, "PolyU-SFT-" + noLoginRequiredDTO.getId()); - } else { - queryWrapperDelete.lambda().like(Account::getBrowserIdentifiers, ipAddress); - } - List accountList = accountMapper.selectList(queryWrapperDelete); - if (CollectionUtil.isNotEmpty(accountList)) { - for (Account account : accountList) { - //jwt本身失效比较难做 统一用缓存实现 删除缓存就失效 - String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); - if (StringUtils.isNotBlank(token)) { - LocalCacheUtils.delTokenCache(String.valueOf(account.getId())); - } - accountMapper.deleteById(account.getId()); - // TODO:注销时删除用户数据,workspace,like,library等 - } - } - return Boolean.TRUE; - } - - @Override - public void upgradeNotification() { -// QueryWrapper queryWrapper = new QueryWrapper<>(); -//// queryWrapper.eq("id", 88L); -// queryWrapper.and(wrapper -> -// wrapper.gt("valid_end_time", 1720540799000L) -// .or().isNull("valid_end_time")) -// .isNotNull("user_email"); - - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lt("valid_end_time", 1720540799000L); - - List accountList = accountMapper.selectList(queryWrapper); - System.out.println(accountList); - int i = 0; - for (Account account : accountList) { -// SendEmailUtil.sendUpgradeNotification(account, null, 0); -// SendEmailUtil.sendUpgradeNotification(account, null, 1); - if (i > 6) { - if (account.getLanguage().equals(Language.CHINESE_SIMPLIFIED.name())) { - SendEmailUtil.sendUpgradeNotification(account, null, 0); - } else { - // 英文 - SendEmailUtil.sendUpgradeNotification(account, null, 1); - } - } - i ++; - } - } - - @Override - public void moveLibraryDate() { - // 查询生产全部library数据,遍历数据,根据用户id和md5查询是否已经迁移过 - - // 未迁移过的进行迁移,注意模特数据迁移打点信息以及转换模特格式 - } - - public void updateCredits(Long accountId, String value) { - Account account = new Account(); - account.setId(accountId); - account.setCredits(new BigDecimal(value)); - accountMapper.updateById(account); - } - // todo 将其与上一个合并 - public void updateCreditsAndEndTime(Long accountId, String value, Long endTime) { - Account account = new Account(); - account.setId(accountId); - account.setCredits(new BigDecimal(value)); - account.setValidEndTime(toDayEnd(endTime)); - accountMapper.updateById(account); - } - - @Override - public Boolean designWorksRegister(AccountDesignWorksRegisterDTO accountDesignWorksRegisterDTO) { - QueryWrapper qw = new QueryWrapper<>(); - qw.eq("BINARY user_email", accountDesignWorksRegisterDTO.getUserEmail()); - List accountList = accountMapper.selectList(qw); - if (CollectionUtil.isNotEmpty(accountList)) { - throw new BusinessException("The email has already been registered"); - } - - String randomVerifyCode = RandomsUtil.generateVerifyCode(100000L, 999999L); - LocalCacheUtils.setVerifyCodeCache("DesignWorksRegister" + "_" + accountDesignWorksRegisterDTO.getUserEmail(), randomVerifyCode); - - Boolean b = SendEmailUtil.designWorksRegister(accountDesignWorksRegisterDTO.getUserEmail(), randomVerifyCode); - if (!b) { - throw new BusinessException("failed.to.send.mail"); - } - return Boolean.TRUE; - } - - @Override - public AccountLoginVO designWorksRegisterCode(AccountDesignWorksRegisterDTO accountDesignWorksRegisterDTO) { - - String verifyCode = LocalCacheUtils.getVerifyCodeCache("DesignWorksRegister" + "_" + accountDesignWorksRegisterDTO.getUserEmail()); - if (StringUtils.isBlank(verifyCode)) { - throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); - } - if (!verifyCode.equals(accountDesignWorksRegisterDTO.getEmailVerifyCode())) { - throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); - } - Account account = CopyUtil.copyObject(accountDesignWorksRegisterDTO, Account.class); - account.setSystemUser(0); - if (StringUtils.isBlank(accountDesignWorksRegisterDTO.getLanguage())) { - account.setLanguage(Language.ENGLISH.name()); - } - account.setIsTrial(1); - account.setIsBeginner(1); - account.setCreateDate(new Date()); - account.setCredits(BigDecimal.valueOf(100)); - accountMapper.insert(account); - AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); - response.setEmail(account.getUserEmail()); - String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); - if (StringUtils.isNotBlank(token)) { - //用户已登入 - response.setToken(token); - } else { - response.setToken(createAccountToken(account)); - } - response.setUserId(account.getId()); - response.setSystemUser(account.getSystemUser()); - return response; - } - - private static final String QUERY_ORDER = "SELECT * FROM pmr_wc_order_stats " + - "WHERE status = 'wc-processing' AND date_paid > '2024-06-20 00:00:00'" + - " ORDER BY order_id DESC "; - - private static final String QUERY_CUSTOMER_EMAIL = "SELECT username, email, country FROM pmr_wc_customer_lookup " + - "WHERE customer_id = ? "; - private static final String UPDATE_ORDER_STATUS = "UPDATE pmr_wc_order_stats " + - "SET status = 'wc-complete' , date_completed = ? " + - "WHERE order_id = ?"; - - private static final DataSource dataSource; - - static { - HikariConfig config = new HikariConfig(); - config.setJdbcUrl("jdbc:mysql://code-create.com.hk:3306/db1nfvsgmjp3b8"); - config.setUsername("uafqtz4gsvfrw"); - config.setPassword("aida123456."); -// config.setJdbcUrl("jdbc:mysql://localhost:3306/code-create-local?serverTimezone=UTC"); -// config.setUsername("root"); -// config.setPassword("root"); - config.addDataSourceProperty("cachePrepStmts", "true"); - config.addDataSourceProperty("prepStmtCacheSize", "250"); - config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); - config.addDataSourceProperty("maxLifetime", 300000); - dataSource = new HikariDataSource(config); - } - - /** - * 为Code-Create的用户延长有效期 - * - * @return null - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean extendValidityForCC() { - try (Connection connection = dataSource.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement(QUERY_ORDER)) { -// preparedStatement.setString(1, "someCondition"); - try (ResultSet queryOrderResultSet = preparedStatement.executeQuery()) { - while (queryOrderResultSet.next()) { - /* 处理结果集 */ - int orderId = queryOrderResultSet.getInt("order_id"); - int customerId = queryOrderResultSet.getInt("customer_id"); - double totalSales = queryOrderResultSet.getDouble("total_sales"); - log.info("Code-Create 订单:{}, 顾客id:{}, 付款金额:{}",orderId, customerId, totalSales); - String email = ""; - String userName = ""; - // 为什么一般没有值 - String country = "English"; - // 1、查pmr_wc_customer_lookup表;确认当前订单对应的用户邮箱 - PreparedStatement preparedQueryEmail = connection.prepareStatement(QUERY_CUSTOMER_EMAIL); - preparedQueryEmail.setInt(1, customerId); - try (ResultSet queryEmailResultSet = preparedQueryEmail.executeQuery()) { - if (queryEmailResultSet.next()) { - email = queryEmailResultSet.getString("email"); - userName = queryEmailResultSet.getString("username"); - country = queryEmailResultSet.getString("country"); - } else { - log.error("未知错误。code-create的用户表中没有付费用户的信息"); - throw new BusinessException("user info missing"); - } - } - - // 2、查t_account表中是否有该用户 - // 2.1 没有 新建用户 - Account userInfo = null; - Long validEndTime = null; - // 标志当前用户是不是新用户 - Boolean flag = Boolean.FALSE; - try { - // 不是新用户 直接延长使用期限 - userInfo = getAccountByEmail(email); - } catch (BusinessException e) { - // 通过邮箱找不到用户 说明是新用户 => 创建用户 - flag = Boolean.TRUE; - } - if (!Objects.isNull(userInfo) && !Objects.isNull(userInfo.getValidEndTime())) - validEndTime = userInfo.getValidEndTime(); - - // 2、获取当前续费费用能延长多长时间 - Account account = extendValidity(validEndTime, totalSales); - - int systemUserType = 0; - - // 不管是不是新用户 都要更新用户角色和积分 - String credits = "0"; - if (totalSales == 5000.0){ - log.info("年付用户,初始积分6000"); - credits = CreditsEventsEnum.INIT_MONTHLY.getValue(); - systemUserType = 1; - }else if (totalSales == 500.0){ - log.info("月付用户,初始积分5000"); - credits = CreditsEventsEnum.INIT_MONTHLY.getValue(); - systemUserType = 2; - }else if (totalSales == 0.0){ - log.info("测试用户,初始积分10"); - credits = "10"; - systemUserType = 3; - } - if (flag) { - // 是新用户 => 新增一条数据 - Boolean b = addUser(new AccountAddDTO(email, - StringUtil.isNullOrEmpty(userName) ? email.substring(0, email.indexOf("@")) : userName, - country, - account.getValidStartTime().toString(), - account.getValidEndTime().toString(), 0,new BigDecimal(credits),systemUserType)); - if (b) log.info("付费新用户 {} 新增成功!", email); - } else { - userInfo.setValidEndTime(toDayEnd(account.getValidEndTime())); - userInfo.setCredits(new BigDecimal(credits)); - userInfo.setSystemUser(systemUserType); - baseMapper.updateById(userInfo); - log.info("付费用户 {} 续订成功", email); - } - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String format = simpleDateFormat.format(account.getValidEndTime()); - - // 3、邮件通知 - SendEmailUtil.notificationForPaidUser(email, flag ? 1 : 2, country, - StringUtil.isNullOrEmpty(userName) ? email.substring(0, email.indexOf("@")) : userName, format); - - // 4、更新订单状态和日期 - PreparedStatement preparedUpdateOrder = connection.prepareStatement(UPDATE_ORDER_STATUS); - LocalDateTime localDateTime = LocalDateTime.now(); - String currentTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - - preparedUpdateOrder.setString(1, currentTime); - preparedUpdateOrder.setInt(2, orderId); - int row = preparedUpdateOrder.executeUpdate(); - if (row == 1) log.info("表 pmr_wc_order_stats 订单状态更新成功"); - - - } - } - } catch (Exception e) { - // 记录异常并处理 - e.printStackTrace(); - return Boolean.FALSE; - } - - return Boolean.TRUE; - } - - private Account extendValidity(Long validEndTime, double totalSales) { - Instant specifiedInstant; - Account account = new Account(); - long epochMilli = Instant.now().toEpochMilli(); - if (!Objects.isNull(validEndTime) && validEndTime > epochMilli) { - // 将 Unix 毫秒级时间戳转换为 Instant - specifiedInstant = Instant.ofEpochMilli(validEndTime); - } else { - specifiedInstant = Instant.now(); - account.setValidStartTime(specifiedInstant.toEpochMilli()); - } - - // 指定时区 - ZoneId zoneId = ZoneId.of("Asia/Shanghai"); - // 将 Instant 转换为 ZonedDateTime,使用指定时区 - ZonedDateTime specifiedDateTime = ZonedDateTime.ofInstant(specifiedInstant, zoneId); - ZonedDateTime validityExtension; - if (totalSales == 500) { - // 一个月 - validityExtension = specifiedDateTime.plusMonths(1); - } else if (totalSales == 5000) { - // 一年 - validityExtension = specifiedDateTime.plusYears(1); - } else { - // 测试 一天 - validityExtension = specifiedDateTime.plusDays(1); - } - // 获取一个月之后的时间的 Unix 毫秒级时间戳 - account.setValidEndTime(toDayEnd(validityExtension.toInstant().toEpochMilli())); - return account; - } - - private static final String QUERY_MAXIMUM_USERID = "SELECT MAX(ID) AS max_id FROM pmr_users;"; - - private static final String QUERY_NEW_USER_EMAIL = "SELECT user_email FROM pmr_users " + - "WHERE ID > ? "; - - @Value("${redis.key.maximumUserId}") - private String maximumUserIdKey; - - /** - * 将Code-Create上注册的用户添加为AiDA的游客 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public void registerUserToVisitor(){ - ArrayList newUserEmails = new ArrayList<>(); - long maxUserId = CommonConstant.MAXIMUM_USER_ID; - try (Connection connection = dataSource.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement(QUERY_MAXIMUM_USERID)) { - try (ResultSet queryOrderResultSet = preparedStatement.executeQuery()) { - while (queryOrderResultSet.next()) { - // 获取最新的最大用户id - maxUserId = queryOrderResultSet.getLong("max_id"); - // 获取历史最大用户id - long maxUserIdHistory = StringUtil.isNullOrEmpty(redisUtil.getFromString(maximumUserIdKey)) ? CommonConstant.MAXIMUM_USER_ID : Long.parseLong(redisUtil.getFromString(maximumUserIdKey)); - if (maxUserId > maxUserIdHistory){ - // 查出新增用户的邮箱 - PreparedStatement newUserEmail = connection.prepareStatement(QUERY_NEW_USER_EMAIL); - // 填充参数 - 历史最大用户ID - newUserEmail.setLong(1, maxUserIdHistory); - try (ResultSet queryEmailResultSet = newUserEmail.executeQuery()) { - if (queryEmailResultSet.next()) { - String email = queryEmailResultSet.getString("user_email"); - newUserEmails.add(email); - } /*else { - log.error("未知错误。code-create的用户表中没有付费用户的信息"); - throw new BusinessException("user info missing"); - }*/ - } - } - } - } - } catch (Exception e) { - // 记录异常并处理 - e.printStackTrace(); -// return null; - } - - if (!newUserEmails.isEmpty()){ - // 查询这些邮箱在aida上是否有账号 - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("user_email", newUserEmails).select("user_email"); - - List collect = baseMapper.selectList(queryWrapper).stream().map(Account::getUserEmail).collect(Collectors.toList()); - if (!collect.isEmpty()){ - // 移除Code-Create新增用户中在AiDA已有账号的邮箱 - newUserEmails.removeAll(collect); - } - // 将新增用户添加到AiDA,身份为游客 - if (!newUserEmails.isEmpty()){ - newUserEmails.forEach(email -> { - Account account = new Account(); - account.setUserEmail(email); - account.setUserName(email); - account.setUserPassword("Third-000000"); - account.setLanguage(Language.ENGLISH.name()); - account.setCreateDate(new Date()); - account.setIsTrial(0); - account.setIsBeginner(1); - account.setCredits(new BigDecimal(0)); - account.setSystemUser(0); - baseMapper.insert(account); - // 邮件通知用户 - SendEmailUtil.notificationForRegisterUser(email); - }); - } - // 记录当前最大的用户id - redisUtil.addToString(maximumUserIdKey, String.valueOf(maxUserId)); - } - } - - // 收集调查问卷的信息 - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean collectQuestionnaires(String questionnaireInfo) { - log.info("调查问卷详细信息:{}", questionnaireInfo); - QuestionnaireVO questionnaireVO = JSON.parseObject(questionnaireInfo, QuestionnaireVO.class); - String email = questionnaireVO.getEmail(); - // 1、通过邮箱判断当前用户有无系统账号 - Account account; - try { - account = getOneByEmail(email); - } catch (BusinessException e) { - log.info(e.getMessage()); - log.warn("当前用户 {} 在AiDA中没有账号", email); - throw new BusinessException("user.has.no.account",ResultEnum.PROMPT.getCode()); - } - // 2、先判断当前用户是否已经填写过问卷 - CreditsDetail record = creditsService.getByAccountIdAndChangeEvent(account.getId(), "Fill out the questionnaire", "+100"); - if (!Objects.isNull(record)) { - log.info("当前用户 {} 已经填写过问卷", email); - throw new BusinessException("questionnaire.filled.out", ResultEnum.PROMPT.getCode()); - } - - // 3.1、将问卷信息存储到数据库 - Questionnaire questionnaire = new Questionnaire(); - questionnaire.setQuestionnaireInfo(questionnaireInfo); - questionnaire.setTitle("AiDA_3.0 Feedback Survey--06/2024"); - questionnaire.setCreateTime(LocalDateTime.now()); - int insert = questionnaireMapper.insert(questionnaire); - - if (insert == 1) { - // 3.2、更新 t_credits_detail表 - CreditsDetail creditsDetail = new CreditsDetail(); - creditsDetail.setAccountId(account.getId()); - creditsDetail.setChangeEvent("Fill out the questionnaire"); - creditsDetail.setChangedCredits("+100"); - BigDecimal added = account.getCredits().add(new BigDecimal("100")); - creditsDetail.setCredits(added); - creditsDetail.setCreateTime(LocalDateTime.now()); - creditsService.save(creditsDetail); - - // 3.3、更新 t_account 表 - if (account.getValidEndTime() != null && account.getValidEndTime() < 1720972799000L){ - updateCreditsAndEndTime(account.getId(), added.toString(), 1720972799000L); - } - } - - // 4、发邮件 区分中英文 - SendEmailUtil.questionnaireRelatedNotify(questionnaireVO.getUserName(), email, questionnaireVO.getLanguage()); - return Boolean.TRUE; - } - - /** - * 为年费用户每月更新积分 - */ - public void refreshCreditsWeekly(){ - UpdateWrapper accountUpdateWrapper = new UpdateWrapper<>(); - // 刷新账号有效期截止之前的年付用户的积分 - long epochMilli = Instant.now().toEpochMilli(); - accountUpdateWrapper.lambda().set(Account::getCredits, CreditsEventsEnum.INIT_WEEKLY.getValue()) - .eq(Account::getSystemUser,1).or().eq(Account::getSystemUser,2) - .gt(Account::getValidEndTime, epochMilli); - baseMapper.update(null,accountUpdateWrapper); - } - - @Override - public String getActivityBenefits(){ - Long id = UserContext.getUserHolder().getId(); - // 1、 判断用户的身份 正式用户 无福利 - Account account = baseMapper.selectById(id); - Integer systemUser = account.getSystemUser(); - Instant now = Instant.now(); - ZoneId zoneId = ZoneId.of("Asia/Shanghai"); - ZonedDateTime specifiedDateTime; - if (systemUser.equals(1)){ - long validEndTime = Objects.isNull(account.getValidEndTime()) ? now.toEpochMilli() : account.getValidEndTime(); - specifiedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(validEndTime), zoneId); - account.setValidEndTime(toDayEnd(specifiedDateTime.plusDays(30).toInstant().toEpochMilli())); - - }else if (systemUser.equals(4)){ - throw new BusinessException("You have participated in the event", 1); - }else if (systemUser.equals(0) || systemUser.equals(3)){ - // 2、赋予游客或试用用户 以正式用户的权限 即 积分置为6000,有效期30天 - // 将 Instant 转换为 ZonedDateTime,使用指定时区 - specifiedDateTime = ZonedDateTime.ofInstant(now, zoneId); - account.setIsTrial(0); - account.setSystemUser(4); - account.setCredits(BigDecimal.valueOf(6000)); - account.setValidStartTime(now.toEpochMilli()); - account.setValidEndTime(toDayEnd(specifiedDateTime.plusDays(30).toInstant().toEpochMilli())); - } - - account.setUpdateDate(new Date()); - baseMapper.updateById(account); - - return "参与成功"; - - } - // 将指定unix时间置为当天的23:59:59 - public long toDayEnd(long unixTimestampMillis){ - // 将UNIX时间戳转换为LocalDateTime对象 - LocalDateTime dateTime = Instant.ofEpochMilli(unixTimestampMillis) - .atZone(ZoneId.systemDefault()) - .toLocalDateTime(); - - // 获取日期部分并设置时间为23:59:59 - LocalDate date = dateTime.toLocalDate(); - LocalDateTime endOfDay = date.atTime(LocalTime.of(23, 59, 59)); - - // 将LocalDateTime对象转换为UNIX时间戳(以毫秒为单位) 北京时间 - return endOfDay.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); - } - - /** - * 获取指定身份过期用户 - * @param systemUserNum - * @return - */ - public List getExpiredUserBySystemUser(Integer systemUserNum){ - QueryWrapper queryWrapper = new QueryWrapper<>(); - long now = Instant.now().toEpochMilli(); - queryWrapper.eq("system_user", systemUserNum) - .isNotNull("valid_end_time") - .lt("valid_end_time", now); - - return baseMapper.selectList(queryWrapper); - } - - public void toVisitor(Account account){ - accountMapper.toVisitor(account.getId(), new Date()); - } - - public List setUserValidToDayEnd(){ - // 获取当前未过期的用户,并将其有效期设置为过期当日的23:59:59 - QueryWrapper queryWrapper = new QueryWrapper<>(); - long now = Instant.now().toEpochMilli(); - queryWrapper.isNotNull("valid_end_time").gt("valid_end_time", now); - List accounts = baseMapper.selectList(queryWrapper); - ArrayList ids = new ArrayList<>(); - - for (Account account: accounts) { - account.setValidEndTime(toDayEnd(account.getValidEndTime())); - ids.add(account.getId()); - updateById(account); - } - - return ids; - } - - public IPage getPageByDateAndUserType(String startTime, String endTime, Integer type, int pageNum, int size){ - QueryWrapper queryWrapper = new QueryWrapper<>(); - setTimeAndSystemUser(queryWrapper,startTime, endTime, type); - - Page accountPage = new Page<>(pageNum, size); - return baseMapper.selectPage(accountPage, queryWrapper); - } - - private void setTimeAndSystemUser(QueryWrapper queryWrapper, String startTime, String endTime, Integer type){ - queryWrapper.gt("create_date", startTime).lt("create_date",endTime); - - if (!Objects.isNull(type)){ - switch (type){ - case 0: - // 游客 - queryWrapper.eq("system_user", 0); - break; - case 1: - queryWrapper.eq("system_user", 1); - break; - case 2: - queryWrapper.eq("system_user", 2); - break; - case 3: - // 试用用户 - queryWrapper.eq("system_user", 3).or().eq("system_user", 4); - break; - - } - } - } - - public Map getByDateAndUserType(String startTime, String endTime, Integer type){ - QueryWrapper queryWrapper = new QueryWrapper<>(); - setTimeAndSystemUser(queryWrapper,startTime, endTime, type); - queryWrapper.groupBy("system_user"); - - queryWrapper.select("system_user as type, count(id) as count"); - List> maps = baseMapper.selectMaps(queryWrapper); - return maps.stream() - .collect(Collectors.toMap( - map -> map.get("type").toString(), - map -> Objects.isNull(map.get("count")) ? 0L : (Long) map.get("count"))); - } - - public IPage getPageByIds(List ids, int pageNum, int size){ - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", ids); - - return baseMapper.selectPage(new Page<>(pageNum, size), queryWrapper); - } - - public List getByIds(List ids){ - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("id", ids); - - return baseMapper.selectList(queryWrapper); - } - - public String uploadAvatar(MultipartFile file){ - Long accountId = UserContext.getUserHolder().getId(); - // 1、上传图片到minio - String avatarPath = minioUtil.upload(userBucket, accountId.toString() + "/avatar", file); - // 2、查询该用户之前的头像 - String avatar = baseMapper.selectById(accountId).getAvatar(); - if (!StringUtil.isNullOrEmpty(avatar) && !avatar.equals(CommonConstant.DEFAULT_AVATAR)){ - minioUtil.deleteObject(avatar); - } - - // 3、替换新的头像 - Account account = new Account(); - account.setId(accountId); - account.setAvatar(avatarPath); - baseMapper.updateById(account); - - return minioUtil.getPreSignedUrl(avatarPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME); - } - - public PersonalHomepageVO getPersonalHomepage(Long accountId){ - // 需要返回 用户头像 用户名 作品总量 粉丝量 关注量 主页访问量 当前用户是否被查看者关注 - Long currentUserId = UserContext.getUserHolder().getId(); - PersonalHomepageVO personalHomepageVO = new PersonalHomepageVO(); - - Account account = baseMapper.selectById(accountId); - personalHomepageVO.setUserName(account.getUserName()); - String avatar = StringUtil.isNullOrEmpty(account.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : account.getAvatar(); - personalHomepageVO.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); - - personalHomepageVO.setPortfolioCount(portfolioService.getPortfolioCount(accountId)); - personalHomepageVO.setFolloweeCount(portfolioService.getFolloweeCount(accountId)); - personalHomepageVO.setFollowerCount(portfolioService.getFollowerCount(accountId)); - personalHomepageVO.setHomepageViewCount(viewPersonalHomepageCount(0L)); - - - if (accountId.equals(currentUserId)){ - personalHomepageVO.setIsFollow(0); - Long viewCount = viewPersonalHomepageCount(accountId); - // 只有本人才能看到个人主页浏览量 - personalHomepageVO.setHomepageViewCount(viewCount == null ? 0 : viewCount); - }else { - personalHomepageVO.setIsFollow(portfolioService.getIfFollowed(accountId, currentUserId)); - // 非本人浏览主页时增加浏览量 - viewsIncrease(accountId); - } - return personalHomepageVO; - } - - @Override - public Boolean viewsIncrease(Long id) { - redisUtil.increasePersonalHomepageViewCount(id); - return Boolean.TRUE; - } - - private Long viewPersonalHomepageCount(Long accountId) { - redisUtil.getPersonalHomepageViewCount(accountId); - return null; - } - -} +package com.ai.da.service.impl; + +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.AuthenticationOperationTypeEnum; +import com.ai.da.common.enums.CreditsEventsEnum; +import com.ai.da.common.enums.LoginTypeEnum; +import com.ai.da.common.response.ResultEnum; +import com.ai.da.common.security.jwt.JWTTokenHelper; +import com.ai.da.common.utils.*; +import com.ai.da.mapper.primary.AccountMapper; +import com.ai.da.mapper.primary.QuestionnaireMapper; +import com.ai.da.mapper.primary.TrialOrderMapper; +import com.ai.da.mapper.primary.entity.*; +import com.ai.da.model.dto.*; +import com.ai.da.model.enums.AutoApproved; +import com.ai.da.model.enums.Language; +import com.ai.da.model.vo.*; +import com.ai.da.service.*; +import com.alibaba.fastjson.JSON; +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.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import io.netty.util.internal.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.text.SimpleDateFormat; +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 服务实现类 + * + * @author easy-generator + * @since 2022-07-06 + */ +@Slf4j +@Service +public class AccountServiceImpl extends ServiceImpl implements AccountService { + @Resource + private AccountMapper accountMapper; + + @Resource + private JWTTokenHelper jwtTokenHelper; + + @Resource + private AccountLoginLogService accountLoginLogService; + + @Resource + private LibraryService libraryService; + + @Resource + private UserLikeGroupService userLikeGroupService; + + @Resource + private TrialOrderMapper trialOrderMapper; + + @Resource + private QuestionnaireMapper questionnaireMapper; + + @Resource + private CreditsService creditsService; + + @Resource + private MinioUtil minioUtil; + + @Value("${minio.bucketName.users}") + private String userBucket; + + @Resource + private RedisUtil redisUtil; + + @Override + @Transactional(rollbackFor = Exception.class) + public AccountPreLoginVO preLogin(AccountPreLoginDTO accountDTO) { + log.info("aida预先登入accountDTO###{}", JSON.toJSONString(accountDTO)); + Account account = getOneByEmail(accountDTO.getEmail()); + //用户有效期校验 + validateUserValidaExpire(account); + if ("Third-000000".equals(account.getUserPassword())) { + account.setUserPassword(accountDTO.getPassword()); + accountMapper.updateById(account); + } else { + if (!account.getUserPassword().equals(accountDTO.getPassword())) { + throw new BusinessException("password.error", ResultEnum.PROMPT.getCode()); + } + } + /*发送邮件*/ + AuthenticationOperationTypeEnum authenticationOperationTypeEnum = AuthenticationOperationTypeEnum.of(accountDTO.getOperationType()); + log.info(account.getUserEmail()); + log.info(accountDTO.getEmail()); + if (!account.getUserEmail().equals(accountDTO.getEmail())) { + throw new BusinessException("email.error", ResultEnum.PROMPT.getCode()); + } + if (Objects.isNull(authenticationOperationTypeEnum)) { + throw new BusinessException("unknown.authentication.operation.type"); + } + String randomVerifyCode = RandomsUtil.generateVerifyCode(100000L, 999999L); + LocalCacheUtils.setVerifyCodeCache( + accountDTO.getOperationType() + "_" + accountDTO.getEmail(), randomVerifyCode); + Boolean result = Boolean.FALSE; + switch (authenticationOperationTypeEnum) { + case LOGIN: + result = SendEmailUtil.send(accountDTO.getEmail(), null, + SendEmailUtil.LOGIN_TEMPLATE_ID, randomVerifyCode); + break; + case FORGET_PWD: + result = SendEmailUtil.send(accountDTO.getEmail(), null, + SendEmailUtil.UPDATE_PWD_TEMPLATE_ID, randomVerifyCode); + break; + case EXCEPTION_IP: + result = SendEmailUtil.send(accountDTO.getEmail(), accountDTO.getIp(), + SendEmailUtil.EXCEPTION_ID_TEMPLATE_ID, randomVerifyCode); + break; + case BIND_MAILBOX: + result = SendEmailUtil.send(accountDTO.getEmail(), null, + SendEmailUtil.BIND_MAILBOX_TEMPLATE_ID, randomVerifyCode); + break; + default: + } + if (!result) { + throw new BusinessException("failed.to.send.mail"); + } + return new AccountPreLoginVO(account.getId()); + } + + @Resource + private PortfolioService portfolioService; + + @Transactional(rollbackFor = Exception.class) + @Override + public AccountLoginVO login(AccountLoginDTO accountLoginDTO, HttpServletRequest request) { +// Assert.isTrue(StringUtils.isNotBlank(accountLoginDTO.getEmail()), "Please input a email !"); +// Assert.isTrue(StringUtils.isNotBlank(accountLoginDTO.getEmailVerifyCode()), "Please input the email verification code !"); + log.info("aida确认登入###accountLoginDTO###{}", JSON.toJSONString(accountLoginDTO)); + Account accountExist = getOneByEmail(accountLoginDTO.getEmail().trim()); + LoginTypeEnum accountType = LoginTypeEnum.of(accountLoginDTO.getLoginType()); + if (Objects.isNull(accountType)) { + throw new BusinessException("unknown.login.type"); + } + if (!accountType.equals(LoginTypeEnum.EMAIL)) { + throw new BusinessException("error.login.type"); + } + //用户有效期校验 + validateUserValidaExpire(accountExist); + + Account account = null; + switch (accountType) { + case PASSWORD: +// Assert.isTrue(StringUtils.isNotBlank(accountLoginDTO.getPassword()), "Please input a password !"); +// account = getOneByUserName(accountLoginDTO.getUserName()); +// Assert.isTrue(Objects.nonNull(account), "User does not exist!"); +// Assert.isTrue(account.getUserPassword().equals(accountLoginDTO.getPassword()), "Password error !"); + // 走不到这边 + break; + case EMAIL: + account = getOneByEmail(accountLoginDTO.getEmail().trim()); + //校验邮箱验证码 + String verifyCode = LocalCacheUtils.getVerifyCodeCache(AuthenticationOperationTypeEnum.LOGIN.name() + "_" + accountLoginDTO.getEmail()); + if (StringUtils.isBlank(verifyCode)) { + throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); + } + if (!"921314".equals(accountLoginDTO.getEmailVerifyCode())) { + if (!verifyCode.equals(accountLoginDTO.getEmailVerifyCode())) { + throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); + } + } + break; + default: + } + AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); + response.setEmail(account.getUserEmail()); + String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); + if (StringUtils.isNotBlank(token)) { + //用户已登入 + response.setToken(token); + } else { + response.setToken(createAccountToken(account)); + } + response.setUserId(account.getId()); + response.setSystemUser(account.getSystemUser()); + // 设置头像 + String avatar; + if (StringUtil.isNullOrEmpty(account.getAvatar())){ + avatar = CommonConstant.DEFAULT_AVATAR; + }else { + avatar = account.getAvatar(); + } + response.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + response.setFolloweeCount(portfolioService.getFolloweeCount(account.getId())); + response.setFollowerCount(portfolioService.getFollowerCount(account.getId())); + //判断是否常用ip 不是则发邮件提示 + calculateExceptionIp(RequestInfoUtil.getIpAddress(request), account); + return response; + } + + private void validateUserValidaExpire(Account account) { + Long currentTime = new Date().getTime(); + if (Objects.nonNull(account.getValidStartTime())) { + if (currentTime < account.getValidStartTime()) { + throw new BusinessException("user.expired"); + } + } + if (Objects.nonNull(account.getValidEndTime())) { + if (currentTime > account.getValidEndTime()) { + throw new BusinessException("user.expired"); + } + } + } + + private void calculateExceptionIp(String ip, Account account) { + //必须先绑定邮箱才可以发有异常ip邮件提醒 + if (StringUtils.isNotBlank(account.getUserEmail())) { + List accountLoginLogs = accountLoginLogService.getByUserId(account.getId()); + if (CollectionUtil.isNotEmpty(accountLoginLogs)) { + List existIps = accountLoginLogs.stream().map(AccountLoginLog::getIp).collect(Collectors.toList()); + if (!existIps.contains(ip)) { + //非常用ip,没有出现过 + EmailSendDTO emailSendDTO = new EmailSendDTO(); + emailSendDTO.setEmail(account.getUserEmail()); + emailSendDTO.setOperationType(AuthenticationOperationTypeEnum.EXCEPTION_IP.name()); + emailSendDTO.setIp(ip); + sendEmail(emailSendDTO); + } + } + } + //保存登入日志 + accountLoginLogService.saveLoginLog(ip, account.getId()); + } + + private String createAccountToken(Account account) { + AuthPrincipalVo principal = new AuthPrincipalVo(); + principal.setId(account.getId()); + principal.setUsername(account.getUserName()); + principal.setLanguage(account.getLanguage()); + principal.setCountry(account.getCountry()); + String token2 = jwtTokenHelper.createToken(principal); + LocalCacheUtils.setTokenCache(String.valueOf(account.getId()), token2); + return token2; + } + + @Override + public Boolean bindEmail(AccountBindEmailDTO accountBindEmailDTO) { + Account account = baseMapper.selectById(accountBindEmailDTO.getUserId()); + if (Objects.isNull(account)) { + throw new BusinessException("userName.does.not.exist", ResultEnum.PROMPT.getCode()); + } + if (StringUtils.isNotBlank(account.getUserEmail())) { + throw new BusinessException("user.has.bound.mailbox"); + } + //校验邮箱验证码 + String verifyCode = LocalCacheUtils.getVerifyCodeCache(AuthenticationOperationTypeEnum.BIND_MAILBOX.name() + "_" + accountBindEmailDTO.getUserEmail()); + if (StringUtils.isBlank(verifyCode)) { + throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); + } + if (!verifyCode.equals(accountBindEmailDTO.getEmailVerifyCode())) { + throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); + } + //绑定 + updatePwdByUserId(accountBindEmailDTO.getUserEmail(), accountBindEmailDTO.getUserId()); + return Boolean.TRUE; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Boolean forgetPwd(AccountRegisterDTO accountDTO) { +// Account emailAccount = getOneByEmail(accountDTO.getEmail()); + //校验邮箱验证码 + if (accountDTO.getVerifyEmail()) { + String verifyCode = LocalCacheUtils.getVerifyCodeCache(AuthenticationOperationTypeEnum.FORGET_PWD.name() + "_" + accountDTO.getEmail()); + if (StringUtils.isBlank(verifyCode)) { + throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); + } + if (!verifyCode.equals(accountDTO.getEmailVerifyCode())) { + throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); + } + } else { + updatePwdByEmail(accountDTO.getPassword(), accountDTO.getEmail()); + } + return Boolean.TRUE; + } + + private void updatePwdByEmail(String pwd, String email) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().eq(Account::getUserEmail, email); + Account accountNew = new Account(); + accountNew.setUserPassword(pwd); + accountMapper.update(accountNew, queryWrapper); + } + + private void updatePwdByUserId(String email, Long userId) { + Account accountNew = new Account(); + accountNew.setUserEmail(email); + accountNew.setId(userId); + accountMapper.updateById(accountNew); + } + + + private Account getOneByEmail(String email) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("BINARY user_email", email); + List accountList = accountMapper.selectList(queryWrapper); + if (CollectionUtil.isEmpty(accountList)) { + throw new BusinessException("email.does.not.exist", ResultEnum.PROMPT.getCode()); + } + return accountList.get(0); + } + + private Account getByEmailIgnoreCase(String email) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_email", email); + List accountList = accountMapper.selectList(queryWrapper); + if (CollectionUtil.isEmpty(accountList)) { + throw new BusinessException("email.does.not.exist", ResultEnum.PROMPT.getCode()); + } + return accountList.get(0); + } + + private Account getOneByUserName(String userName) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().eq(Account::getUserName, userName); + queryWrapper.lambda().last("limit 1"); + List accountList = accountMapper.selectList(queryWrapper); + if (CollectionUtil.isEmpty(accountList)) { + throw new BusinessException("userName.does.not.exist", ResultEnum.PROMPT.getCode()); + } + return accountList.get(0); + } + + private Account getOneByUserId(Long userId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id", userId); + return accountMapper.selectOne(queryWrapper); + } + + + @Override + public Boolean sendEmail(EmailSendDTO emailSendDTO) { + AuthenticationOperationTypeEnum authenticationOperationTypeEnum = AuthenticationOperationTypeEnum.of(emailSendDTO.getOperationType()); + if (Objects.isNull(authenticationOperationTypeEnum)) { + throw new BusinessException("unknown.authentication.operation.type"); + } + Account emailAccount = getOneByEmail(emailSendDTO.getEmail()); + String randomVerifyCode = RandomsUtil.generateVerifyCode(100000L, 999999L); + LocalCacheUtils.setVerifyCodeCache( + emailSendDTO.getOperationType() + "_" + emailSendDTO.getEmail(), randomVerifyCode); + Boolean result = Boolean.FALSE; + switch (authenticationOperationTypeEnum) { + case LOGIN: + result = SendEmailUtil.send(emailSendDTO.getEmail(), null, + SendEmailUtil.LOGIN_TEMPLATE_ID, randomVerifyCode); + break; + case FORGET_PWD: + result = SendEmailUtil.send(emailSendDTO.getEmail(), null, + SendEmailUtil.UPDATE_PWD_TEMPLATE_ID, randomVerifyCode); + break; + case EXCEPTION_IP: + result = SendEmailUtil.send(emailSendDTO.getEmail(), emailSendDTO.getIp(), + SendEmailUtil.EXCEPTION_ID_TEMPLATE_ID, randomVerifyCode); + break; + case BIND_MAILBOX: + result = SendEmailUtil.send(emailSendDTO.getEmail(), null, + SendEmailUtil.BIND_MAILBOX_TEMPLATE_ID, randomVerifyCode); + break; + default: + } + if (!result) { + throw new BusinessException("failed.to.send.mail"); + } + return Boolean.TRUE; + } + + @Override + public Boolean logout(AccountLogoutDTO accountLogoutDTO) { + //jwt本身失效比较难做 统一用缓存实现 删除缓存就失效 + String token = LocalCacheUtils.getTokenCache(String.valueOf(accountLogoutDTO.getUserId())); + if (StringUtils.isNotBlank(token)) { + LocalCacheUtils.delTokenCache(String.valueOf(accountLogoutDTO.getUserId())); + } + return Boolean.TRUE; + } + + @Override + public Boolean isLogin(AccountLogoutDTO accountLogoutDTO) { + String token = LocalCacheUtils.getTokenCache(String.valueOf(accountLogoutDTO.getUserId())); + if (StringUtils.isNotBlank(token)) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + @Override + public Boolean addUser(AccountAddDTO accountAddDTO) { + Account account; + account = CopyUtil.copyObject(accountAddDTO,Account.class); +// account.setUserEmail(accountAddDTO.getUserEmail()); +// account.setUserName(accountAddDTO.getUserName()); +// account.setIsTrial(accountAddDTO.getIsTrial()); + account.setValidStartTime(Long.valueOf(accountAddDTO.getValidStartTime())); + account.setValidEndTime(toDayEnd(Long.parseLong(accountAddDTO.getValidEndTime()))); + account.setUserPassword("Third-000000"); + account.setLanguage(Language.ENGLISH.name()); + account.setCreateDate(new Date()); + account.setIsTrial(0); + account.setIsBeginner(1); + return accountMapper.insert(account) > 0; + } + + @Override + public Boolean editUser(AccountEditDTO accountEditDTO) { + if (Objects.isNull(accountEditDTO) || ObjectUtils.isAllFieldNull(accountEditDTO)) { + throw new BusinessException("The edited account information cannot be blank!"); + } + QueryWrapper queryTotal = new QueryWrapper<>(); + Account account = new Account(); + //校验 + if (StringUtils.isNotBlank(accountEditDTO.getNewEmail())) { + Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldEmail()), "oldEmail cannot be empty!"); + queryTotal.eq("user_email", accountEditDTO.getOldEmail()); + Account accountSelect = accountMapper.selectOne(queryTotal); + Assert.notNull(accountSelect, "oldEmail does not exist!"); + + account.setUserEmail(accountEditDTO.getNewEmail()); + } + if (StringUtils.isNotBlank(accountEditDTO.getNewUserName())) { + Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldUserName()), "oldUserName cannot be empty!"); + queryTotal.eq("user_name", accountEditDTO.getOldUserName()); + Account accountSelect = accountMapper.selectOne(queryTotal); + Assert.notNull(accountSelect, "oldUserName does not exist!"); + + account.setUserName(accountEditDTO.getNewUserName()); + } + if (StringUtils.isNotBlank(accountEditDTO.getNewValidStartTime())) { + Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldUserName()), "oldUserName cannot be empty!"); + queryTotal.eq("user_name", accountEditDTO.getOldUserName()); + Account accountSelect = accountMapper.selectOne(queryTotal); + Assert.notNull(accountSelect, "oldUserName does not exist!"); + + account.setValidStartTime(Long.valueOf(accountEditDTO.getNewValidStartTime())); + } + if (StringUtils.isNotBlank(accountEditDTO.getNewValidEndTime())) { + Assert.isTrue(StringUtils.isNotBlank(accountEditDTO.getOldUserName()), "oldUserName cannot be empty!"); + queryTotal.eq("user_name", accountEditDTO.getOldUserName()); + Account accountSelect = accountMapper.selectOne(queryTotal); + Assert.notNull(accountSelect, "oldUserName does not exist!"); + + account.setValidEndTime(toDayEnd(Long.parseLong(accountEditDTO.getNewValidEndTime()))); + } + Account accountSelect = accountMapper.selectOne(queryTotal); + Assert.notNull(accountSelect, "oldAccount does not exist!"); + accountMapper.update(account, queryTotal); + return null; + } + + @Override + public String getUserLanguage() { + AuthPrincipalVo userInfo = UserContext.getUserHolder(); + return Language.valueOf(userInfo.getLanguage()).name(); + } + + @Override + public String changeUserLanguage(String language) { + AuthPrincipalVo userInfo = UserContext.getUserHolder(); + Account account = accountMapper.selectById(userInfo.getId()); + account.setLanguage(language); + accountMapper.updateById(account); + String accountToken = createAccountToken(account); + return accountToken; + } + + @Override + public Boolean trialUserLogout() { + AuthPrincipalVo userInfo = UserContext.getUserHolder(); + Account account = accountMapper.selectById(userInfo.getId()); + if (account.getIsTrial() != 1) { + throw new BusinessException("用户为正式用户"); + } + libraryService.deleteTrialData(userInfo.getId()); + userLikeGroupService.deleteTrialData(userInfo.getId()); + return Boolean.TRUE; + } + + @Override + public Boolean completeGuidance() { + AuthPrincipalVo userInfo = UserContext.getUserHolder(); + Account account = accountMapper.selectById(userInfo.getId()); + account.setIsBeginner(0); + accountMapper.updateById(account); + return Boolean.TRUE; + } + + @Override + public Boolean addTrialUser(AccountTrialDTO accountTrialDTO, HttpServletRequest request) { + // 获取用户申请试用IP + String ipAddress = RequestInfoUtil.getIpAddress(request); + boolean link = false; + if (StringUtils.isNotBlank(accountTrialDTO.getRef())) { + link = true; + } + // 先检测试用订单 + QueryWrapper trialOrderQueryWrapper = new QueryWrapper<>(); + trialOrderQueryWrapper.eq("BINARY email", accountTrialDTO.getEmail()); +// trialOrderQueryWrapper.lambda().eq(TrialOrder::getIp, ipAddress); +// trialOrderQueryWrapper.lambda().and(wrapper -> +// wrapper.eq(TrialOrder::getEmail, accountTrialDTO.getEmail()) +// .or() // OR +// .like(TrialOrder::getUserName, accountTrialDTO.getUserName())); + List trialOrders = trialOrderMapper.selectList(trialOrderQueryWrapper); + if (CollectionUtil.isNotEmpty(trialOrders)) { + throw new BusinessException("You have submitted a trial application, please wait for approval."); + } + // 先检测用户名和邮箱 + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("BINARY user_email", accountTrialDTO.getEmail()); + List accountList = accountMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(accountList) && !accountList.get(0).getSystemUser().equals(0)) { + if (accountList.get(0).getIsTrial() == 1) { + throw new BusinessException("The email has already been registered", ResultEnum.PROMPT.getCode()); + } else { + Account account = accountList.get(0); + if (null == account.getValidEndTime() || account.getValidEndTime() > System.currentTimeMillis()) { + throw new BusinessException("The email has already been registered", ResultEnum.PROMPT.getCode()); + } + } + } + // 接收到数据后要形成一条使用订单信息 + TrialOrder trialOrder = CopyUtil.copyObject(accountTrialDTO, TrialOrder.class); + trialOrder.setCreateTime(LocalDateTime.now()); + trialOrder.setStatus(0); + trialOrder.setIp(ipAddress); + trialOrderMapper.insert(trialOrder); +// SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,1); +// SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,1); +// SendEmailUtil.sendCustomEmail("kaicpang.pang@connect.polyu.hk", null, trialOrder,1); + // 判断当前的试用订单是否自动批准 + if (AutoApproved.getStatus()) { + // 改变试用订单状态,新增试用用户 + trialOrder.setStatus(1); + trialOrder.setUpdateTime(LocalDateTime.now()); + trialOrderMapper.updateById(trialOrder); + Account account = new Account(); + if (CollectionUtil.isNotEmpty(accountList)) { + account = CopyUtil.copyObject(accountList.get(0), Account.class); + account.setIsTrial(1); + account.setIsBeginner(1); + account.setSystemUser(3); + account.setValidStartTime(System.currentTimeMillis()); + if (link) { + account.setValidEndTime(toDayEnd(Instant.now().plus(14, ChronoUnit.DAYS).toEpochMilli())); + } else { + account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); + } + accountMapper.updateById(account); + } else { + account.setUserName(trialOrder.getUserName()); + account.setUserPassword("Third-000000"); + account.setUserEmail(trialOrder.getEmail()); + account.setLanguage(Language.ENGLISH.name()); + account.setValidStartTime(System.currentTimeMillis()); + if (link) { + account.setValidEndTime(toDayEnd(Instant.now().plus(14, ChronoUnit.DAYS).toEpochMilli())); + } else { + account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); + } + account.setCreateDate(new Date()); + account.setIsTrial(1); + account.setIsBeginner(1); + account.setSystemUser(3); + account.setCredits(BigDecimal.valueOf(100)); + accountMapper.insert(account); + } + // 发送邮件提醒用户试用用户已创建 +// SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,2); +// SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,2); +// SendEmailUtil.sendCustomEmail("kaicpang.pang@connect.polyu.hk", null, trialOrder,2); + if (trialOrder.getCountry().equals("China")) { + SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), link); + } else { + SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), link); + } + } + return Boolean.TRUE; + } + + @Override + public IPage trialOrderList(TrialOrderDTO trialOrderDTO) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(trialOrderDTO.getStatus() != null, TrialOrder::getStatus, trialOrderDTO.getStatus()); + return trialOrderMapper.selectPage(new Page<>(trialOrderDTO.getPage(), trialOrderDTO.getSize()), qw); + } + + @Override + public Boolean trialOrderApproval(List ids) { + for (Long id : ids) { + TrialOrder trialOrder = trialOrderMapper.selectById(id); + trialOrder.setStatus(1); + trialOrder.setUpdateTime(LocalDateTime.now()); + trialOrderMapper.updateById(trialOrder); + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("BINARY user_email", trialOrder.getEmail()); + List accountList = accountMapper.selectList(qw); + + Account account = new Account(); + if (CollectionUtil.isNotEmpty(accountList)) { + account = CopyUtil.copyObject(accountList.get(0), Account.class); + account.setIsTrial(1); + account.setIsBeginner(1); + account.setValidStartTime(System.currentTimeMillis()); + account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); + accountMapper.updateById(account); + } else { + account.setUserName(trialOrder.getUserName()); + account.setUserPassword("Third-000000"); + account.setUserEmail(trialOrder.getEmail()); + account.setLanguage(Language.ENGLISH.name()); + account.setValidStartTime(System.currentTimeMillis()); + account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); + account.setCreateDate(new Date()); + account.setIsTrial(1); + account.setIsBeginner(1); + account.setSystemUser(1); + accountMapper.insert(account); + } + // 发送邮件提醒用户试用用户已创建 +// SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,2, trialOrder.getCountry()); +// SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,2, trialOrder.getCountry()); +// SendEmailUtil.sendCustomEmail("kaicpang.pang@connect.polyu.hk", null, trialOrder,2, trialOrder.getCountry()); + if (trialOrder.getCountry().equals("China")) { + SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), false); + } else { + SendEmailUtil.sendCustomEmail(account.getUserEmail(), null, trialOrder, 3, trialOrder.getCountry(), false); + } + } + return Boolean.TRUE; + } + + @Override + public Boolean getIsAutoApproval() { + return AutoApproved.getStatus(); + } + + @Override + public Boolean switchIsAutoApproval() { + AutoApproved.setStatus(!AutoApproved.getStatus()); + return Boolean.TRUE; + } + + @Override + public Boolean trialOrderRefuse(List ids) { + for (Long id : ids) { + TrialOrder trialOrder = trialOrderMapper.selectById(id); + trialOrder.setStatus(2); + trialOrder.setUpdateTime(LocalDateTime.now()); + trialOrderMapper.updateById(trialOrder); + } + return Boolean.TRUE; + } + + @Override + public Long getExpiredTime() { + AuthPrincipalVo userInfo = UserContext.getUserHolder(); + return accountMapper.selectById(userInfo.getId()).getValidEndTime(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean addNoLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO) { + // 构建查询条件,查找已注册的账户数量 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().isNotNull(Account::getBrowserIdentifiers); + queryWrapper.lambda().like(Account::getUserName, "PolyU-SFT-"); + List existingAccounts = accountMapper.selectList(queryWrapper); + + // 检查注册账户数量是否超过限制 + if (existingAccounts.size() >= 100) { + throw new BusinessException("The number of registered accounts exceeds the limit"); + } + + // 检查浏览器标识是否已经被注册 + queryWrapper.clear(); + queryWrapper.lambda().eq(Account::getBrowserIdentifiers, noLoginRequiredDTO.getBrowserIdentifiers()); + if (!accountMapper.selectList(queryWrapper).isEmpty()) { + throw new BusinessException("This browser has already been registered"); + } + + // 创建新账户 + Account newAccount = new Account(); + newAccount.setUserName("PolyU-SFT-" + String.format("%03d", existingAccounts.size() + 1)); + newAccount.setUserPassword("Third-000000"); + newAccount.setValidStartTime(System.currentTimeMillis()); + newAccount.setValidEndTime(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000); + newAccount.setCreateDate(new Date()); + newAccount.setIsBeginner(1); + newAccount.setIsTrial(0); + newAccount.setBrowserIdentifiers(noLoginRequiredDTO.getBrowserIdentifiers()); + newAccount.setLanguage(Language.ENGLISH.name()); + + // 插入新账户 + newAccount.setSystemUser(1); + accountMapper.insert(newAccount); + + return Boolean.TRUE; + } + + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteNoLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO) { + // 删除将被注销的用户 + QueryWrapper queryWrapperDelete = new QueryWrapper<>(); + queryWrapperDelete.lambda().eq(Account::getBrowserIdentifiers, noLoginRequiredDTO.getBrowserIdentifiers()); + List accountList = accountMapper.selectList(queryWrapperDelete); + if (CollectionUtil.isNotEmpty(accountList)) { + Account accountDelete = accountList.get(0); + String userName = accountDelete.getUserName(); + // 查询当前浏览器标识下的所有用户,并按照用户名编号降序排序 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().isNotNull(Account::getBrowserIdentifiers); + queryWrapper.lambda().orderByDesc(Account::getUserName); + List accounts = accountMapper.selectList(queryWrapper); + + // 如果存在用户,将将被注销的用户的浏览器标识更新为用户名编号最大的用户的浏览器标识 + if (!accounts.isEmpty()) { + Account userToBeUpdate = accounts.get(0); + //jwt本身失效比较难做 统一用缓存实现 删除缓存就失效 + String token = LocalCacheUtils.getTokenCache(String.valueOf(accountDelete.getId())); + if (StringUtils.isNotBlank(token)) { + LocalCacheUtils.delTokenCache(String.valueOf(accountDelete.getId())); + } + if (!userName.equals(userToBeUpdate.getUserName())) { + accountMapper.deleteById(accountDelete); + userToBeUpdate.setUserName(userName); + accountMapper.updateById(userToBeUpdate); + } else { + accountMapper.deleteById(accountDelete); + } + } + } + + return Boolean.TRUE; + } + + + @Override + public AccountLoginVO noLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { + String id = noLoginRequiredDTO.getId(); + if (!isStringInRange(id)) { + throw new BusinessException("Illegal serial number!"); + } + // 获取真实 IP 地址,考虑了经过代理的情况 + String ipAddress = request.getHeader("X-Forwarded-For"); + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + } + String browserIdentifiers = ipAddress + "," + id; + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Account::getUserName, "PolyU-SFT-" + id); + qw.lambda().eq(Account::getBrowserIdentifiers, browserIdentifiers); + List accountList = accountMapper.selectList(qw); + if (CollectionUtil.isEmpty(accountList)) { + throw new BusinessException("Machine not registered or machine identification has changed, login free has failed, please contact us at help@aida.com.hk."); + } + Account account = accountList.get(0); + AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); + String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); + if (StringUtils.isNotBlank(token)) { + //用户已登入 + response.setToken(token); + } else { + response.setToken(createAccountToken(account)); + } + response.setUserId(account.getId()); + return response; + } + + @Override + public Boolean existNoLoginRequired(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { + String id = noLoginRequiredDTO.getId(); + // 获取真实 IP 地址,考虑了经过代理的情况 + String ipAddress = request.getHeader("X-Forwarded-For"); + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + } + String browserIdentifiers = ipAddress + "," + id; + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Account::getUserName, "PolyU-SFT-" + id); + List accountList = accountMapper.selectList(qw); + if (!CollectionUtil.isEmpty(accountList)) { + throw new BusinessException(""); + } + return Boolean.TRUE; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String addNoLoginRequiredNew(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { + // 验证机房注册序列号(001-100) + String id = noLoginRequiredDTO.getId(); + if (!isStringInRange(id)) { + throw new BusinessException("Illegal serial number."); + } + // 获取真实 IP 地址,考虑了经过代理的情况 + String ipAddress = request.getHeader("X-Forwarded-For"); + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + } + String browserIdentifiers = ipAddress + "," + id; + // 构建查询条件,查找已注册的账户数量 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().eq(Account::getUserName, "PolyU-SFT-" + id); +// queryWrapper.lambda().eq(Account::getBrowserIdentifiers, browserIdentifiers); + List existingAccounts = accountMapper.selectList(queryWrapper); + + // 检查序列号是否被注册 + if (CollectionUtil.isNotEmpty(existingAccounts)) { + throw new BusinessException("The serial number has already been registered."); + } + + // 检查机器是否已经注册了别的序列号 + queryWrapper.clear(); + queryWrapper.lambda().like(Account::getBrowserIdentifiers, ipAddress); + List accountList = accountMapper.selectList(queryWrapper); + if (CollectionUtil.isNotEmpty(accountList)) { + throw new BusinessException("This machine has already been registered with serial number " + accountList.get(0).getUserName().split("-")[2]); + } + + // 创建新账户 + Account newAccount = new Account(); + newAccount.setUserName("PolyU-SFT-" + id); + newAccount.setUserPassword("Third-000000"); + newAccount.setValidStartTime(System.currentTimeMillis()); + newAccount.setValidEndTime(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000); + newAccount.setCreateDate(new Date()); + newAccount.setIsBeginner(1); + newAccount.setIsTrial(0); + newAccount.setBrowserIdentifiers(browserIdentifiers); + newAccount.setLanguage(Language.ENGLISH.name()); + + // 插入新账户 + newAccount.setSystemUser(1); + accountMapper.insert(newAccount); + + return "\n" + + "                        \n" + + "                        \n" + + "                            \n" + + "                            \n" + + "                            Document\n" + + " \n" + + "                        \n" + + "                        \n" + + "                        \n" + + "                            \n" + + "                        "; + } + + public static boolean isStringInRange(String input) { + // 去除字符串两端的空格 + input = input.trim(); + + // 使用正则表达式检查是否是三位数字 + if (input.matches("\\d{3}")) { + // 将字符串转换为整数 + int number = Integer.parseInt(input); + + // 检查是否在指定范围内 + return number >= 1 && number <= 100; + } + + return false; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteNoLoginRequiredNew(NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) { + // 获取真实 IP 地址,考虑了经过代理的情况 + String ipAddress = request.getHeader("X-Forwarded-For"); + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + } + // 删除将被注销的用户 + QueryWrapper queryWrapperDelete = new QueryWrapper<>(); + if (StringUtils.isNotBlank(noLoginRequiredDTO.getId()) && noLoginRequiredDTO.getDeleteById()) { + // 验证机房注册序列号(001-100) + String id = noLoginRequiredDTO.getId(); + if (!isStringInRange(id)) { + throw new BusinessException("Illegal serial number."); + } + queryWrapperDelete.lambda().eq(Account::getUserName, "PolyU-SFT-" + noLoginRequiredDTO.getId()); + } else { + queryWrapperDelete.lambda().like(Account::getBrowserIdentifiers, ipAddress); + } + List accountList = accountMapper.selectList(queryWrapperDelete); + if (CollectionUtil.isNotEmpty(accountList)) { + for (Account account : accountList) { + //jwt本身失效比较难做 统一用缓存实现 删除缓存就失效 + String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); + if (StringUtils.isNotBlank(token)) { + LocalCacheUtils.delTokenCache(String.valueOf(account.getId())); + } + accountMapper.deleteById(account.getId()); + // TODO:注销时删除用户数据,workspace,like,library等 + } + } + return Boolean.TRUE; + } + + @Override + public void upgradeNotification() { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +//// queryWrapper.eq("id", 88L); +// queryWrapper.and(wrapper -> +// wrapper.gt("valid_end_time", 1720540799000L) +// .or().isNull("valid_end_time")) +// .isNotNull("user_email"); + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lt("valid_end_time", 1720540799000L); + + List accountList = accountMapper.selectList(queryWrapper); + System.out.println(accountList); + int i = 0; + for (Account account : accountList) { +// SendEmailUtil.sendUpgradeNotification(account, null, 0); +// SendEmailUtil.sendUpgradeNotification(account, null, 1); + if (i > 6) { + if (account.getLanguage().equals(Language.CHINESE_SIMPLIFIED.name())) { + SendEmailUtil.sendUpgradeNotification(account, null, 0); + } else { + // 英文 + SendEmailUtil.sendUpgradeNotification(account, null, 1); + } + } + i ++; + } + } + + @Override + public void moveLibraryDate() { + // 查询生产全部library数据,遍历数据,根据用户id和md5查询是否已经迁移过 + + // 未迁移过的进行迁移,注意模特数据迁移打点信息以及转换模特格式 + } + + public void updateCredits(Long accountId, String value) { + Account account = new Account(); + account.setId(accountId); + account.setCredits(new BigDecimal(value)); + accountMapper.updateById(account); + } + // todo 将其与上一个合并 + public void updateCreditsAndEndTime(Long accountId, String value, Long endTime) { + Account account = new Account(); + account.setId(accountId); + account.setCredits(new BigDecimal(value)); + account.setValidEndTime(toDayEnd(endTime)); + accountMapper.updateById(account); + } + + @Override + public Boolean designWorksRegister(AccountDesignWorksRegisterDTO accountDesignWorksRegisterDTO) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("BINARY user_email", accountDesignWorksRegisterDTO.getUserEmail()); + List accountList = accountMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(accountList)) { + throw new BusinessException("The email has already been registered"); + } + + String randomVerifyCode = RandomsUtil.generateVerifyCode(100000L, 999999L); + LocalCacheUtils.setVerifyCodeCache("DesignWorksRegister" + "_" + accountDesignWorksRegisterDTO.getUserEmail(), randomVerifyCode); + + Boolean b = SendEmailUtil.designWorksRegister(accountDesignWorksRegisterDTO.getUserEmail(), randomVerifyCode); + if (!b) { + throw new BusinessException("failed.to.send.mail"); + } + return Boolean.TRUE; + } + + @Override + public AccountLoginVO designWorksRegisterCode(AccountDesignWorksRegisterDTO accountDesignWorksRegisterDTO) { + + String verifyCode = LocalCacheUtils.getVerifyCodeCache("DesignWorksRegister" + "_" + accountDesignWorksRegisterDTO.getUserEmail()); + if (StringUtils.isBlank(verifyCode)) { + throw new BusinessException("the.verification.code.has.expired", ResultEnum.PROMPT.getCode()); + } + if (!verifyCode.equals(accountDesignWorksRegisterDTO.getEmailVerifyCode())) { + throw new BusinessException("verification.code.error", ResultEnum.PROMPT.getCode()); + } + Account account = CopyUtil.copyObject(accountDesignWorksRegisterDTO, Account.class); + account.setSystemUser(0); + if (StringUtils.isBlank(accountDesignWorksRegisterDTO.getLanguage())) { + account.setLanguage(Language.ENGLISH.name()); + } + account.setIsTrial(0); + account.setIsBeginner(1); + account.setValidStartTime(Instant.now().toEpochMilli()); + account.setCreateDate(new Date()); + account.setCredits(BigDecimal.valueOf(0)); + accountMapper.insert(account); + AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); + response.setEmail(account.getUserEmail()); + String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); + if (StringUtils.isNotBlank(token)) { + //用户已登入 + response.setToken(token); + } else { + response.setToken(createAccountToken(account)); + } + response.setUserId(account.getId()); + response.setSystemUser(account.getSystemUser()); + return response; + } + + private static final String QUERY_ORDER = "SELECT * FROM pmr_wc_order_stats " + + "WHERE status = 'wc-processing' AND date_paid > '2024-06-20 00:00:00'" + + " ORDER BY order_id DESC "; + + private static final String QUERY_CUSTOMER_EMAIL = "SELECT username, email, country FROM pmr_wc_customer_lookup " + + "WHERE customer_id = ? "; + private static final String UPDATE_ORDER_STATUS = "UPDATE pmr_wc_order_stats " + + "SET status = 'wc-complete' , date_completed = ? " + + "WHERE order_id = ?"; + + private static final DataSource dataSource; + + static { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql://code-create.com.hk:3306/db1nfvsgmjp3b8"); + config.setUsername("uafqtz4gsvfrw"); + config.setPassword("aida123456."); +// config.setJdbcUrl("jdbc:mysql://localhost:3306/code-create-local?serverTimezone=UTC"); +// config.setUsername("root"); +// config.setPassword("root"); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + config.addDataSourceProperty("maxLifetime", 300000); + dataSource = new HikariDataSource(config); + } + + /** + * 为Code-Create的用户延长有效期 + * + * @return null + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean extendValidityForCC() { + try (Connection connection = dataSource.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(QUERY_ORDER)) { +// preparedStatement.setString(1, "someCondition"); + try (ResultSet queryOrderResultSet = preparedStatement.executeQuery()) { + while (queryOrderResultSet.next()) { + /* 处理结果集 */ + int orderId = queryOrderResultSet.getInt("order_id"); + int customerId = queryOrderResultSet.getInt("customer_id"); + double totalSales = queryOrderResultSet.getDouble("total_sales"); + log.info("Code-Create 订单:{}, 顾客id:{}, 付款金额:{}",orderId, customerId, totalSales); + String email = ""; + String userName = ""; + // 为什么一般没有值 + String country = "English"; + // 1、查pmr_wc_customer_lookup表;确认当前订单对应的用户邮箱 + PreparedStatement preparedQueryEmail = connection.prepareStatement(QUERY_CUSTOMER_EMAIL); + preparedQueryEmail.setInt(1, customerId); + try (ResultSet queryEmailResultSet = preparedQueryEmail.executeQuery()) { + if (queryEmailResultSet.next()) { + email = queryEmailResultSet.getString("email"); + userName = queryEmailResultSet.getString("username"); + country = queryEmailResultSet.getString("country"); + } else { + log.error("未知错误。code-create的用户表中没有付费用户的信息"); + throw new BusinessException("user info missing"); + } + } + + // 2、查t_account表中是否有该用户 + // 2.1 没有 新建用户 + Account userInfo = null; + Long validEndTime = null; + // 标志当前用户是不是新用户 + Boolean flag = Boolean.FALSE; + try { + // 不是新用户 直接延长使用期限 + userInfo = getByEmailIgnoreCase(email); + } catch (BusinessException e) { + // 通过邮箱找不到用户 说明是新用户 => 创建用户 + flag = Boolean.TRUE; + } + if (!Objects.isNull(userInfo) && !Objects.isNull(userInfo.getValidEndTime())) + validEndTime = userInfo.getValidEndTime(); + + // 2、获取当前续费费用能延长多长时间 + Account account = extendValidity(validEndTime, totalSales); + + int systemUserType = 0; + + // 不管是不是新用户 都要更新用户角色和积分 + String credits = "0"; + if (totalSales == 5000.0){ + log.info("年付用户,初始积分6000"); + credits = CreditsEventsEnum.INIT_MONTHLY.getValue(); + systemUserType = 1; + }else if (totalSales == 500.0){ + log.info("月付用户,初始积分5000"); + credits = CreditsEventsEnum.INIT_MONTHLY.getValue(); + systemUserType = 2; + }else if (totalSales == 0.0){ + log.info("测试用户,初始积分10"); + credits = "10"; + systemUserType = 3; + } + if (flag) { + // 是新用户 => 新增一条数据 + Boolean b = addUser(new AccountAddDTO(email, + StringUtil.isNullOrEmpty(userName) ? email.substring(0, email.indexOf("@")) : userName, + country, + account.getValidStartTime().toString(), + account.getValidEndTime().toString(), 0,new BigDecimal(credits),systemUserType)); + if (b) log.info("付费新用户 {} 新增成功!", email); + } else { + userInfo.setValidEndTime(toDayEnd(account.getValidEndTime())); + userInfo.setCredits(new BigDecimal(credits)); + userInfo.setSystemUser(systemUserType); + baseMapper.updateById(userInfo); + log.info("付费用户 {} 续订成功", email); + } + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String format = simpleDateFormat.format(account.getValidEndTime()); + + // 3、邮件通知 + SendEmailUtil.notificationForPaidUser(email, flag ? 1 : 2, country, + StringUtil.isNullOrEmpty(userName) ? email.substring(0, email.indexOf("@")) : userName, format); + + // 4、更新订单状态和日期 + PreparedStatement preparedUpdateOrder = connection.prepareStatement(UPDATE_ORDER_STATUS); + LocalDateTime localDateTime = LocalDateTime.now(); + String currentTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + preparedUpdateOrder.setString(1, currentTime); + preparedUpdateOrder.setInt(2, orderId); + int row = preparedUpdateOrder.executeUpdate(); + if (row == 1) log.info("表 pmr_wc_order_stats 订单状态更新成功"); + + + } + } + } catch (Exception e) { + // 记录异常并处理 + e.printStackTrace(); + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + private Account extendValidity(Long validEndTime, double totalSales) { + Instant specifiedInstant; + Account account = new Account(); + long epochMilli = Instant.now().toEpochMilli(); + if (!Objects.isNull(validEndTime) && validEndTime > epochMilli) { + // 将 Unix 毫秒级时间戳转换为 Instant + specifiedInstant = Instant.ofEpochMilli(validEndTime); + } else { + specifiedInstant = Instant.now(); + account.setValidStartTime(specifiedInstant.toEpochMilli()); + } + + // 指定时区 + ZoneId zoneId = ZoneId.of("Asia/Shanghai"); + // 将 Instant 转换为 ZonedDateTime,使用指定时区 + ZonedDateTime specifiedDateTime = ZonedDateTime.ofInstant(specifiedInstant, zoneId); + ZonedDateTime validityExtension; + if (totalSales == 500) { + // 一个月 + validityExtension = specifiedDateTime.plusMonths(1); + } else if (totalSales == 5000) { + // 一年 + validityExtension = specifiedDateTime.plusYears(1); + } else { + // 测试 一天 + validityExtension = specifiedDateTime.plusDays(1); + } + // 获取一个月之后的时间的 Unix 毫秒级时间戳 + account.setValidEndTime(toDayEnd(validityExtension.toInstant().toEpochMilli())); + return account; + } + + private static final String QUERY_MAXIMUM_USERID = "SELECT MAX(ID) AS max_id FROM pmr_users;"; + + private static final String QUERY_NEW_USER_EMAIL = "SELECT user_email FROM pmr_users " + + "WHERE ID > ? "; + + @Value("${redis.key.maximumUserId}") + private String maximumUserIdKey; + + /** + * 将Code-Create上注册的用户添加为AiDA的游客 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void registerUserToVisitor(){ + ArrayList newUserEmails = new ArrayList<>(); + long maxUserId = CommonConstant.MAXIMUM_USER_ID; + try (Connection connection = dataSource.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(QUERY_MAXIMUM_USERID)) { + try (ResultSet queryOrderResultSet = preparedStatement.executeQuery()) { + while (queryOrderResultSet.next()) { + // 获取最新的最大用户id + maxUserId = queryOrderResultSet.getLong("max_id"); + // 获取历史最大用户id + long maxUserIdHistory = StringUtil.isNullOrEmpty(redisUtil.getFromString(maximumUserIdKey)) ? CommonConstant.MAXIMUM_USER_ID : Long.parseLong(redisUtil.getFromString(maximumUserIdKey)); + if (maxUserId > maxUserIdHistory){ + // 查出新增用户的邮箱 + PreparedStatement newUserEmail = connection.prepareStatement(QUERY_NEW_USER_EMAIL); + // 填充参数 - 历史最大用户ID + newUserEmail.setLong(1, maxUserIdHistory); + try (ResultSet queryEmailResultSet = newUserEmail.executeQuery()) { + if (queryEmailResultSet.next()) { + String email = queryEmailResultSet.getString("user_email"); + newUserEmails.add(email); + } /*else { + log.error("未知错误。code-create的用户表中没有付费用户的信息"); + throw new BusinessException("user info missing"); + }*/ + } + } + } + } + } catch (Exception e) { + // 记录异常并处理 + e.printStackTrace(); +// return null; + } + + if (!newUserEmails.isEmpty()){ + // 查询这些邮箱在aida上是否有账号 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("user_email", newUserEmails).select("user_email"); + + List collect = baseMapper.selectList(queryWrapper).stream().map(Account::getUserEmail).collect(Collectors.toList()); + if (!collect.isEmpty()){ + // 移除Code-Create新增用户中在AiDA已有账号的邮箱 + newUserEmails.removeAll(collect); + } + // 将新增用户添加到AiDA,身份为游客 + if (!newUserEmails.isEmpty()){ + newUserEmails.forEach(email -> { + Account account = new Account(); + account.setUserEmail(email); + account.setUserName(email); + account.setUserPassword("Third-000000"); + account.setLanguage(Language.ENGLISH.name()); + account.setValidStartTime(Instant.now().toEpochMilli()); + account.setCreateDate(new Date()); + account.setIsTrial(0); + account.setIsBeginner(1); + account.setCredits(new BigDecimal(0)); + account.setSystemUser(0); + baseMapper.insert(account); + // 邮件通知用户 + SendEmailUtil.notificationForRegisterUser(email); + }); + } + // 记录当前最大的用户id + redisUtil.addToString(maximumUserIdKey, String.valueOf(maxUserId)); + } + } + + // 收集调查问卷的信息 + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean collectQuestionnaires(String questionnaireInfo) { + log.info("调查问卷详细信息:{}", questionnaireInfo); + QuestionnaireVO questionnaireVO = JSON.parseObject(questionnaireInfo, QuestionnaireVO.class); + String email = questionnaireVO.getEmail(); + // 1、通过邮箱判断当前用户有无系统账号 + Account account; + try { + account = getOneByEmail(email); + } catch (BusinessException e) { + log.info(e.getMessage()); + log.warn("当前用户 {} 在AiDA中没有账号", email); + throw new BusinessException("user.has.no.account",ResultEnum.PROMPT.getCode()); + } + // 2、先判断当前用户是否已经填写过问卷 + CreditsDetail record = creditsService.getByAccountIdAndChangeEvent(account.getId(), "Fill out the questionnaire", "+100"); + if (!Objects.isNull(record)) { + log.info("当前用户 {} 已经填写过问卷", email); + throw new BusinessException("questionnaire.filled.out", ResultEnum.PROMPT.getCode()); + } + + // 3.1、将问卷信息存储到数据库 + Questionnaire questionnaire = new Questionnaire(); + questionnaire.setQuestionnaireInfo(questionnaireInfo); + questionnaire.setTitle("AiDA_3.0 Feedback Survey--06/2024"); + questionnaire.setCreateTime(LocalDateTime.now()); + int insert = questionnaireMapper.insert(questionnaire); + + if (insert == 1) { + // 3.2、更新 t_credits_detail表 + CreditsDetail creditsDetail = new CreditsDetail(); + creditsDetail.setAccountId(account.getId()); + creditsDetail.setChangeEvent("Fill out the questionnaire"); + creditsDetail.setChangedCredits("+100"); + BigDecimal added = account.getCredits().add(new BigDecimal("100")); + creditsDetail.setCredits(added); + creditsDetail.setCreateTime(LocalDateTime.now()); + creditsService.save(creditsDetail); + + // 3.3、更新 t_account 表 + if (account.getValidEndTime() != null && account.getValidEndTime() < 1720972799000L){ + updateCreditsAndEndTime(account.getId(), added.toString(), 1720972799000L); + } + } + + // 4、发邮件 区分中英文 + SendEmailUtil.questionnaireRelatedNotify(questionnaireVO.getUserName(), email, questionnaireVO.getLanguage()); + return Boolean.TRUE; + } + + /** + * 为年费用户每月更新积分 + */ + public void refreshCreditsWeekly(){ + UpdateWrapper accountUpdateWrapper = new UpdateWrapper<>(); + // 刷新账号有效期截止之前的年付用户的积分 + long epochMilli = Instant.now().toEpochMilli(); + accountUpdateWrapper.lambda().set(Account::getCredits, CreditsEventsEnum.INIT_WEEKLY.getValue()) + .eq(Account::getSystemUser,1).or().eq(Account::getSystemUser,2) + .gt(Account::getValidEndTime, epochMilli); + baseMapper.update(null,accountUpdateWrapper); + } + + @Override + public String getActivityBenefits(){ + Long id = UserContext.getUserHolder().getId(); + // 1、 判断用户的身份 正式用户 无福利 + Account account = baseMapper.selectById(id); + Integer systemUser = account.getSystemUser(); + Instant now = Instant.now(); + ZoneId zoneId = ZoneId.of("Asia/Shanghai"); + ZonedDateTime specifiedDateTime; + if (systemUser.equals(1)){ + long validEndTime = Objects.isNull(account.getValidEndTime()) ? now.toEpochMilli() : account.getValidEndTime(); + specifiedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(validEndTime), zoneId); + account.setValidEndTime(toDayEnd(specifiedDateTime.plusDays(30).toInstant().toEpochMilli())); + + }else if (systemUser.equals(4)){ + throw new BusinessException("You have participated in the event", 1); + }else if (systemUser.equals(0) || systemUser.equals(3)){ + // 2、赋予游客或试用用户 以正式用户的权限 即 积分置为6000,有效期30天 + // 将 Instant 转换为 ZonedDateTime,使用指定时区 + specifiedDateTime = ZonedDateTime.ofInstant(now, zoneId); + account.setIsTrial(0); + account.setSystemUser(4); + account.setCredits(BigDecimal.valueOf(6000)); + account.setValidStartTime(now.toEpochMilli()); + account.setValidEndTime(toDayEnd(specifiedDateTime.plusDays(30).toInstant().toEpochMilli())); + } + + account.setUpdateDate(new Date()); + baseMapper.updateById(account); + + return "参与成功"; + + } + // 将指定unix时间置为当天的23:59:59 + public long toDayEnd(long unixTimestampMillis){ + // 将UNIX时间戳转换为LocalDateTime对象 + LocalDateTime dateTime = Instant.ofEpochMilli(unixTimestampMillis) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime(); + + // 获取日期部分并设置时间为23:59:59 + LocalDate date = dateTime.toLocalDate(); + LocalDateTime endOfDay = date.atTime(LocalTime.of(23, 59, 59)); + + // 将LocalDateTime对象转换为UNIX时间戳(以毫秒为单位) 北京时间 + return endOfDay.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); + } + + /** + * 获取指定身份过期用户 + * @param systemUserNum + * @return + */ + public List getExpiredUserBySystemUser(Integer systemUserNum){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + long now = Instant.now().toEpochMilli(); + queryWrapper.eq("system_user", systemUserNum) + .isNotNull("valid_end_time") + .lt("valid_end_time", now); + + return baseMapper.selectList(queryWrapper); + } + + public void toVisitor(Account account){ + accountMapper.toVisitor(account.getId(), new Date()); + } + + public List setUserValidToDayEnd(){ + // 获取当前未过期的用户,并将其有效期设置为过期当日的23:59:59 + QueryWrapper queryWrapper = new QueryWrapper<>(); + long now = Instant.now().toEpochMilli(); + queryWrapper.isNotNull("valid_end_time").gt("valid_end_time", now); + List accounts = baseMapper.selectList(queryWrapper); + ArrayList ids = new ArrayList<>(); + + for (Account account: accounts) { + account.setValidEndTime(toDayEnd(account.getValidEndTime())); + ids.add(account.getId()); + updateById(account); + } + + return ids; + } + + public IPage getPageByDateAndUserType(String startTime, String endTime, Integer type, int pageNum, int size){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + setTimeAndSystemUser(queryWrapper,startTime, endTime, type); + + Page accountPage = new Page<>(pageNum, size); + return baseMapper.selectPage(accountPage, queryWrapper); + } + + private void setTimeAndSystemUser(QueryWrapper queryWrapper, String startTime, String endTime, Integer type){ + queryWrapper.gt("create_date", startTime).lt("create_date",endTime); + + if (!Objects.isNull(type)){ + switch (type){ + case 0: + // 游客 + queryWrapper.eq("system_user", 0); + break; + case 1: + queryWrapper.eq("system_user", 1); + break; + case 2: + queryWrapper.eq("system_user", 2); + break; + case 3: + // 试用用户 + queryWrapper.eq("system_user", 3).or().eq("system_user", 4); + break; + + } + } + } + + public Map getByDateAndUserType(String startTime, String endTime, Integer type){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + setTimeAndSystemUser(queryWrapper,startTime, endTime, type); + queryWrapper.groupBy("system_user"); + + queryWrapper.select("system_user as type, count(id) as count"); + List> maps = baseMapper.selectMaps(queryWrapper); + return maps.stream() + .collect(Collectors.toMap( + map -> map.get("type").toString(), + map -> Objects.isNull(map.get("count")) ? 0L : (Long) map.get("count"))); + } + + public IPage getPageByIds(List ids, int pageNum, int size){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("id", ids); + + return baseMapper.selectPage(new Page<>(pageNum, size), queryWrapper); + } + + public List getByIds(List ids){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("id", ids); + + return baseMapper.selectList(queryWrapper); + } + + public String uploadAvatar(MultipartFile file){ + Long accountId = UserContext.getUserHolder().getId(); + // 1、上传图片到minio + String avatarPath = minioUtil.upload(userBucket, accountId.toString() + "/avatar", file); + // 2、查询该用户之前的头像 + String avatar = baseMapper.selectById(accountId).getAvatar(); + if (!StringUtil.isNullOrEmpty(avatar) && !avatar.equals(CommonConstant.DEFAULT_AVATAR)){ + minioUtil.deleteObject(avatar); + } + + // 3、替换新的头像 + Account account = new Account(); + account.setId(accountId); + account.setAvatar(avatarPath); + baseMapper.updateById(account); + + return minioUtil.getPreSignedUrl(avatarPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME); + } + + public PersonalHomepageVO getPersonalHomepage(Long accountId){ + // 需要返回 用户头像 用户名 作品总量 粉丝量 关注量 主页访问量 当前用户是否被查看者关注 + Long currentUserId = UserContext.getUserHolder().getId(); + PersonalHomepageVO personalHomepageVO = new PersonalHomepageVO(); + + Account account = baseMapper.selectById(accountId); + personalHomepageVO.setUserName(account.getUserName()); + String avatar = StringUtil.isNullOrEmpty(account.getAvatar()) ? CommonConstant.DEFAULT_AVATAR : account.getAvatar(); + personalHomepageVO.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + + personalHomepageVO.setPortfolioCount(portfolioService.getPortfolioCount(accountId)); + personalHomepageVO.setFolloweeCount(portfolioService.getFolloweeCount(accountId)); + personalHomepageVO.setFollowerCount(portfolioService.getFollowerCount(accountId)); + personalHomepageVO.setHomepageViewCount(viewPersonalHomepageCount(0L)); + + + if (accountId.equals(currentUserId)){ + personalHomepageVO.setIsFollow(0); + Long viewCount = viewPersonalHomepageCount(accountId); + // 只有本人才能看到个人主页浏览量 + personalHomepageVO.setHomepageViewCount(viewCount == null ? 0 : viewCount); + }else { + personalHomepageVO.setIsFollow(portfolioService.getIfFollowed(accountId, currentUserId)); + // 非本人浏览主页时增加浏览量 + viewsIncrease(accountId); + } + return personalHomepageVO; + } + + @Override + public Boolean viewsIncrease(Long id) { + redisUtil.increasePersonalHomepageViewCount(id); + return Boolean.TRUE; + } + + private Long viewPersonalHomepageCount(Long accountId) { + redisUtil.getPersonalHomepageViewCount(accountId); + return null; + } + +} diff --git a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java index 99f0b6be..c8180384 100644 --- a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java @@ -23,21 +23,27 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.collect.Lists; +import com.mysql.cj.util.StringUtils; import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.SerializationUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.io.File; import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** @@ -85,6 +91,8 @@ public class DesignItemServiceImpl extends ServiceImpl { // 如果sketch截图不为空,则将该截图上传,并替换path - if (!StringUtil.isNullOrEmpty(item.getMaskUrl())){ - // 由于前端不好处理这块,所以,当mask没有做任何修改的时候,仍然会传原始mask的minio地址 - if (!item.getMaskUrl().startsWith("data:image") && item.getMaskUrl().startsWith("https://")){ - // 当没有修改mask时,还是用之前的mask地址 - item.setMaskUrl(item.getMaskMinioUrl()); - }else { - // 将原图地址作为修改后的图片地址,放在不同的桶 - String path = minioUtil.base64UploadToPath(item.getMaskUrl(), clothingBucket, "labelingMask/" + UUID.randomUUID()); - if (StringUtil.isNullOrEmpty(path)){ - log.error("标注的mask图片上传失败"); - throw new BusinessException("image.modify.failed"); + if (setNull){ + item.setMaskUrl(null); + }else { + if (!StringUtil.isNullOrEmpty(item.getMaskUrl())){ + // 由于前端不好处理这块,所以,当mask没有做任何修改的时候,仍然会传原始mask的minio地址 + if (!item.getMaskUrl().startsWith("data:image") && item.getMaskUrl().startsWith("https://")){ + // 当没有修改mask时,还是用之前的mask地址 + item.setMaskUrl(item.getMaskMinioUrl()); + }else { + // 将原图地址作为修改后的图片地址,放在不同的桶 + String path = minioUtil.base64UploadToPath(item.getMaskUrl(), clothingBucket, "labelingMask/" + UUID.randomUUID()); + if (StringUtil.isNullOrEmpty(path)){ + log.error("标注的mask图片上传失败"); + throw new BusinessException("image.modify.failed"); + } + item.setMaskUrl(path); } - item.setMaskUrl(path); } } }); @@ -909,228 +928,157 @@ public class DesignItemServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); + queryWrapper.ne("design_item_id", -1) + .ne("converted", 1) + .groupBy(Arrays.asList("design_outfit_id"," design_item_id")).select(" design_item_id", "design_outfit_id"); - // 查询用户like过的design 且没有使用渐变色的 design_item_id和design_python_outfit_id - List> historyLikeWithoutGradient = userLikeMapper.getHistoryLikeWithoutGradient(); - log.info("historyLikeWithoutGradient total count : {}", historyLikeWithoutGradient.size()); - // 遍历list - // 先试一下,刷新10条,需要花费的时间 + List userLikes = userLikeMapper.selectList(queryWrapper); +// List> userLikes = userLikeMapper.selectMaps(queryWrapper); + log.info("userLike 总数 :{}", userLikes.size()); + // 用于存储结果 + List pairs = new ArrayList<>(); + AtomicInteger count = new AtomicInteger(); - /*Map userLikeMap = historyLikeWithoutGradient.get(0); - log.info("test 替换mask" + userLikeMap.toString()); + // 2、查询指定designOutfitId对应的mask + userLikes.forEach(item -> { + // 存储数据,按前缀分组 + Map> groupedData = new HashMap<>(); + Long designItemId = item.getDesignItemId(); + Long designOutfitId = item.getDesignOutfitId(); - // 查每个design_item_id和design_python_outfit_id的detail - DesignItemDetailVO detail = designService.detail(userLikeMap.get("design_outfit_id"), userLikeMap.get("design_item_id")); - Long accountId = userLikeMap.get("account_id"); - // 组装参数 - DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO = convertToDesignSingleIncludeLayersDTO(detail, accountId); - if (Objects.isNull(designSingleIncludeLayersDTO)){ - throw new BusinessException("cannot find model"); - } - // 调用design single - designSingleIncludeLayers(designSingleIncludeLayersDTO, accountId); + List designPythonOutfitDetails = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designOutfitId); + List designItemDetails = designItemDetailService.selectByDesignItemId(designItemId); + // 为没有优先级的sketch添加优先级 + designItemDetailService.setDesignItemDetailPriority(designItemDetails); + // 为没有优先级的图层添加优先级 + designPythonOutfitDetailService.setDesignPythonOutfitDetailPriority(designPythonOutfitDetails); + Map designItemPath = designItemDetails.stream() + .filter(designItemDetail -> !designItemDetail.getType().equals("Body")) + .collect(Collectors.toMap( + DesignItemDetail::getPriority, // key: category 转为小写 + DesignItemDetail::getPath // value: path 字段 + )); + // 遍历列表,拿出每个种类的前后片 + designPythonOutfitDetails.forEach(designPythonOutfitDetail -> { + String imageCategory = designPythonOutfitDetail.getImageCategory(); + String maskPath = designPythonOutfitDetail.getMaskUrl(); + Integer priority = Math.abs(designPythonOutfitDetail.getPriority()); - // 标志字段置为1 - UserLike userLike = new UserLike(); - userLike.setId(userLikeMap.get("id")); - userLike.setConverted(1); + // 提取前缀和后缀 + if (imageCategory.contains("_")) { + String[] parts = imageCategory.split("_"); +// String prefix = parts[0]; + String suffix = parts[1]; - userLikeMapper.updateById(userLike);*/ - long start = System.currentTimeMillis(); - for (int i = 0; i < 10; i++){ - try { - Map userLikeMap = historyLikeWithoutGradient.get(0); - log.info("test 替换mask" + userLikeMap.toString()); - Long designItemId = userLikeMap.get("design_item_id"); - Long designOutfitId = userLikeMap.get("design_outfit_id"); - - // 查每个design_item_id和design_python_outfit_id的detail - DesignItemDetailVO detail = designService.detail(designOutfitId, designItemId); - Long accountId = userLikeMap.get("account_id"); - // 组装参数 - DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO = convertToDesignSingleIncludeLayersDTO(detail, accountId); - if (Objects.isNull(designSingleIncludeLayersDTO)){ - throw new BusinessException("cannot find model. designItemId: " + designItemId + "designOutfitId : " + designOutfitId ); + // 初始化前缀组 + groupedData.putIfAbsent(priority, new HashMap<>()); + groupedData.get(priority).put(suffix, maskPath); } - // 调用design single - designSingleIncludeLayers(designSingleIncludeLayersDTO, accountId); + }); - // 标志字段置为1 - UserLike userLike = new UserLike(); - userLike.setId(userLikeMap.get("id")); - userLike.setConverted(1); - - userLikeMapper.updateById(userLike); - }catch (BusinessException e){ - log.error("mask convert error : {}", e.getMessage()); + // 查找成对的front和back + for (Map.Entry> entry : groupedData.entrySet()) { + Map suffixes = entry.getValue(); + if (suffixes.containsKey("front") && suffixes.containsKey("back")) { + String frontMask = suffixes.get("front"); + String backMask = suffixes.get("back"); + pairs.add(new String[]{designItemPath.get(entry.getKey()),frontMask, backMask, frontMask}); + } } - } - long end = System.currentTimeMillis(); + log.info("总数 count + current : {} + {} = {}", count, groupedData.size(), count.get() + groupedData.size()); + count.addAndGet(groupedData.size()); - log.info("convert mask ,10条 执行时长:" + (end - start) + "毫秒"); - - - } - - - public DesignSingleIncludeLayersDTO convertToDesignSingleIncludeLayersDTO(DesignItemDetailVO designItemDetailVO, Long userId){ - DesignSingleIncludeLayersDTO resp = new DesignSingleIncludeLayersDTO(); - - Long designItemId = designItemDetailVO.getDesignItemId(); - String gender ; - String modelPath = designItemDetailVO.getOthers().get(0).getMinIOPath(); - List modelSysFile = sysFileService.getByUrlList(Collections.singletonList(modelPath)); - if (modelSysFile.isEmpty()){ - log.error("cannot find model 【{}】 in t_sys_file ", modelPath); - return null; - }else { - gender = modelSysFile.get(0).getLevel2Type(); - } - - resp.setDesignItemId(designItemId); - resp.setGender(gender); - resp.setIsPreview(Boolean.FALSE); - resp.setProcessId(String.valueOf(userId)); - resp.setTimeZone("Etc/GMT-8"); - List designSingleItemDTOS = new ArrayList<>(); - resp.setDesignSingleItemDTOList(designSingleItemDTOS); - - designItemDetailVO.getClothes().forEach(cloth -> { - DesignSingleItemDTO itemDTO = CopyUtil.copyObject(cloth, DesignSingleItemDTO.class); - itemDTO.setChanged(Boolean.FALSE); - itemDTO.setDesignType("Library"); - itemDTO.setPath(cloth.getMinIOPath()); - PantoneVO color = cloth.getColor(); - String colorString = color.getR() + " " + color.getG() + " " + color.getB(); - itemDTO.setColor(colorString); - if (cloth.getLayersObject().isEmpty()){ - itemDTO.setOffset(Arrays.asList(0L,0L)); - itemDTO.setScale(new Float[]{1.0f,1.0f}); - }else { - DesignPythonOutfitVO designPythonOutfitVO = cloth.getLayersObject().get(0); - itemDTO.setOffset(designPythonOutfitVO.getOffset()); - itemDTO.setScale(designPythonOutfitVO.getScale()); - } - // 统一设置mask为null,不用旧版mask - itemDTO.setMaskMinioUrl(null); - designSingleItemDTOS.add(itemDTO); }); - return resp; + // 将结果写入JSON文件 + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 格式化JSON输出 + + try { + // 写入JSON文件 + objectMapper.writeValue(new File("mask_pairs.json"), pairs); + log.info("待合成mask的数量:{}",pairs.size()); + System.out.println("数据已成功写入mask_pairs.json文件"); + } catch (IOException e) { + e.printStackTrace(); + } } - // temp 用于处理历史like的design没有新的mask的问题 - public void designSingleIncludeLayers(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO, Long userId) { - // 记录入参 base64数据太长,所以这里去掉 - DesignSingleIncludeLayersDTO clone = SerializationUtils.clone(designSingleIncludeLayersDTO); - clone.getDesignSingleItemDTOList().forEach( i -> { - // 渐变色 - if (!Objects.isNull(i.getGradient()) && !StringUtil.isNullOrEmpty(i.getGradient().getColorImg())){ - log.info("set gradient colorImage为空,便于日志打印"); - i.getGradient().setColorImg(null); - } - // 画笔修改过的sketch - if (!StringUtil.isNullOrEmpty(i.getSketchString())){ - log.info("set sketchString为空,便于日志打印"); - i.setSketchString(null); - } - // 标注过的mask - if (!StringUtil.isNullOrEmpty(i.getMaskUrl())){ - log.info("set labelingMask为空,便于日志打印"); - i.setMaskUrl(null); - }else { - // todo 允许为空吗? -// throw new BusinessException("labeling mask cannot be empty"); - } + @Transactional(rollbackFor = Exception.class) + public void updateMaskUrl(){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.ne("design_item_id", -1) + .ne("converted", 1) + .groupBy(Arrays.asList("design_outfit_id"," design_item_id")).select(" design_item_id", "design_outfit_id"); + + List userLikes = userLikeMapper.selectList(queryWrapper); + log.info("userLike 总数 :{}", userLikes.size()); + ArrayList tDesignPythonOutfitDetails = new ArrayList<>(); + + + // 2、查询指定designOutfitId对应的mask + userLikes.forEach(item -> { + Long designOutfitId = item.getDesignOutfitId(); + + // 存储以front结尾的mask路径 + Map frontMaskMap = new HashMap<>(); + HashMap backMaskIdMap = new HashMap<>(); + List designPythonOutfitDetails = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designOutfitId); + // 遍历列表,拿出每个种类的前后片 + designPythonOutfitDetails.forEach(designPythonOutfitDetail -> { + String imageCategory = designPythonOutfitDetail.getImageCategory(); + String maskUrl = designPythonOutfitDetail.getMaskUrl(); + + // 检查是否以'front'结尾 + if (imageCategory.endsWith("front")) { + String maskPath = maskUrl.replace("aida-clothing", "test" ); + String prefix = imageCategory.substring(0, imageCategory.lastIndexOf("_")); + if (backMaskIdMap.containsKey(prefix)) { + TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); + tDesignPythonOutfitDetail.setMaskUrl(maskPath); + tDesignPythonOutfitDetail.setUpdateDate(LocalDateTime.now()); + tDesignPythonOutfitDetail.setId(backMaskIdMap.get(prefix)); + tDesignPythonOutfitDetails.add(tDesignPythonOutfitDetail); + }else { + frontMaskMap.put(prefix, maskPath); + } + + TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); + tDesignPythonOutfitDetail.setMaskUrl(maskPath); + tDesignPythonOutfitDetail.setUpdateDate(LocalDateTime.now()); + tDesignPythonOutfitDetail.setId(designPythonOutfitDetail.getId()); + tDesignPythonOutfitDetails.add(tDesignPythonOutfitDetail); + } + + if (imageCategory.endsWith("back")) { + String prefix = imageCategory.substring(0, imageCategory.lastIndexOf("_")); + if (frontMaskMap.containsKey(prefix)) { + // 更新back的mask路径为front的mask路径 + String frontMaskPath = frontMaskMap.get(prefix); + + TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); + tDesignPythonOutfitDetail.setMaskUrl(frontMaskPath); + tDesignPythonOutfitDetail.setUpdateDate(LocalDateTime.now()); + tDesignPythonOutfitDetail.setId(designPythonOutfitDetail.getId()); + tDesignPythonOutfitDetails.add(tDesignPythonOutfitDetail); + }else { + backMaskIdMap.put(prefix, designPythonOutfitDetail.getId()); + } + } + }); }); - log.info("designSingle request入参 ==> " + JSONObject.toJSONString(clone)); - -// Long userId = UserContext.getUserHolder().getId(); - DesignItem designItem = selectById(designSingleIncludeLayersDTO.getDesignItemId()); - if (Objects.isNull(designItem)) { - throw new BusinessException("designItem.not.found"); - } - Design design = designService.getById(designItem.getDesignId()); - if (Objects.isNull(design)) { - throw new BusinessException("design.not.found"); - } - - DesignLibraryModelPointVO designLibraryModelPointVO = null; - // 设置模特 - if (Objects.nonNull(design.getTemplateId())) { - String modelUrl; - Integer high; - Integer width; - if (design.getModelType().equals(ModelType.SYSTEM.getValue())) { - SysFileVO sysFile = sysFileService.getById(design.getTemplateId()); - if (Objects.isNull(sysFile)) { - throw new BusinessException("model.not.found"); - } - modelUrl = sysFile.getUrl(); - high = 700; - width = 320; - } else if (design.getModelType().equals(ModelType.LIBRARY.getValue())){ - Library libFile = libraryService.getById(design.getTemplateId()); - if (Objects.isNull(libFile)) { - throw new BusinessException("model.not.found"); - } - modelUrl = libFile.getUrl(); - high = libFile.getHigh(); - width = libFile.getWidth(); - }else { - throw new BusinessException("unknown.modelType"); - } - LibraryModelPoint modelPoint = libraryModelPointService.getByRelationId(design.getTemplateId(), design.getModelType()); - if (Objects.isNull(modelPoint)) { - throw new BusinessException("modelPoint.not.found"); - } - - designLibraryModelPointVO = collectionElementService.calculateTemplatePoint(modelPoint, high, width, modelUrl); - } - - // 画笔修改的sketch截图 上传后替换path - // 由于用户在系统或自己上传sketch的基础上修改过的衣服,再次修改后,第一次修改的衣服不会回到某个池子被再次利用, - // 所以,这里选择使用system或collection相同的地址,只是放在不同的桶,这样能保证图片服务器上,类似的sketch不会存在很多 - sketchBase64ToPath(designSingleIncludeLayersDTO); - - // todo 将标注后的mask上传到minio,并将minio地址传给python端 -// maskBase64ToPath(designSingleIncludeLayersDTO); - - // 组装入参 - DesignPythonObjects objects = pythonService.covertDesignSingleParam( - designSingleIncludeLayersDTO, design.getSingleOverall(), design.getSwitchCategory(), designLibraryModelPointVO); - // design - JSONObject jsonObject = pythonService.designNew(objects); - // preview -> 不存数据库 submit -> 存数据库 - List tDesignPythonOutfitDetails; - JSONObject data = jsonObject.getJSONObject("data"); - if (data == null) { - throw new BusinessException("python response data is null"); - } - JSONObject outfit = data.getJSONObject("0"); - - JSONArray layers = outfit.getJSONArray("layers"); - Map categoryAndUndividedLayer = setTypeAndUndividedLayer(layers); - // 直接更新及保存图层信息,全部走submit 不走preview - saveDesignSingleItemDetailAndLayers(objects, design.getId(), designSingleIncludeLayersDTO.getDesignItemId() - , userId, outfit, designSingleIncludeLayersDTO.getTimeZone() - , designSingleIncludeLayersDTO.getDesignSingleItemDTOList() - , categoryAndUndividedLayer); - - // 如果当前item被like过,需要更新t_user_like表和t_user_like_group表 - // - 这里,因为处理的都是like过的,所以都需要更新 - updateUserLikeDate(designSingleIncludeLayersDTO.getDesignItemId(),designSingleIncludeLayersDTO.getTimeZone()); - - // 数据替换完成即可,不需要返回数据 + log.info("更新总数:{}", tDesignPythonOutfitDetails.size()); + designPythonOutfitDetailService.updateBatchById(tDesignPythonOutfitDetails); + log.info("更新完成"); } } 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 7f779570..2e2d4e15 100644 --- a/src/main/java/com/ai/da/service/impl/DesignServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/DesignServiceImpl.java @@ -813,9 +813,9 @@ public class DesignServiceImpl extends ServiceImpl impleme // return new DesignLikeVO(); // } List oldElements = collectionElementService.getByCollectionId(userLikeGroup.getCollectionId()); - if (CollectionUtil.isEmpty(oldElements)) { - throw new BusinessException("old.elements.not.found"); - } +// if (CollectionUtil.isEmpty(oldElements)) { +// throw new BusinessException("old.elements.not.found"); +// } List designItemDetails = designItemDetailService.selectByDesignItemId(designLikeDTO.getDesignItemId()); if (CollectionUtil.isEmpty(designItemDetails)) { throw new BusinessException("new.designItemDetails.not.found"); @@ -867,8 +867,11 @@ public class DesignServiceImpl extends ServiceImpl impleme if (CollectionUtils.isEmpty(hasCollections)) { return null; } - List oldIds = oldElements.stream().map(CollectionElement::getId).collect(Collectors.toList()); List elementIds = hasCollections.stream().map(DesignItemDetail::getCollectionElementId).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oldElements)) { + return elementIds; + } + List oldIds = oldElements.stream().map(CollectionElement::getId).collect(Collectors.toList()); //本次新增collection个数 List adds = elementIds.stream().filter(id -> !oldIds.contains(id)).collect(Collectors.toList()); if (CollectionUtils.isEmpty(adds)) { @@ -934,7 +937,7 @@ public class DesignServiceImpl extends ServiceImpl impleme List userLikeVOS = userLikeService.getGroupDetail(userLike.getUserLikeGroupId()); if (CollectionUtils.isEmpty(userLikeVOS)) { //group 下面没有元素时候 直接删除 - userLikeGroupService.removeById(userLike.getUserLikeGroupId()); +// userLikeGroupService.removeById(userLike.getUserLikeGroupId()); } return Boolean.TRUE; } @@ -1001,7 +1004,6 @@ public class DesignServiceImpl extends ServiceImpl impleme response.setSingleOverall(design.getSingleOverall()); response.setSwitchCategory(design.getSwitchCategory()); response.setDesignItemId(designItemId); -// response.setDesignItemUrl(designItem.getDesignUrl()); response.setHighDesignUrl(designItem.getHighDesignUrl()); List filterDetail = designItemDetails.stream() .filter(f -> OUTWEAR_DRESS_BLOUSE.contains(f.getType()) || SKIRT_TROUSERS.contains(f.getType()) @@ -1035,8 +1037,6 @@ public class DesignServiceImpl extends ServiceImpl impleme .filter(f -> SYS_HAIRSTYLE_SHOES_BODY.contains(f.getType())) .collect(Collectors.toList()); response.setOthers(CopyUtil.copyList(filterDetail2, DesignItemOthersDetailVO.class, (o, d) -> { - // todo 不确定businessId的作用,暂时取消传递,查看影响 -// d.setId(o.getBusinessId()); d.setId(0L); d.setPath(minioUtil.getPreSignedUrl(o.getPath(), 24 * 60)); d.setMinIOPath(o.getPath()); @@ -1172,12 +1172,6 @@ public class DesignServiceImpl extends ServiceImpl impleme designPythonOutfitDetailService.setDesignPythonOutfitDetailPriority(details); details.forEach(detail -> { -// List offset = new ArrayList<>(); -// if (StringUtil.isNullOrEmpty(detail.getOffset()) || detail.getOffset().equals("null")) { -// offset = Arrays.asList(0L, 0L); -// } else { -// offset = Arrays.stream(detail.getOffset().replaceAll("\\[|\\]", "").split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); -// } detailsVO.add(designPythonOutfitDetailService.convertToDesignPythonOutfitVO(detail, null)); }); @@ -1185,11 +1179,7 @@ public class DesignServiceImpl extends ServiceImpl impleme designItemDetailVO.setDesignItemUrl(minioUtil.getPreSignedUrl(designPythonOutfit.getDesignUrl(), 24 * 60)); // 2.1 填充clothes designItemDetailVO.getClothes().forEach(c -> { -// String type = c.getType().toLowerCase(); -// List outfitVOS = detailsVO.stream().filter((detail -> detail.getImageCategory().equals(type + "_back") || -// detail.getImageCategory().equals(type + "_front"))).collect(Collectors.toList()); List outfitVOS = detailsVO.stream().filter(detail -> detail.getPriority().equals(c.getPriority())).collect(Collectors.toList()); - c.setLayersObject(outfitVOS); }); // 2.2 填充others 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 95f17e90..3b83ca8d 100644 --- a/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java @@ -3,16 +3,12 @@ package com.ai.da.service.impl; 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.CollectionLevel2TypeEnum; -import com.ai.da.common.enums.CreditsEventsEnum; -import com.ai.da.common.enums.GenerateModeEnum; -import com.ai.da.common.enums.ModelNameEnum; +import com.ai.da.common.enums.*; 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.GenerateLikeDTO; -import com.ai.da.model.dto.GenerateThroughImageTextDTO; -import com.ai.da.model.dto.GenerateToPythonDTO; +import com.ai.da.model.dto.*; +import com.ai.da.model.enums.SketchStyle; import com.ai.da.model.vo.*; import com.ai.da.python.PythonService; import com.ai.da.service.*; @@ -26,13 +22,16 @@ import com.google.gson.Gson; import io.minio.errors.MinioException; import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.io.IOException; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; import static com.ai.da.common.enums.CollectionLevel1TypeEnum.*; @@ -77,6 +76,9 @@ public class GenerateServiceImpl extends ServiceImpl i @Value("${minio.bucketName.slogan}") private String sloganBucket; + @Value("${minio.bucketName.users}") + private String userBucket; + @Value("${redis.key.relightResultKey}") private String relightResultKey; @@ -88,6 +90,8 @@ public class GenerateServiceImpl extends ServiceImpl i // 创建 Random 对象 Random random = new Random(); + @Autowired + private ProductServiceImpl productServiceImpl; @Override public GenerateCaptionVO generateCaption(Long sketchElementId) { @@ -132,7 +136,6 @@ public class GenerateServiceImpl extends ServiceImpl i text = modifyPrompt(text, generate, generateThroughImageTextDTO.getLevel1Type()); } - // todo 这一步现在还是有必要的吗? // 2.1 sketch或print在t_collection_element表/t_library表中的信息是否需要更新 如 level2Type CollectionElement collectionElement = collectionElementService.editLevel2Type(elementId, generateThroughImageTextDTO.getLevel2Type(), generateThroughImageTextDTO.getDesignType()); @@ -298,27 +301,6 @@ public class GenerateServiceImpl extends ServiceImpl i } generate.setGenerateType(generateType); - /*switch (generateType) { - case "text": - if (StringUtil.isNullOrEmpty(text)) { - throw new BusinessException("please.input.the.caption"); - } - generate.setText(text); - break; - case "image": - if (Objects.isNull(elementId)) { - throw new BusinessException("please.choose.an.image"); - } - generate.setElementId(elementId); - break; - case "text-image": - if (StringUtil.isNullOrEmpty(text) || Objects.isNull(elementId)) { - throw new BusinessException("please.input.the.caption.and.choose.an.image"); - } - generate.setText(text); - generate.setElementId(elementId); - default: - }*/ } private String modifyPrompt(String userInput, Generate generate, String level1Type) { @@ -781,8 +763,101 @@ public class GenerateServiceImpl extends ServiceImpl i @Resource private GenerateMapper generateMapper; + public List> getCountByUserAndTime(String startTime, String endTime, List accountIdList) { List> byTypeAndTime = generateMapper.getByTypeAndTime(startTime, endTime, accountIdList); return byTypeAndTime; } + + @Override + @Transactional(rollbackFor = Exception.class) + public GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO) { + String bucket = userBucket; + Long accountId = UserContext.getUserHolder().getId(); + log.info("imageToSketch parameter : {}", imageToSketchDTO); + + CollectionElement collectionElement = collectionElementService.getById(imageToSketchDTO.getElementId()); + String imagePath = collectionElement.getUrl(); + + log.info(minioUtil.getPreSignedUrl(imagePath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + String imageName = UUID.randomUUID().toString(); + String objectName = accountId + "/imageToSketch/" + imageName; + String style = imageToSketchDTO.getStyle(); + String styleCode = style.equals(SketchStyle.THICK.getValue()) ? "1" : + style.equals(SketchStyle.MEDIUM.getValue()) ? "2" : + style.equals(SketchStyle.THIN.getValue()) ? "3" : "Custom"; + String styleImage; + if (!Objects.isNull(imageToSketchDTO.getStyleImageId())){ + CollectionElement styleElement = collectionElementService.getById(imageToSketchDTO.getElementId()); + styleImage = styleElement.getUrl(); + } else { + styleImage = ""; + } + String sketchPath = pythonService.imageToSketch(imagePath, bucket, objectName, styleCode, styleImage); + + // 存DB + Generate generate = new Generate(); + generate.setAccountId(accountId); + generate.setUniqueId(String.valueOf(0)); + generate.setLevel1Type(SKETCH_BOARD.getRealName()); + generate.setLevel2Type("ImageToSketch"); + generate.setElementSource("collection"); + generate.setElementId(imageToSketchDTO.getElementId()); + generate.setGenerateType("image"); + generate.setSketchStyle(styleCode); + generate.setStyleImageElementId(imageToSketchDTO.getElementId()); + generate.setCreateDate(new Date()); + baseMapper.insert(generate); + + // 将生成结果存入DB + GenerateDetail generateDetail = new GenerateDetail(); + generateDetail.setGenerateId(generate.getId()); + generateDetail.setUrl(sketchPath); + generateDetail.setIsLike((byte)0); + generateDetail.setMd5(MD5Utils.encryptFile(minioUtil.getPreSignedUrl(sketchPath, 24 * 60), Boolean.FALSE)); + generateDetail.setCreateDate(LocalDateTime.now()); + generateDetailMapper.insert(generateDetail); + + String clothCategory = pythonService.getClothCategory(sketchPath, imageToSketchDTO.getGender()); + clothCategory = BusinessException.getMessageFromResource(clothCategory.toUpperCase()); + + return new GenerateResultVO(generateDetail.getId(), minioUtil.getPreSignedUrl(sketchPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME), "Success", clothCategory); + } + + // 对提取出来的sketch做调整 + // 输入 base64,以及 性别 分类,将图片添加到library + @Override + @Transactional(rollbackFor = Exception.class) + public CollectionElementVO modifySketch(GenerateModifyDTO generateModifyDTO) { + log.info("修改提取出的sketch,并加入到library"); + Long accountId = UserContext.getUserHolder().getId(); + String base64 = generateModifyDTO.getBase64(); + String gender = generateModifyDTO.getGender(); + String category = generateModifyDTO.getCategory(); + + // 将base64上传到minio + String path = accountId + "/sketchboard/" + gender.toLowerCase() + "/" + category + "/" + UUID.randomUUID(); + String minioPath = minioUtil.base64UploadToPath(base64, userBucket, path); + + log.info("修改后的图片 : {}", minioPath); + + // 存入db 保存到t_collection_element + CollectionElement collectionElement = new CollectionElement(); + collectionElement.setAccountId(accountId); + collectionElement.setCollectionId(0L); + collectionElement.setLevel1Type(SKETCH_BOARD.getRealName()); + collectionElement.setLevel2Type(generateModifyDTO.getCategory()); + collectionElement.setName(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); + collectionElement.setUrl(minioPath); + collectionElement.setHasPin((byte)0); + collectionElement.setMd5(MD5Utils.encryptFile(minioUtil.getPreSignedUrl(minioPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME), Boolean.FALSE)); + collectionElement.setCreateDate(new Date()); + collectionElementService.save(collectionElement); + + CollectionElementVO collectionElementVO = CopyUtil.copyObject(collectionElement, CollectionElementVO.class); + collectionElementVO.setMinIOPath(collectionElementVO.getUrl()); + collectionElementVO.setUrl(minioUtil.getPreSignedUrl(collectionElementVO.getUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + collectionElementVO.setDesignType(DesignTypeEnum.COLLECTION.getRealName()); + return collectionElementVO; + } } diff --git a/src/main/java/com/ai/da/service/impl/PortfolioServiceImpl.java b/src/main/java/com/ai/da/service/impl/PortfolioServiceImpl.java index 04948a34..b59a7479 100644 --- a/src/main/java/com/ai/da/service/impl/PortfolioServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/PortfolioServiceImpl.java @@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.base.Function; import io.netty.util.internal.StringUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -35,6 +36,7 @@ import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +@Slf4j @Service public class PortfolioServiceImpl extends ServiceImpl implements PortfolioService { @@ -76,6 +78,7 @@ public class PortfolioServiceImpl extends ServiceImpl()); } } + List topThree = new ArrayList<>(); + + if (query.getPage() == 1 && + (query.getGetMyPortfolio() != 1 || query.getGetLikePortfolio() != 1)) { + List topThreeLike = getTopThreeLikeFromRedis(RedisUtil.PORTFOLIO_LIKE_KEY); + log.info("top three like 的作品集的id : {}", topThreeLike); + List topThreeView = getTopThreeViewFromRedis(RedisUtil.PORTFOLIO_VIEW_KEY); + log.info("top three view 的作品集的id : {}", topThreeView); + QueryWrapper queryLike = new QueryWrapper<>(); + queryLike.in("id", topThreeLike); + QueryWrapper queryView = new QueryWrapper<>(); + queryView.in("id", topThreeView); + List topThreeLikePortfolio = baseMapper.selectList(queryLike); + List topThreeViewPortfolio = baseMapper.selectList(queryView); + topThree.addAll(topThreeLikePortfolio); + topThree.addAll(topThreeViewPortfolio); + } + qw.lambda().orderByDesc(Portfolio::getUpdateDate); IPage page = portfolioMapper.selectPage(new Page<>(query.getPage(), query.getSize()), qw); + if (!topThree.isEmpty()) { + List records = page.getRecords(); + records.addAll(0, topThree); + page.setRecords(records); + } IPage convert = page.convert((Function) portfolio -> { if (portfolio != null) { PortfolioVO vo = CopyUtil.copyObject(portfolio, PortfolioVO.class); @@ -670,8 +696,8 @@ public class PortfolioServiceImpl extends ServiceImpl designItemDetailPrintQueryWrapper = new QueryWrapper<>(); designItemDetailPrintQueryWrapper.lambda().eq(DesignItemDetailPrint::getDesignItemDetailId, designItemDetailIdOld); - DesignItemDetailPrint designItemDetailPrint = designItemDetailPrintMapper.selectOne(designItemDetailPrintQueryWrapper); - if (Objects.nonNull(designItemDetailPrint)) { + List designItemDetailPrintList = designItemDetailPrintMapper.selectList(designItemDetailPrintQueryWrapper); + for (DesignItemDetailPrint designItemDetailPrint : designItemDetailPrintList) { designItemDetailPrint.setId(null); designItemDetailPrint.setDesignItemDetailId(designItemDetailIdNew); designItemDetailPrintMapper.insert(designItemDetailPrint); @@ -960,6 +986,65 @@ public class PortfolioServiceImpl extends ServiceImpl getTopThreeLikeFromRedis(String prefix) { + // 获取所有与 PORTFOLIO_LIKE_KEY 相关的 keys + Set keys = redisUtil.getKeysFromString(prefix + "*"); + + List> portfolioSizes = new ArrayList<>(); + + if (keys != null) { + for (String key : keys) { + // 获取 Set 的 size + Long size = redisUtil.getSize(key); + // 保存 key 和 size + portfolioSizes.add(new AbstractMap.SimpleEntry<>(key, size)); + } + // 按 size 倒序排序 + portfolioSizes.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue())); + // 获取 size 最大的前三个 + List top3PortfolioIds = portfolioSizes.stream() + .limit(3) + .map(Map.Entry::getKey) + .map(key -> key.replace(prefix, "")) // 去掉前缀,获取 portfolioId + .map(Long::valueOf) + .collect(Collectors.toList()); + // 输出 top3PortfolioIds + top3PortfolioIds.forEach(System.out::println); + return top3PortfolioIds; + } + return null; + } + + private List getTopThreeViewFromRedis(String prefix) { + // Step 1: Get all keys with the specific prefix + Set keys = redisUtil.getKeysFromString(prefix + "*"); +// Step 2: Create a map to store portfolioId and its corresponding value + Map portfolioViews = new HashMap<>(); + if (keys != null) { + for (String key : keys) { + // Get the value associated with the key + Long value = redisUtil.getViewCount(key); + if (!Objects.isNull(value)) { + // Extract the portfolioId from the key (assuming the key structure is consistent) + Long portfolioId = Long.valueOf(key.replace(prefix, "")); + portfolioViews.put(portfolioId, value); + } + } + } +// Step 3: Find the top 3 portfolio IDs with the largest values + if (!portfolioViews.isEmpty()){ + List top3PortfolioIds = portfolioViews.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(3) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + System.out.println("Top 3 Portfolio IDs: " + top3PortfolioIds); + return top3PortfolioIds; + } + return null; + } + public void follow(Long followeeId) { Long accountId = UserContext.getUserHolder().getId(); // 1、不能关注自己 diff --git a/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java b/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java index 63585f19..03ed3d69 100644 --- a/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java @@ -79,7 +79,6 @@ public class SuperResolutionServiceImpl extends ServiceImpl uuidList = new ArrayList<>(); for (SuperResolutionDTO superResolutionDTO : superResolutionDTOList) { - // todo 校验倍率是否是2的幂次(前端已做) // 2、生成唯一id 使用uuid 由于uuid重复的几率很小很小,故这里取消验证uuid是否已存在 String uuid = UUID.randomUUID().toString(); diff --git a/src/main/java/com/ai/da/service/impl/TDesignPythonOutfitDetailServiceImpl.java b/src/main/java/com/ai/da/service/impl/TDesignPythonOutfitDetailServiceImpl.java index 8604dccf..5003523e 100644 --- a/src/main/java/com/ai/da/service/impl/TDesignPythonOutfitDetailServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/TDesignPythonOutfitDetailServiceImpl.java @@ -18,6 +18,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import javax.annotation.Resource; import java.util.Arrays; +import java.util.Date; import java.util.List; import java.util.Objects; @@ -106,18 +107,21 @@ public class TDesignPythonOutfitDetailServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); -// queryWrapper.eq("design_python_outfit_id",designPythonOutfitId); -// TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail(); -// tDesignPythonOutfitDetail.setIsDeleted(1); + public void deleteByDesignPythonOutfitIdLogical(Long designPythonOutfitId) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("design_python_outfit_id", designPythonOutfitId); updateWrapper.set("is_deleted", (byte) 1); + updateWrapper.set("update_date", new Date()); baseMapper.update(null, updateWrapper); } + @Override + public void deleteByDesignPythonOutfitIdPhysical(Long designPythonOutfitId) { + // 执行物理删除 + baseMapper.deleteByDesignPythonOutfitIdPhysical(designPythonOutfitId); + } + @Override public void setDesignPythonOutfitDetailPriority(List details){ diff --git a/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java b/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java index 57ba60c5..59d7e9db 100644 --- a/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/UserLikeServiceImpl.java @@ -70,8 +70,11 @@ public class UserLikeServiceImpl extends ServiceImpl i public UserLike getByDesignItemId(Long designItemId){ QueryWrapper qw = new QueryWrapper<>(); qw.eq("design_item_id",designItemId); - - return baseMapper.selectOne(qw); + List userLikes = baseMapper.selectList(qw); + if (!userLikes.isEmpty()){ + return baseMapper.selectList(qw).get(0); + } + return null; } @Override @@ -91,21 +94,4 @@ public class UserLikeServiceImpl extends ServiceImpl i return userLikeMapper.selectList(qw); } - @Override - public List> getHistoryLikeWithGradient(){ - List> historyLikeWithGradient = baseMapper.getHistoryLikeWithGradient(); - return historyLikeWithGradient.stream() - .map(map -> { - Map newMap = new HashMap<>(); - if (map.containsKey("design_item_id")) { - newMap.put("designItemId", map.get("design_item_id")); - } - if (map.containsKey("design_outfit_id")) { - newMap.put("designPythonOutfitId", map.get("design_outfit_id")); - } - return newMap; - }) - .collect(Collectors.toList()); - } - } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 974fee23..8550475d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,7 +2,7 @@ #spring.profiles.active=test #����application-prod�ļ�(��������) -#spring.profiles.active=prod +spring.profiles.active=prod #����application-dev�ļ�(��������) -spring.profiles.active=dev +#spring.profiles.active=dev diff --git a/src/main/resources/mapper/primary/UserLikeMapper.xml b/src/main/resources/mapper/primary/UserLikeMapper.xml index 5067caab..41567bf0 100644 --- a/src/main/resources/mapper/primary/UserLikeMapper.xml +++ b/src/main/resources/mapper/primary/UserLikeMapper.xml @@ -103,6 +103,28 @@ a.design_outfit_id; + + diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 3e1f25ca..8985db45 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -208,4 +208,11 @@ BUTTON=Button BELT=Belt CORSAGE=Corsage ZIPPER=Zipper -POCKET=Pocket \ No newline at end of file +POCKET=Pocket + +THICK=Thick Lines +MEDIUM=Medium Lines +THIN=Thin lines + +GENERATE=Generate Sketch +EXTRACT=Extract Sketch \ No newline at end of file diff --git a/src/main/resources/messages_zh.properties b/src/main/resources/messages_zh.properties index 1a5d4a6a..4219585f 100644 --- a/src/main/resources/messages_zh.properties +++ b/src/main/resources/messages_zh.properties @@ -201,4 +201,11 @@ BUTTON=纽扣 BELT=腰带 CORSAGE=胸花 ZIPPER=拉链 -POCKET=口袋 \ No newline at end of file +POCKET=口袋 + +THICK=粗线条 +MEDIUM=中线条 +THIN=细线条 + +GENERATE=生成线稿 +EXTRACT=提取线稿 \ No newline at end of file