Merge branch 'dev/dev_xp' into dev/dev

This commit is contained in:
2024-09-25 11:31:40 +08:00
33 changed files with 2242 additions and 1935 deletions

View File

@@ -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() {
}

View File

@@ -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<Account> 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);

View File

@@ -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);
}
}

View File

@@ -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<String> getMultiValue(Set<String> 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);
}
}

View File

@@ -82,17 +82,16 @@ public class DesignDetailController {
}
@ApiOperation(value = "mask数据兼容")
@PostMapping("/convertWithoutGradient")
@GetMapping("/convertWithoutGradient")
public Response<String> convertHistoryMaskWithoutGradient(){
designItemService.convertHistoryMaskWithoutGradient();
return Response.success("success");
}
@Resource
private UserLikeService userLikeService;
@ApiOperation(value = "获取历史like中包含有渐变色的design")
@PostMapping("/getHistoryLikeWithGradient")
public Response<List<Map<String, Long>>> getHistoryLikeWithGradient(){
return Response.success(userLikeService.getHistoryLikeWithGradient());
@ApiOperation(value = "mask数据库路径更新")
@GetMapping("/updateMaskUrl")
public Response<String> updateMaskUrl(){
designItemService.updateMaskUrl();
return Response.success("success");
}
}

View File

@@ -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<GenerateResultVO> imageToSketch(@Valid @RequestBody ImageToSketchDTO imageToSketchDTO) {
return Response.success(generateService.imageToSketch(imageToSketchDTO));
}
// modifySketch
@ApiOperation(value = "modifySketch")
@PostMapping("/modifySketch")
public Response<CollectionElementVO> modifySketch(@Valid @RequestBody GenerateModifyDTO generateModifyDTO) {
return Response.success(generateService.modifySketch(generateModifyDTO));
}
}

View File

@@ -104,9 +104,9 @@ public class SavedCollectionController {
}
List<Long> groupIds = page.getRecords().stream().map(UserLikeGroup::getId).collect(Collectors.toList());
List<UserLikeVO> 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<Long, List<UserLikeVO>> 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<UserLikeVO> 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<UserLikeVO> 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());

View File

@@ -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<TDesignPyt
*/
List<TDesignPythonOutfitDetailVO> 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);
}

View File

@@ -14,8 +14,4 @@ import java.util.Map;
*/
public interface UserLikeMapper extends CommonMapper<UserLike> {
List<Map<String, Long>> getHistoryLikeWithoutGradient();
List<Map<String, Long>> getHistoryLikeWithGradient();
}

View File

@@ -72,6 +72,19 @@ public class Generate {
*/
private String seed;
/**
* 1 -> 粗
* 2 -> 中
* 3 -> 细
* custom -> 自定义
*/
private String sketchStyle;
/**
* sketch 风格参考图的collection_element_id
*/
private Long styleImageElementId;
/**
* 创建时间
*/

View File

@@ -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;
}

View File

@@ -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!")

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<String, Object> 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();
}
}
}

View File

@@ -62,4 +62,6 @@ public interface DesignItemService extends IService<DesignItem> {
Long getCountByUserAndTime(String startTime, String endTime, List<Long> accountIds);
void convertHistoryMaskWithoutGradient();
void updateMaskUrl();
}

View File

@@ -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<Generate> {
void processRelightResult(String taskId, String url, String category);
List<Map<String, Object>> getCountByUserAndTime(String startTime, String endTime, List<Long> accountIdList);
GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO);
CollectionElementVO modifySketch(GenerateModifyDTO generateModifyDTO);
}

View File

@@ -36,7 +36,9 @@ public interface ITDesignPythonOutfitDetailService extends IService<TDesignPytho
DesignPythonOutfitVO convertToDesignPythonOutfitVO(TDesignPythonOutfitDetail detail, List<Long> offset);
void deleteByDesignPythonOutfitId(Long designPythonOutfitId);
void deleteByDesignPythonOutfitIdLogical(Long designPythonOutfitId);
void deleteByDesignPythonOutfitIdPhysical(Long designPythonOutfitId);
void setDesignPythonOutfitDetailPriority(List<TDesignPythonOutfitDetail> details);

View File

@@ -26,6 +26,4 @@ public interface UserLikeService extends IService<UserLike> {
void updateDate(Long designItemId,String timeZone);
List<UserLike> getUserLikeList(Long id);
List<Map<String, Long>> getHistoryLikeWithGradient();
}

File diff suppressed because it is too large Load Diff

View File

@@ -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<DesignItemMapper, DesignI
@Value("${minio.bucketName.clothing}")
private String clothingBucket;
@Autowired
private RedisUtil redisUtil;
@Override
public Long saveOne(DesignItem designItem) {
@@ -372,7 +380,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
designPythonOutfitService.updateById(designPythonOutfit);
// 6、删除designPythonOutfitDetail表中原始的图层信息逻辑删除
designPythonOutfitDetailService.deleteByDesignPythonOutfitId(designPythonOutfit.getId());
designPythonOutfitDetailService.deleteByDesignPythonOutfitIdLogical(designPythonOutfit.getId());
// 7、将新生成的图层信息存入designPythonOutfitDetail表
JSONArray layers = outfit.getJSONArray("layers");
@@ -497,8 +505,15 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
// 所以这里选择使用system或collection相同的地址只是放在不同的桶这样能保证图片服务器上,类似的sketch不会存在很多
sketchBase64ToPath(designSingleIncludeLayersDTO);
// todo 将标注后的mask上传到minio,并将minio地址传给python端
maskBase64ToPath(designSingleIncludeLayersDTO);
// 将标注后的mask上传到minio,并将minio地址传给python端
// todo 如何当前design使用的仍是旧的mask 则置maskUrl为null
// 1、查询当前design item在不在history中
UserLike userLikeDesign = userLikeService.getByDesignItemId(designItem.getId());
Boolean setNull = Boolean.FALSE;
if (!Objects.isNull(userLikeDesign) && userLikeDesign.getConverted() == 0){
setNull = Boolean.TRUE;
}
maskBase64ToPath(designSingleIncludeLayersDTO, setNull);
// 组装入参
DesignPythonObjects objects = pythonService.covertDesignSingleParam(
@@ -581,22 +596,26 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
});
}
private void maskBase64ToPath(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO){
private void maskBase64ToPath(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO, Boolean setNull){
designSingleIncludeLayersDTO.getDesignSingleItemDTOList().forEach(item -> {
// 如果sketch截图不为空则将该截图上传并替换path
if (!StringUtil.isNullOrEmpty(item.getMaskUrl())){
// 由于前端不好处理这块所以当mask没有做任何修改的时候仍然会传原始mask的minio地址
if (!item.getMaskUrl().startsWith("data:image") && item.getMaskUrl().startsWith("https://")){
// 当没有修改mask时还是用之前的mask地址
item.setMaskUrl(item.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<DesignItemMapper, DesignI
}
}
// todo 1、新增一个字段 用于记录历史like的design中 没有新的mask的design
// 2、获取design detail时当其design_item_id和design_python_outfit_id在like中时重新调用design并更新标志字段
@Resource
private UserLikeMapper userLikeMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void convertHistoryMaskWithoutGradient(){
// 1、获取全部需要转换的designOutfitId
// 1、获取t_user_like表中design_item_id不为-1的所有design_item_id, design_outfit_id
QueryWrapper<UserLike> queryWrapper = new QueryWrapper<>();
queryWrapper.ne("design_item_id", -1)
.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<Map<String, Long>> historyLikeWithoutGradient = userLikeMapper.getHistoryLikeWithoutGradient();
log.info("historyLikeWithoutGradient total count : {}", historyLikeWithoutGradient.size());
// 遍历list
// 先试一下刷新10条需要花费的时间
List<UserLike> userLikes = userLikeMapper.selectList(queryWrapper);
// List<Map<String, Object>> userLikes = userLikeMapper.selectMaps(queryWrapper);
log.info("userLike 总数 {}", userLikes.size());
// 用于存储结果
List<String[]> pairs = new ArrayList<>();
AtomicInteger count = new AtomicInteger();
/*Map<String, Long> userLikeMap = historyLikeWithoutGradient.get(0);
log.info("test 替换mask" + userLikeMap.toString());
// 2、查询指定designOutfitId对应的mask
userLikes.forEach(item -> {
// 存储数据,按前缀分组
Map<Integer, Map<String, String>> 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<TDesignPythonOutfitDetail> designPythonOutfitDetails = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designOutfitId);
List<DesignItemDetail> designItemDetails = designItemDetailService.selectByDesignItemId(designItemId);
// 为没有优先级的sketch添加优先级
designItemDetailService.setDesignItemDetailPriority(designItemDetails);
// 为没有优先级的图层添加优先级
designPythonOutfitDetailService.setDesignPythonOutfitDetailPriority(designPythonOutfitDetails);
Map<Integer, String> 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<String, Long> 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<Integer, Map<String, String>> entry : groupedData.entrySet()) {
Map<String, String> 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<SysFileVO> modelSysFile = sysFileService.getByUrlList(Collections.singletonList(modelPath));
if (modelSysFile.isEmpty()){
log.error("cannot find model 【{}】 in t_sys_file ", modelPath);
return null;
}else {
gender = modelSysFile.get(0).getLevel2Type();
}
resp.setDesignItemId(designItemId);
resp.setGender(gender);
resp.setIsPreview(Boolean.FALSE);
resp.setProcessId(String.valueOf(userId));
resp.setTimeZone("Etc/GMT-8");
List<DesignSingleItemDTO> 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<UserLike> 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<UserLike> userLikes = userLikeMapper.selectList(queryWrapper);
log.info("userLike 总数 {}", userLikes.size());
ArrayList<TDesignPythonOutfitDetail> tDesignPythonOutfitDetails = new ArrayList<>();
// 2、查询指定designOutfitId对应的mask
userLikes.forEach(item -> {
Long designOutfitId = item.getDesignOutfitId();
// 存储以front结尾的mask路径
Map<String, String> frontMaskMap = new HashMap<>();
HashMap<String, Long> backMaskIdMap = new HashMap<>();
List<TDesignPythonOutfitDetail> 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<TDesignPythonOutfitDetail> 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<String, String> 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("更新完成");
}
}

View File

@@ -813,9 +813,9 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
// return new DesignLikeVO();
// }
List<CollectionElement> 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<DesignItemDetail> 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<DesignMapper, Design> impleme
if (CollectionUtils.isEmpty(hasCollections)) {
return null;
}
List<Long> oldIds = oldElements.stream().map(CollectionElement::getId).collect(Collectors.toList());
List<Long> elementIds = hasCollections.stream().map(DesignItemDetail::getCollectionElementId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(oldElements)) {
return elementIds;
}
List<Long> oldIds = oldElements.stream().map(CollectionElement::getId).collect(Collectors.toList());
//本次新增collection个数
List<Long> adds = elementIds.stream().filter(id -> !oldIds.contains(id)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(adds)) {
@@ -934,7 +937,7 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
List<UserLikeVO> 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<DesignMapper, Design> impleme
response.setSingleOverall(design.getSingleOverall());
response.setSwitchCategory(design.getSwitchCategory());
response.setDesignItemId(designItemId);
// response.setDesignItemUrl(designItem.getDesignUrl());
response.setHighDesignUrl(designItem.getHighDesignUrl());
List<DesignItemDetail> 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<DesignMapper, Design> 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<DesignMapper, Design> impleme
designPythonOutfitDetailService.setDesignPythonOutfitDetailPriority(details);
details.forEach(detail -> {
// List<Long> 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<DesignMapper, Design> impleme
designItemDetailVO.setDesignItemUrl(minioUtil.getPreSignedUrl(designPythonOutfit.getDesignUrl(), 24 * 60));
// 2.1 填充clothes
designItemDetailVO.getClothes().forEach(c -> {
// String type = c.getType().toLowerCase();
// List<DesignPythonOutfitVO> outfitVOS = detailsVO.stream().filter((detail -> detail.getImageCategory().equals(type + "_back") ||
// detail.getImageCategory().equals(type + "_front"))).collect(Collectors.toList());
List<DesignPythonOutfitVO> outfitVOS = detailsVO.stream().filter(detail -> detail.getPriority().equals(c.getPriority())).collect(Collectors.toList());
c.setLayersObject(outfitVOS);
});
// 2.2 填充others

View File

@@ -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<GenerateMapper, Generate> 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<GenerateMapper, Generate> 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<GenerateMapper, Generate> 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<GenerateMapper, Generate> 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<GenerateMapper, Generate> i
@Resource
private GenerateMapper generateMapper;
public List<Map<String, Object>> getCountByUserAndTime(String startTime, String endTime, List<Long> accountIdList) {
List<Map<String, Object>> 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;
}
}

View File

@@ -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<PortfolioMapper, Portfolio> implements PortfolioService {
@@ -76,6 +78,7 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
@Resource
private DesignItemDetailPrintMapper designItemDetailPrintMapper;
@Resource
private MinioUtil minioUtil;
@@ -436,8 +439,31 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
return PageBaseResponse.success(new Page<>());
}
}
List<Portfolio> topThree = new ArrayList<>();
if (query.getPage() == 1 &&
(query.getGetMyPortfolio() != 1 || query.getGetLikePortfolio() != 1)) {
List<Long> topThreeLike = getTopThreeLikeFromRedis(RedisUtil.PORTFOLIO_LIKE_KEY);
log.info("top three like 的作品集的id : {}", topThreeLike);
List<Long> topThreeView = getTopThreeViewFromRedis(RedisUtil.PORTFOLIO_VIEW_KEY);
log.info("top three view 的作品集的id : {}", topThreeView);
QueryWrapper<Portfolio> queryLike = new QueryWrapper<>();
queryLike.in("id", topThreeLike);
QueryWrapper<Portfolio> queryView = new QueryWrapper<>();
queryView.in("id", topThreeView);
List<Portfolio> topThreeLikePortfolio = baseMapper.selectList(queryLike);
List<Portfolio> topThreeViewPortfolio = baseMapper.selectList(queryView);
topThree.addAll(topThreeLikePortfolio);
topThree.addAll(topThreeViewPortfolio);
}
qw.lambda().orderByDesc(Portfolio::getUpdateDate);
IPage<Portfolio> page = portfolioMapper.selectPage(new Page<>(query.getPage(), query.getSize()), qw);
if (!topThree.isEmpty()) {
List<Portfolio> records = page.getRecords();
records.addAll(0, topThree);
page.setRecords(records);
}
IPage<PortfolioVO> convert = page.convert((Function<Portfolio, PortfolioVO>) portfolio -> {
if (portfolio != null) {
PortfolioVO vo = CopyUtil.copyObject(portfolio, PortfolioVO.class);
@@ -670,8 +696,8 @@ public class PortfolioServiceImpl extends ServiceImpl<PortfolioMapper, Portfolio
Long designItemDetailIdNew = designItemDetailOld.getId();
QueryWrapper<DesignItemDetailPrint> designItemDetailPrintQueryWrapper = new QueryWrapper<>();
designItemDetailPrintQueryWrapper.lambda().eq(DesignItemDetailPrint::getDesignItemDetailId, designItemDetailIdOld);
DesignItemDetailPrint designItemDetailPrint = designItemDetailPrintMapper.selectOne(designItemDetailPrintQueryWrapper);
if (Objects.nonNull(designItemDetailPrint)) {
List<DesignItemDetailPrint> 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<PortfolioMapper, Portfolio
return resultList;
}
private List<Long> getTopThreeLikeFromRedis(String prefix) {
// 获取所有与 PORTFOLIO_LIKE_KEY 相关的 keys
Set<String> keys = redisUtil.getKeysFromString(prefix + "*");
List<Map.Entry<String, Long>> 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<Long> 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<Long> getTopThreeViewFromRedis(String prefix) {
// Step 1: Get all keys with the specific prefix
Set<String> keys = redisUtil.getKeysFromString(prefix + "*");
// Step 2: Create a map to store portfolioId and its corresponding value
Map<Long, Long> 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<Long> top3PortfolioIds = portfolioViews.entrySet().stream()
.sorted(Map.Entry.<Long, Long>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、不能关注自己

View File

@@ -79,7 +79,6 @@ public class SuperResolutionServiceImpl extends ServiceImpl<TaskListMapper, Task
ArrayList<String> uuidList = new ArrayList<>();
for (SuperResolutionDTO superResolutionDTO : superResolutionDTOList) {
// todo 校验倍率是否是2的幂次(前端已做)
// 2、生成唯一id 使用uuid 由于uuid重复的几率很小很小故这里取消验证uuid是否已存在
String uuid = UUID.randomUUID().toString();

View File

@@ -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<TDesignPyt
}
@Override
public void deleteByDesignPythonOutfitId(Long designPythonOutfitId) {
// QueryWrapper<TDesignPythonOutfitDetail> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("design_python_outfit_id",designPythonOutfitId);
// TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail();
// tDesignPythonOutfitDetail.setIsDeleted(1);
public void deleteByDesignPythonOutfitIdLogical(Long designPythonOutfitId) {
UpdateWrapper<TDesignPythonOutfitDetail> 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<TDesignPythonOutfitDetail> details){

View File

@@ -70,8 +70,11 @@ public class UserLikeServiceImpl extends ServiceImpl<UserLikeMapper, UserLike> i
public UserLike getByDesignItemId(Long designItemId){
QueryWrapper<UserLike> qw = new QueryWrapper<>();
qw.eq("design_item_id",designItemId);
return baseMapper.selectOne(qw);
List<UserLike> 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<UserLikeMapper, UserLike> i
return userLikeMapper.selectList(qw);
}
@Override
public List<Map<String, Long>> getHistoryLikeWithGradient(){
List<Map<String, Long>> historyLikeWithGradient = baseMapper.getHistoryLikeWithGradient();
return historyLikeWithGradient.stream()
.map(map -> {
Map<String, Long> 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());
}
}