Merge remote-tracking branch 'origin/develop' into dev_shb
# Conflicts: # src/main/java/com/ai/da/mapper/entity/SysFile.java
This commit is contained in:
@@ -4,56 +4,28 @@ public class PantoneUtils {
|
||||
|
||||
public static int[] rgbToHsv(int[] rgb) {
|
||||
//切割rgb数组
|
||||
int R = rgb[0];
|
||||
int G = rgb[1];
|
||||
int B = rgb[2];
|
||||
//公式运算 /255
|
||||
float R_1 = R / 255f;
|
||||
float G_1 = G / 255f;
|
||||
float B_1 = B / 255f;
|
||||
//重新拼接运算用数组
|
||||
float[] all = {R_1, G_1, B_1};
|
||||
float max = all[0];
|
||||
float min = all[0];
|
||||
//循环查找最大值和最小值
|
||||
for (int i = 0; i < all.length; i++) {
|
||||
if (max <= all[i]) {
|
||||
max = all[i];
|
||||
}
|
||||
if (min >= all[i]) {
|
||||
min = all[i];
|
||||
}
|
||||
}
|
||||
float C_max = max;
|
||||
float C_min = min;
|
||||
//计算差值
|
||||
float diff = C_max - C_min;
|
||||
float hue = 0f;
|
||||
//判断情况计算色调H
|
||||
if (diff == 0f) {
|
||||
hue = 0f;
|
||||
} else {
|
||||
if (C_max == R_1) {
|
||||
hue = (((G_1 - B_1) / diff) % 6) * 60f;
|
||||
}
|
||||
if (C_max == G_1) {
|
||||
hue = (((B_1 - R_1) / diff) + 2f) * 60f;
|
||||
}
|
||||
if (C_max == B_1) {
|
||||
hue = (((R_1 - G_1) / diff) + 4f) * 60f;
|
||||
}
|
||||
}
|
||||
//计算饱和度S
|
||||
float saturation;
|
||||
if (C_max == 0f) {
|
||||
saturation = 0f;
|
||||
} else {
|
||||
saturation = diff / C_max;
|
||||
}
|
||||
//计算明度V
|
||||
float value = C_max;
|
||||
int[] result = {Math.round(hue), Math.round(saturation * 100), Math.round(value * 100)};
|
||||
return result;
|
||||
int red = rgb[0];
|
||||
int green= rgb[1];
|
||||
int blue = rgb[2];
|
||||
|
||||
float r = (float) red / 255;
|
||||
float g = (float) green / 255;
|
||||
float b = (float) blue / 255;
|
||||
|
||||
float min = Math.min(Math.min(r, g), b);
|
||||
|
||||
float[] hsv = {60, 0, Math.max(Math.max(r, g), b)};
|
||||
|
||||
hsv[1] = (hsv[2] == 0) ? 0 : 1 - min / hsv[2];
|
||||
|
||||
hsv[0] = 60 * (
|
||||
(hsv[2] == min) ? Float.NaN :
|
||||
(hsv[2] == r) ? (g - b) / (hsv[2] - min) + ((g < b) ? 6 : 0) :
|
||||
(hsv[2] == g) ? (b - r) / (hsv[2] - min) + 2:
|
||||
(r - g) / (hsv[2] - min) + 4
|
||||
);
|
||||
|
||||
return new int[]{Math.round(hsv[0]), Math.round(hsv[1] * 100), Math.round(hsv[2] * 100)};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@Api(tags = "design Detail模块")
|
||||
@@ -68,5 +69,9 @@ public class DesignDetailController {
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "编辑图层大小和位置")
|
||||
@PostMapping("/editLayers")
|
||||
public Response<ComposeLayersVO> editPositionAndScale(@Valid @RequestBody EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException {
|
||||
return Response.success(designItemService.editLayersPositionAndScale(positionAndScaleVO));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ai.da.mapper;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.entity.DesignItemDetailPrint;
|
||||
|
||||
|
||||
public interface DesignItemDetailPrintMapper extends CommonMapper<DesignItemDetailPrint> {
|
||||
}
|
||||
@@ -93,4 +93,9 @@ public class DesignItemDetail implements Serializable {
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateDate;
|
||||
|
||||
/**
|
||||
* 逻辑删除 1->删除 0->未删除 默认null
|
||||
*/
|
||||
private Byte isDeleted;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ai.da.mapper.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("t_design_item_detail_print")
|
||||
public class DesignItemDetailPrint {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
/**
|
||||
* 关联t_design_item_detail表ID
|
||||
*/
|
||||
private Long designItemDetailId;
|
||||
/**
|
||||
* 印花路径
|
||||
*/
|
||||
private String path;
|
||||
/**
|
||||
* 印花位置
|
||||
*/
|
||||
private String position;
|
||||
/**
|
||||
* 印花缩放比例
|
||||
*/
|
||||
private Double scale;
|
||||
/**
|
||||
* 印花旋转角度
|
||||
*/
|
||||
private Double angle;
|
||||
/**
|
||||
* 印花优先级(多个印花)
|
||||
*/
|
||||
private Integer priority;
|
||||
/**
|
||||
* 选择single or overall 模式
|
||||
*/
|
||||
private String singleOrOverall;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createDate;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateDate;
|
||||
}
|
||||
@@ -67,8 +67,6 @@ public class SysFile implements Serializable {
|
||||
*/
|
||||
private Date updateDate;
|
||||
|
||||
// private Integer isCopy;
|
||||
|
||||
public SysFile() {
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@ public class TDesignPythonOutfitDetail implements Serializable {
|
||||
*/
|
||||
@ApiModelProperty(value = "位置")
|
||||
private String position;
|
||||
/**
|
||||
* 图层缩放大小
|
||||
*/
|
||||
@ApiModelProperty(value = "图层缩放大小")
|
||||
private String scale;
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@ import lombok.Data;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
public class DesignSingleItemDTO {
|
||||
public class DesignSingleItemDTO {
|
||||
|
||||
@NotBlank(message = "id cannot be empty!")
|
||||
@ApiModelProperty("切换图片对应的id")
|
||||
@@ -16,10 +16,10 @@ public class DesignSingleItemDTO {
|
||||
@ApiModelProperty("生成item实际对应的类型 有:outwear,dress,blouse,skirt,trousers Shoes Hairstyle Earring")
|
||||
private String type;
|
||||
|
||||
@NotBlank(message = "path cannot be empty!")
|
||||
@ApiModelProperty("对应的图片的绝对路径")
|
||||
@ApiModelProperty("对应的图片的minIO路径")
|
||||
private String path;
|
||||
|
||||
@NotBlank(message = "color cannot be empty!")
|
||||
@ApiModelProperty("颜色 存 RGB值 中间空格分隔 比如 \"58 58 169\"")
|
||||
private String color;
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import java.util.List;
|
||||
@ApiModel("design single 印花请求信息")
|
||||
public class DesignSinglePrintDTO {
|
||||
|
||||
@ApiModelProperty("印花url")
|
||||
private String path;
|
||||
// @ApiModelProperty("印花url")
|
||||
// private String path;
|
||||
|
||||
@ApiModelProperty("single -> true,overall -> false")
|
||||
private Boolean ifSingle;
|
||||
@@ -20,4 +20,6 @@ public class DesignSinglePrintDTO {
|
||||
@ApiModelProperty("印花详细")
|
||||
private List<DesignSinglePrint> prints;
|
||||
|
||||
public DesignSinglePrintDTO() {
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/ai/da/model/vo/ComposeLayersVO.java
Normal file
21
src/main/java/com/ai/da/model/vo/ComposeLayersVO.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ApiModel("编辑图层位置大小,合成图层")
|
||||
public class ComposeLayersVO {
|
||||
|
||||
@ApiModelProperty("designItemId")
|
||||
private Long designItemId;
|
||||
|
||||
@ApiModelProperty("图层信息")
|
||||
private List<DesignPythonOutfitVO> layers;
|
||||
|
||||
@ApiModelProperty("合成图")
|
||||
private String designItemUrl;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import com.ai.da.python.vo.DesignPythonItemPrint;
|
||||
import com.ai.da.model.dto.DesignSinglePrintDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -11,6 +11,9 @@ import java.util.List;
|
||||
@ApiModel("designItem detail clothes 响应")
|
||||
public class DesignItemClothesDetailVO {
|
||||
|
||||
/**
|
||||
* designItemDetail对应的Id
|
||||
*/
|
||||
@ApiModelProperty("对应的上游id")
|
||||
private Long id;
|
||||
|
||||
@@ -20,15 +23,21 @@ public class DesignItemClothesDetailVO {
|
||||
@ApiModelProperty("上传时候对应的类型,一级类型 Moodboard Printboard Sketchboard MarketingSketch Colorboard")
|
||||
private String level1Type;
|
||||
|
||||
@ApiModelProperty("对应的图片的绝对路径")
|
||||
@ApiModelProperty("对应的图片路径")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty("对应图片minIO路径")
|
||||
private String minIOPath;
|
||||
|
||||
@ApiModelProperty(" 颜色 存 RGB值 中间空格分隔 比如 58 58 169")
|
||||
// private String color;
|
||||
private PantoneVO color;
|
||||
|
||||
@ApiModelProperty("对应的print图片对象")
|
||||
private DesignPythonItemPrint printObject;
|
||||
// @ApiModelProperty("对应的print图片对象")
|
||||
// private DesignPythonItemPrint printObject;
|
||||
|
||||
@ApiModelProperty("print详细")
|
||||
private DesignSinglePrintDTO printObject = new DesignSinglePrintDTO();
|
||||
|
||||
@ApiModelProperty("对应图层信息")
|
||||
private List<DesignPythonOutfitVO> layersObject;
|
||||
|
||||
@@ -17,9 +17,12 @@ public class DesignItemOthersDetailVO {
|
||||
@ApiModelProperty("对应的类型 有Hairstyle Earring Body")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("对应的图片的绝对路径")
|
||||
@ApiModelProperty("对应的图片路径")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty("对应图片minIO路径")
|
||||
private String minIOPath;
|
||||
|
||||
@ApiModelProperty(" 颜色 存 RGB值 中间空格分隔 比如 58 58 169")
|
||||
// private String color;
|
||||
private PantoneVO color;
|
||||
|
||||
@@ -42,4 +42,9 @@ public class DesignPythonOutfitVO {
|
||||
*/
|
||||
@ApiModelProperty(value = "位置")
|
||||
private List<Long> position;
|
||||
/**
|
||||
* 图层缩放比例
|
||||
*/
|
||||
@ApiModelProperty(value = "缩放比例")
|
||||
private Float scale = 1.0f;
|
||||
}
|
||||
|
||||
@@ -12,20 +12,41 @@ import java.util.List;
|
||||
@ApiModel("design single 印花详情")
|
||||
public class DesignSinglePrint {
|
||||
|
||||
@ApiModelProperty("印花url")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty("印花minIO路径")
|
||||
private String minIOPath;
|
||||
|
||||
@ApiModelProperty("印花位置")
|
||||
@Range(max = 1L,message = "印花坐标需用大于等于0小于等于1的数表示")
|
||||
private List<Float> location;
|
||||
private List<Double> location;
|
||||
|
||||
@ApiModelProperty("印花大小")
|
||||
@Range(max = 1,message = "印花缩放值需用大于等于0小于等于1的数表示")
|
||||
private Float scale;
|
||||
private Double scale;
|
||||
|
||||
@Range(min = -360,max = 360,message = "印花旋转角度范围为-360° ~ 360°")
|
||||
@ApiModelProperty("印花角度")
|
||||
private Float angle;
|
||||
private Double angle;
|
||||
|
||||
@Min(value = 1)
|
||||
@ApiModelProperty("印花优先级")
|
||||
private Integer priority;
|
||||
|
||||
public DesignSinglePrint() {
|
||||
}
|
||||
|
||||
public DesignSinglePrint(String path, Double scale) {
|
||||
this.path = path;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public DesignSinglePrint(String path, String minIOPath, List<Double> location, Double scale, Double angle, Integer priority) {
|
||||
this.path = path;
|
||||
this.minIOPath = minIOPath;
|
||||
this.location = location;
|
||||
this.scale = scale;
|
||||
this.angle = angle;
|
||||
this.priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,10 @@ import java.util.List;
|
||||
@Data
|
||||
public class DesignSingleVO {
|
||||
|
||||
@ApiModelProperty("designItemId")
|
||||
private Long designItemId;
|
||||
|
||||
/**
|
||||
* 全身图
|
||||
*/
|
||||
@ApiModelProperty("全身图")
|
||||
private String designItemUrl;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel("编辑图层的位置、大小")
|
||||
public class EditLayersPositionAndScaleVO {
|
||||
@ApiModelProperty("layers")
|
||||
private ComposeLayersVO layers;
|
||||
|
||||
@ApiModelProperty("时区")
|
||||
private String timeZone;
|
||||
}
|
||||
@@ -1341,7 +1341,7 @@ public class PythonService {
|
||||
designSingleItem.getType(),
|
||||
designSingleItem.getPath(),
|
||||
designSingleItem.getColor(),
|
||||
resolveDesignSinglePrint(designSingleItem .getPrintObject(), designSingleItem.getPath()),
|
||||
resolveDesignSinglePrint(designSingleItem.getPrintObject(), designSingleItem.getPath()),
|
||||
"none",
|
||||
// todo businessId 待确认
|
||||
designSingleItem.getId(),
|
||||
@@ -1363,47 +1363,55 @@ public class PythonService {
|
||||
|
||||
|
||||
private DesignPythonItemPrint resolveDesignSinglePrint(DesignSinglePrintDTO printObject, String clothesPath) {
|
||||
if (Objects.isNull(printObject.getPath()) || CollectionUtil.isEmpty(printObject.getPrints())) {
|
||||
// 没有印花时的参数设置
|
||||
if (printObject.getIfSingle().equals(Boolean.FALSE) && CollectionUtil.isEmpty(printObject.getPrints())) {
|
||||
return new DesignPythonItemPrint(new ArrayList<>(),false);
|
||||
}
|
||||
DesignPythonItemPrint print = CopyUtil.copyObject(printObject, DesignPythonItemPrint.class);
|
||||
if(StringUtils.isEmpty(printObject.getPath())){
|
||||
print.setPrint_path_list(new ArrayList<>());
|
||||
}else {
|
||||
print.setPrint_path_list(Collections.singletonList(printObject.getPath()));
|
||||
}
|
||||
if (StringUtils.isEmpty(clothesPath)
|
||||
|| "none".equals(clothesPath)
|
||||
|| CollectionUtils.isEmpty(printObject.getPrints())) {
|
||||
return print;
|
||||
}
|
||||
// if(StringUtils.isEmpty(printObject.getPath())){
|
||||
// print.setPrint_path_list(new ArrayList<>());
|
||||
// }else {
|
||||
// print.setPrint_path_list(Collections.singletonList(printObject.getPath()));
|
||||
// }
|
||||
// if (StringUtils.isEmpty(clothesPath)
|
||||
// || "none".equals(clothesPath)
|
||||
// || CollectionUtils.isEmpty(printObject.getPrints())) {
|
||||
// return print;
|
||||
// }
|
||||
//图片宽 高
|
||||
FileVO fileVO = FileUtil.getFileSize(FileUtil.getOriginFile(clothesPath));
|
||||
// FileVO fileVO = FileUtil.getFileSize(FileUtil.getOriginFile(clothesPath));
|
||||
/* List<List<Float>> locations = printObject.getLocation();
|
||||
locations.forEach(location -> {
|
||||
location.set(0, location.get(0) * fileVO.getWidth());
|
||||
location.set(1, location.get(1) * fileVO.getHigh());
|
||||
});*/
|
||||
|
||||
List<List<Float>> location = new ArrayList<>(printObject.getPrints().size());
|
||||
List<Float> scale = new ArrayList<>(printObject.getPrints().size());
|
||||
List<Float> angle = new ArrayList<>(printObject.getPrints().size());
|
||||
List<List<Double>> location = new ArrayList<>(printObject.getPrints().size());
|
||||
List<Double> scale = new ArrayList<>(printObject.getPrints().size());
|
||||
List<Double> angle = new ArrayList<>(printObject.getPrints().size());
|
||||
ArrayList<String> paths = new ArrayList<>(printObject.getPrints().size());
|
||||
|
||||
// 设置印花的位置、大小、旋转角度
|
||||
// todo 空指针
|
||||
List<DesignSinglePrint> prints = printObject.getPrints();
|
||||
prints.forEach(p -> {
|
||||
p.getLocation().set(0,p.getLocation().get(0) * fileVO.getWidth());
|
||||
p.getLocation().set(1,p.getLocation().get(1) * fileVO.getHigh());
|
||||
Integer priority = p.getPriority();
|
||||
location.add(priority - 1, p.getLocation());
|
||||
scale.add(priority - 1,p.getScale());
|
||||
angle.add(priority - 1,p.getAngle());
|
||||
log.info("本次print打点locations###{}###fileVO{}", p.getLocation(), JSON.toJSONString(fileVO));
|
||||
if (printObject.getIfSingle().equals(Boolean.FALSE)){
|
||||
scale.add(p.getScale());
|
||||
paths.add(p.getPath());
|
||||
}else {
|
||||
p.getLocation().set(0,p.getLocation().get(0));
|
||||
p.getLocation().set(1,p.getLocation().get(1));
|
||||
Integer priority = p.getPriority();
|
||||
location.add(priority - 1, p.getLocation());
|
||||
scale.add(priority - 1,p.getScale());
|
||||
angle.add(priority - 1,p.getAngle());
|
||||
paths.add(priority - 1,p.getMinIOPath());
|
||||
}
|
||||
// log.info("本次print打点locations###{}###fileVO{}", p.getLocation(), JSON.toJSONString(fileVO));
|
||||
});
|
||||
print.setLocation(location);
|
||||
print.setPrint_scale_list(scale);
|
||||
print.setPrint_angle_list(angle);
|
||||
print.setPrint_path_list(paths);
|
||||
|
||||
return print;
|
||||
}
|
||||
@@ -1643,8 +1651,8 @@ public class PythonService {
|
||||
content.put("category", category);
|
||||
content.put("mode",mode);
|
||||
content.put("str", text);
|
||||
content.put("version",2);
|
||||
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content));
|
||||
content.put("version",modelName);
|
||||
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content,SerializerFeature.WriteMapNullValue));
|
||||
Request request = new Request.Builder()
|
||||
// .url(accessPythonIp + ":2828/aida/diffusion")
|
||||
// .url("http://18.167.251.121:9992")
|
||||
@@ -1656,7 +1664,7 @@ public class PythonService {
|
||||
Response response = null;
|
||||
String bodyString = null;
|
||||
try {
|
||||
log.info("generateSketchOrPrint请求入参content###{}", JSON.toJSONString(content));
|
||||
log.info("generateSketchOrPrint请求入参content###{}", JSON.toJSONString(content,SerializerFeature.WriteMapNullValue));
|
||||
response = client.newCall(request).execute();
|
||||
bodyString = response.body().string();
|
||||
// bodyString = "{\n" +
|
||||
@@ -1681,15 +1689,15 @@ public class PythonService {
|
||||
JSONObject jsonObject = JSON.parseObject(bodyString);
|
||||
Boolean result = JSON.parseObject(JSON.toJSONString(response)).getBoolean("successful");
|
||||
// Boolean result = Boolean.TRUE;
|
||||
if (result) {
|
||||
if (result && jsonObject.get("code").equals(200)) {
|
||||
return setGenerateImageList(jsonObject.getJSONObject("data"));
|
||||
}
|
||||
log.info("generateSketchOrPrintPrint失败###{}", jsonObject);
|
||||
//生成失败
|
||||
throw new BusinessException("generate exception!");
|
||||
throw new BusinessException("Generate Exception! Code : " + jsonObject.get("code"));
|
||||
}
|
||||
|
||||
public String sendPostToModel(Map<String,Object> content,String portAndRoute,String functionName){
|
||||
public Response sendPostToModel(String content,String portAndRoute,String functionName){
|
||||
|
||||
OkHttpClient client = new OkHttpClient().newBuilder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
@@ -1698,33 +1706,67 @@ public class PythonService {
|
||||
.writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒)
|
||||
.build();
|
||||
MediaType mediaType = MediaType.parse("application/json");
|
||||
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content));
|
||||
RequestBody body = RequestBody.create(mediaType, content);
|
||||
Request request = new Request.Builder()
|
||||
.url(accessPythonIp + ":" + portAndRoute)
|
||||
.url("http://18.167.251.121" + ":" + portAndRoute)
|
||||
.method("POST", body)
|
||||
.addHeader("Authorization", "Basic YWlkbGFiOjEyMw==")
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.build();
|
||||
Response response = null;
|
||||
String bodyString = null;
|
||||
// String bodyString = null;
|
||||
try {
|
||||
log.info(functionName + "请求入参content###{}", JSON.toJSONString(content));
|
||||
log.info(functionName + "请求入参content###{}", content);
|
||||
response = client.newCall(request).execute();
|
||||
bodyString = response.body().string();
|
||||
// bodyString = response.body().string();
|
||||
} catch (IOException ioException) {
|
||||
log.error("PythonService##"+ functionName +"异常###{}", ExceptionUtil.getThrowableList(ioException));
|
||||
}
|
||||
return bodyString;
|
||||
return response;
|
||||
}
|
||||
|
||||
private static List<String> setGenerateImageList(JSONObject jsonObject){
|
||||
private List<String> setGenerateImageList(JSONObject jsonObject){
|
||||
List<String> imageUrlList = JSONObject.parseArray(jsonObject.get("list").toString(),String.class);
|
||||
if (imageUrlList.size() == 0){
|
||||
if (imageUrlList.isEmpty()){
|
||||
log.error("PythonService##generateSketchOrPrint异常###{}","diffusion response list is null");
|
||||
// todo 如果这里返回为空,是判断出错还是返回给前端空
|
||||
throw new BusinessException("Some errors occurred, please try again later");
|
||||
throw new BusinessException("The data returned on the python side is empty");
|
||||
}
|
||||
|
||||
return imageUrlList;
|
||||
}
|
||||
|
||||
public String composeLayers(List<OutfitDetailPythonItem> layersDetail) throws IOException {
|
||||
HashMap<String, List<OutfitDetailPythonItem>> layers = new HashMap<>();
|
||||
HashMap<String, HashMap<String, List<OutfitDetailPythonItem>>> content = new HashMap<>();
|
||||
layers.put("layers", layersDetail);
|
||||
content.put("0",layers);
|
||||
String jsonString = JSON.toJSONString(content, SerializerFeature.WriteNullStringAsEmpty);
|
||||
|
||||
// todo 添加限流
|
||||
Response response = this.sendPostToModel(jsonString, "9991/api/preview_control", "composeLayers");
|
||||
// todo 结束限流
|
||||
|
||||
String bodyString;
|
||||
// 生成失败
|
||||
if (Objects.isNull(response) || Objects.isNull(response.body())) {
|
||||
log.error("PythonService##composeLayers异常###{}", "response or body is empty!");
|
||||
throw new BusinessException("generate exception!");
|
||||
}else {
|
||||
bodyString = response.body().string();
|
||||
}
|
||||
JSONObject jsonObject = JSON.parseObject(bodyString);
|
||||
Boolean result = JSON.parseObject(JSON.toJSONString(response)).getBoolean("successful");
|
||||
if (result && jsonObject.get("msg").equals("OK!")) {
|
||||
return getCompositeImage(jsonObject.getJSONObject("code"));
|
||||
}
|
||||
log.info("composeLayers 失败###{}", jsonObject);
|
||||
//生成失败
|
||||
throw new BusinessException("composeLayers Exception!");
|
||||
}
|
||||
|
||||
private String getCompositeImage(JSONObject jsonObject){
|
||||
JSONObject item0 = jsonObject.getJSONObject("0");
|
||||
return item0.getString("synthesis_url");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,20 +33,19 @@ public class DesignPythonItemPrint {
|
||||
|
||||
|
||||
@ApiModelProperty("print的位置 传 [[0.2, 0.2]]")
|
||||
private List<List<Float>> location;
|
||||
private List<List<Double>> location;
|
||||
|
||||
@ApiModelProperty("print的缩放比例 传 [0.2, 0.2]")
|
||||
private List<Float> print_scale_list;
|
||||
private List<Double> print_scale_list;
|
||||
|
||||
@ApiModelProperty("print的旋转角度 传 [0.2, 0.2]")
|
||||
private List<Float> print_angle_list;
|
||||
private List<Double> print_angle_list;
|
||||
|
||||
@JSONField(name="IfSingle")
|
||||
public Boolean getIfSingle() {
|
||||
return IfSingle;
|
||||
}
|
||||
|
||||
// todo
|
||||
public DesignPythonItemPrint(String singlePath, String level1Type, Float scale, Boolean ifSingle) {
|
||||
this.path = singlePath;
|
||||
this.level1Type = level1Type;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ai.da.python.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OutfitDetailPythonItem {
|
||||
|
||||
private String image_category;
|
||||
|
||||
private List<Long> position;
|
||||
|
||||
private List<Long> image_size;
|
||||
|
||||
private Float scale;
|
||||
|
||||
private String image_url;
|
||||
|
||||
private String mask_url;
|
||||
|
||||
public OutfitDetailPythonItem() {
|
||||
}
|
||||
|
||||
public OutfitDetailPythonItem(String image_category, List<Long> position, List<Long> image_size, Float scale, String image_url, String mask_url) {
|
||||
this.image_category = image_category;
|
||||
this.position = position;
|
||||
this.image_size = image_size;
|
||||
this.scale = scale;
|
||||
this.image_url = image_url;
|
||||
this.mask_url = mask_url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.mapper.entity.DesignItemDetailPrint;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DesignItemDetailPrintService extends IService<DesignItemDetailPrint> {
|
||||
List<DesignItemDetailPrint> getByDesignItemDetailId(Long designItemDetailId);
|
||||
|
||||
void deleteByDesignItemDetailId(Long designItemDetailId);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.ai.da.model.dto.DesignSingleIncludeLayersDTO;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -47,4 +48,6 @@ public interface DesignItemService extends IService<DesignItem> {
|
||||
|
||||
DesignSingleVO designSingleIncludeLayers(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO);
|
||||
|
||||
ComposeLayersVO editLayersPositionAndScale(EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.mapper.DesignItemDetailPrintMapper;
|
||||
import com.ai.da.mapper.entity.DesignItemDetailPrint;
|
||||
import com.ai.da.mapper.entity.TDesignPythonOutfitDetail;
|
||||
import com.ai.da.service.DesignItemDetailPrintService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class DesignItemDetailPrintServiceImpl extends ServiceImpl<DesignItemDetailPrintMapper, DesignItemDetailPrint> implements DesignItemDetailPrintService {
|
||||
|
||||
|
||||
@Override
|
||||
public List<DesignItemDetailPrint> getByDesignItemDetailId(Long designItemDetailId){
|
||||
QueryWrapper<DesignItemDetailPrint> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("design_item_detail_id",designItemDetailId);
|
||||
|
||||
return baseMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByDesignItemDetailId(Long designItemDetailId){
|
||||
UpdateWrapper<DesignItemDetailPrint> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("design_item_detail_id", designItemDetailId);
|
||||
updateWrapper.set("is_deleted",(byte)1);
|
||||
|
||||
baseMapper.update(null,updateWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.ai.da.mapper.DesignItemDetailMapper;
|
||||
import com.ai.da.mapper.entity.DesignItemDetail;
|
||||
import com.ai.da.service.DesignItemDetailService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -39,9 +40,15 @@ public class DesignItemDetailServiceImpl extends ServiceImpl<DesignItemDetailMap
|
||||
|
||||
@Override
|
||||
public int deleteByDesignItemId(Long designItemId) {
|
||||
QueryWrapper<DesignItemDetail> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("design_item_id", designItemId);
|
||||
return designItemDetailMapper.delete(queryWrapper);
|
||||
// QueryWrapper<DesignItemDetail> queryWrapper = new QueryWrapper<>();
|
||||
// queryWrapper.eq("design_item_id", designItemId);
|
||||
// DesignItemDetail designItemDetail = new DesignItemDetail();
|
||||
// designItemDetail.setIsDeleted((byte)1);
|
||||
|
||||
UpdateWrapper<DesignItemDetail> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("design_item_id", designItemId);
|
||||
updateWrapper.set("is_deleted",(byte)1);
|
||||
return designItemDetailMapper.update(null,updateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,14 +10,10 @@ import com.ai.da.common.utils.DateUtil;
|
||||
import com.ai.da.common.utils.MinioUtil;
|
||||
import com.ai.da.mapper.DesignItemMapper;
|
||||
import com.ai.da.mapper.entity.*;
|
||||
import com.ai.da.model.dto.DesignSingleDTO;
|
||||
import com.ai.da.model.dto.DesignSingleIncludeLayersDTO;
|
||||
import com.ai.da.model.dto.DesignSingleItemDTO;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.ai.da.python.PythonService;
|
||||
import com.ai.da.python.vo.DesignPythonItem;
|
||||
import com.ai.da.python.vo.DesignPythonItemPrint;
|
||||
import com.ai.da.python.vo.DesignPythonObjects;
|
||||
import com.ai.da.python.vo.*;
|
||||
import com.ai.da.service.*;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
@@ -25,12 +21,14 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.checkerframework.checker.units.qual.A;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
@@ -68,9 +66,9 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
@Resource
|
||||
private PanToneService panToneService;
|
||||
@Resource
|
||||
private DesignItemDetailPrintService designItemDetailPrintService;
|
||||
@Resource
|
||||
private MinioUtil minioUtil;
|
||||
@Value("${minio.bucketName.results}")
|
||||
private String bucketName;
|
||||
|
||||
@Override
|
||||
public Long saveOne(DesignItem designItem) {
|
||||
@@ -281,22 +279,20 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
}
|
||||
|
||||
private List<TDesignPythonOutfitDetail> saveDesignSingleItemDetailAndLayers(DesignPythonObjects pythonObjects
|
||||
, Long designId,Long designItemId, Long collectionId, AuthPrincipalVo userInfo
|
||||
, JSONObject outfit, String timeZone){
|
||||
, Long designId,Long designItemId, AuthPrincipalVo userInfo
|
||||
, JSONObject outfit, String timeZone,List<DesignSingleItemDTO> designSingleItemDTOList){
|
||||
|
||||
DesignItem designItem = new DesignItem();
|
||||
String url = pythonObjects.getObjects().get(0).getBasic().getSave_name();
|
||||
// String url = pythonObjects.getObjects().get(0).getBasic().getSave_name();
|
||||
designItem.setUpdateDate(DateUtil.getByTimeZone(timeZone));
|
||||
designItem.setDesignUrl(url);
|
||||
designItem.setDesignUrl(outfit.getString("synthesis_url"));
|
||||
designItem.setId(designItemId);
|
||||
|
||||
//更新item
|
||||
// 1、更新designItem
|
||||
updateById(designItem);
|
||||
//删除itemDetail
|
||||
// 2、删除designItemDetail(逻辑删除)
|
||||
designItemDetailService.deleteByDesignItemId(designItemId);
|
||||
|
||||
List<DesignItemDetail> designItemDetails = Lists.newArrayList();
|
||||
// 保存designItem
|
||||
// 3、保存新的designItemDetail
|
||||
pythonObjects.getObjects().get(0).getItems().forEach(detail ->{
|
||||
if(null == detail){
|
||||
return;
|
||||
@@ -315,23 +311,28 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designItemDetail.setIconPath(detail.getIcon());
|
||||
DesignPythonItemPrint printObject = detail.getPrint();
|
||||
designItemDetail.setPrintPath(Objects.isNull(printObject)? "" :printObject.getPath());
|
||||
designItemDetail.setPrintJson(JSON.toJSONString(printObject));
|
||||
// 当有多个印花后,返回的printObject太长,导致存储到数据库时报错
|
||||
// designItemDetail.setPrintJson(JSON.toJSONString(printObject));
|
||||
designItemDetails.add(designItemDetail);
|
||||
});
|
||||
// todo businessId
|
||||
// businessId 来自t_sys_file或者t_library
|
||||
designItemDetailService.saveBatch(designItemDetails);
|
||||
|
||||
// 覆盖designPythonOutfit表中的模特全身图
|
||||
// 4、保存印花信息到designItemDetailPrint
|
||||
List<DesignItemDetailPrint> designItemDetailPrints = setDesignItemDetailPrintList(designItemDetails, designSingleItemDTOList, timeZone);
|
||||
designItemDetailPrintService.saveBatch(designItemDetailPrints);
|
||||
|
||||
// 5、覆盖designPythonOutfit表中的模特全身图
|
||||
TDesignPythonOutfit designPythonOutfit = new TDesignPythonOutfit();
|
||||
designPythonOutfit.setDesignUrl(outfit.getString("synthesis_url"));
|
||||
designPythonOutfit.setId(designPythonOutfitService.getByDesignItemId(designItemId).getId());
|
||||
designPythonOutfit.setUpdateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
designPythonOutfitService.updateById(designPythonOutfit);
|
||||
|
||||
// 删除designPythonOutfitDetail表中原始的图层信息
|
||||
// 6、删除designPythonOutfitDetail表中原始的图层信息(逻辑删除)
|
||||
designPythonOutfitDetailService.deleteByDesignPythonOutfitId(designPythonOutfit.getId());
|
||||
|
||||
// 将新生成的图层信息存入designPythonOutfitDetail表
|
||||
// 7、将新生成的图层信息存入designPythonOutfitDetail表
|
||||
JSONArray layers = outfit.getJSONArray("layers");
|
||||
List<TDesignPythonOutfitDetail> list = setTDesignPythonOutfitDetailList(layers, designId, designPythonOutfit.getId(), userInfo.getId());
|
||||
|
||||
@@ -353,6 +354,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designPythonOutfitDetail.setImageSize(jsonObject.getString("image_size"));
|
||||
designPythonOutfitDetail.setImageCategory(jsonObject.getString("image_category"));
|
||||
designPythonOutfitDetail.setMaskUrl(jsonObject.getString("mask_url"));
|
||||
designPythonOutfitDetail.setScale(Objects.isNull(jsonObject.getString("scale")) ? null : jsonObject.getString("scale"));
|
||||
designPythonOutfitDetail.setUserId(userId);
|
||||
list.add(designPythonOutfitDetail);
|
||||
}
|
||||
@@ -378,6 +380,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
Assert.notNull(designItem,"design item does not exists!");
|
||||
Design design = designService.getById(designItem.getDesignId());
|
||||
Assert.notNull(design,"design does not exists!");
|
||||
|
||||
DesignLibraryModelPointVO designLibraryModelPointVO = null;
|
||||
// 设置模特
|
||||
if (Objects.nonNull(design.getTemplateId())){
|
||||
@@ -388,18 +391,21 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
designLibraryModelPointVO = collectionElementService.calculateTemplatePoint(modelPoint,library.getHigh(),library.getWidth(),library.getUrl());
|
||||
}
|
||||
|
||||
// 组装入参
|
||||
DesignPythonObjects objects =pythonService.covertDesignSingleParam(
|
||||
designSingleIncludeLayersDTO,design.getSingleOverall(),design.getSwitchCategory(),designLibraryModelPointVO);
|
||||
JSONObject jsonObject = pythonService.designNew(objects);
|
||||
// preview -> 不存数据库 submit -> 存数据库
|
||||
List<TDesignPythonOutfitDetail> tDesignPythonOutfitDetails;
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
// todo 空指针
|
||||
if (data == null) {
|
||||
throw new BusinessException("python response data is null");
|
||||
}
|
||||
JSONObject outfit = data.getJSONObject("0");
|
||||
if (!designSingleIncludeLayersDTO.getIsPreview()){
|
||||
// 更新及保存图层信息
|
||||
tDesignPythonOutfitDetails = saveDesignSingleItemDetailAndLayers(objects, design.getId(), designSingleIncludeLayersDTO.getDesignItemId(),
|
||||
design.getCollectionId(), userInfo, outfit, designSingleIncludeLayersDTO.getTimeZone());
|
||||
userInfo, outfit, designSingleIncludeLayersDTO.getTimeZone(),designSingleIncludeLayersDTO.getDesignSingleItemDTOList());
|
||||
}else {
|
||||
JSONArray layers = outfit.getJSONArray("layers");
|
||||
tDesignPythonOutfitDetails = setTDesignPythonOutfitDetailList(layers,designItem.getDesignId(),null,userInfo.getId());
|
||||
@@ -412,11 +418,70 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
});
|
||||
|
||||
TDesignPythonOutfit designPythonOutfit = designPythonOutfitService.getByDesignItemId(designSingleIncludeLayersDTO.getDesignItemId());
|
||||
// todo designPythonOutFit 空指针
|
||||
return assembleDesignSingleResponse(designItem.getId(),minioUtil.splitThenGetPreviewUrl(designPythonOutfit.getDesignUrl(),480),
|
||||
Assert.notNull(designItem,"design item detail layers does not exists!");
|
||||
|
||||
return assembleDesignSingleResponse(designItem.getId(),
|
||||
minioUtil.splitThenGetPreviewUrl(designPythonOutfit.getDesignUrl(),480),
|
||||
designSingleIncludeLayersDTO.getDesignSingleItemDTOList(),detailsVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComposeLayersVO editLayersPositionAndScale(EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException {
|
||||
ComposeLayersVO designItemLayer = positionAndScaleVO.getLayers();
|
||||
// 1、校验designItem是是否存在
|
||||
DesignItem designItem = selectById(designItemLayer.getDesignItemId());
|
||||
Assert.notNull(designItem,"designItem does not exists!");
|
||||
|
||||
// 2、校验layers是否存在
|
||||
designItemLayer.getLayers().forEach(layer -> {
|
||||
TDesignPythonOutfitDetail detail = designPythonOutfitDetailService.getById(layer.getId());
|
||||
Assert.notNull(detail,layer.getImageCategory() + " layer does not exists!");
|
||||
|
||||
layer.setImageUrl(detail.getImageUrl());
|
||||
layer.setMaskUrl(detail.getMaskUrl());
|
||||
});
|
||||
|
||||
// 3、组装python入参
|
||||
List<OutfitDetailPythonItem> outfitDetailPythonItems = convertToOutfitDetailPythonItemList(designItemLayer.getLayers());
|
||||
|
||||
// 4、合成图层
|
||||
String synthesisUrl = pythonService.composeLayers(outfitDetailPythonItems);
|
||||
designItemLayer.setDesignItemUrl(minioUtil.splitThenGetPreviewUrl(synthesisUrl,480));
|
||||
|
||||
// 5、更新数据库,根据designItemId更新designItemUrl
|
||||
designItem.setUpdateDate(DateUtil.getByTimeZone(positionAndScaleVO.getTimeZone()));
|
||||
designItem.setDesignUrl(synthesisUrl);
|
||||
designItem.setId(designItemLayer.getDesignItemId());
|
||||
updateById(designItem);
|
||||
|
||||
// 6、将图层信息position和scale更新到t_design_python_outfit_detail表
|
||||
ArrayList<TDesignPythonOutfitDetail> details = new ArrayList<>();
|
||||
designItemLayer.getLayers().forEach(layer -> {
|
||||
TDesignPythonOutfitDetail layerDetail = new TDesignPythonOutfitDetail();
|
||||
layerDetail.setPosition(layer.getPosition().toString());
|
||||
layerDetail.setScale(layer.getScale().toString());
|
||||
layerDetail.setId(layer.getId());
|
||||
details.add(layerDetail);
|
||||
});
|
||||
designPythonOutfitDetailService.updateBatchById(details);
|
||||
|
||||
// 7、返回图层及合成图信息
|
||||
designItemLayer.getLayers().forEach(layer -> {
|
||||
ArrayList<Long> imageSize = new ArrayList<>();
|
||||
for (int i = 0; i < layer.getImageSize().size(); i++) {
|
||||
imageSize.add((long) (layer.getImageSize().get(i) * layer.getScale()));
|
||||
}
|
||||
layer.setImageSize(imageSize);
|
||||
if (!StringUtil.isNullOrEmpty(layer.getImageUrl())){
|
||||
layer.setImageUrl(minioUtil.splitThenGetPreviewUrl(layer.getImageUrl(),480));
|
||||
}
|
||||
if (!StringUtil.isNullOrEmpty(layer.getMaskUrl())){
|
||||
layer.setMaskUrl(minioUtil.splitThenGetPreviewUrl(layer.getMaskUrl(),480));
|
||||
}
|
||||
});
|
||||
return designItemLayer;
|
||||
}
|
||||
|
||||
private DesignSingleVO assembleDesignSingleResponse(Long designItemId,String designItemUrl,
|
||||
List<DesignSingleItemDTO> designSingleItemDTOList,
|
||||
List<DesignPythonOutfitVO> layersObject){
|
||||
@@ -430,9 +495,13 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
|
||||
designSingleItemDTOList.forEach(singleItem -> {
|
||||
DesignItemClothesDetailVO designItemClothesDetailVO = new DesignItemClothesDetailVO();
|
||||
designItemClothesDetailVO.setId(singleItem.getId());
|
||||
designItemClothesDetailVO.setType(singleItem.getType());
|
||||
designItemClothesDetailVO.setPath(minioUtil.splitThenGetPreviewUrl(singleItem.getPath(),480));
|
||||
designItemClothesDetailVO.setMinIOPath(singleItem.getPath());
|
||||
designItemClothesDetailVO.setColor(panToneService.getPantoneByRgb(singleItem.getColor()));
|
||||
designItemClothesDetailVO.setPrintObject(new DesignPythonItemPrint(singleItem.getPrintObject().getPath()));
|
||||
// designItemClothesDetailVO.setPrintObject(new DesignPythonItemPrint(singleItem.getPrintObject().getPath()));
|
||||
designItemClothesDetailVO.setPrintObject(singleItem.getPrintObject());
|
||||
designItemClothesDetailVO.setLayersObject(layersObject.stream().filter(
|
||||
layers -> singleItem.getType().toLowerCase().equals(layers.getImageCategory().split("_")[0])
|
||||
).collect(Collectors.toList()));
|
||||
@@ -444,4 +513,58 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
||||
|
||||
return designSingleVO;
|
||||
}
|
||||
|
||||
private List<DesignItemDetailPrint> setDesignItemDetailPrintList(List<DesignItemDetail> designItemDetails,
|
||||
List<DesignSingleItemDTO> designSingleItemDTOList,
|
||||
String timeZone){
|
||||
|
||||
Map<String, Long> designItemDetailTypeIdMap = designItemDetails.stream().collect(Collectors.toMap(DesignItemDetail::getType, DesignItemDetail::getId));
|
||||
ArrayList<DesignItemDetailPrint> designItemDetailPrints = new ArrayList<>();
|
||||
|
||||
designSingleItemDTOList.forEach(designSingleItem -> {
|
||||
// 1、判断有无印花,无印花则跳过
|
||||
DesignSinglePrintDTO printObject = designSingleItem.getPrintObject();
|
||||
if (printObject.getIfSingle().equals(Boolean.FALSE)
|
||||
&& CollectionUtil.isEmpty(printObject.getPrints()) ){
|
||||
return;
|
||||
}else {
|
||||
// 2、有印花,添加到list
|
||||
printObject.getPrints().forEach(print -> {
|
||||
// 2.1 判断是否第一次添加印花,是:直接添加
|
||||
List<DesignItemDetailPrint> designItemDetailPrintList = designItemDetailPrintService.getByDesignItemDetailId(designItemDetailTypeIdMap.get(designSingleItem.getType()));
|
||||
if (!designItemDetailPrintList.isEmpty()){
|
||||
// 2.2 否:先删除原始印花,再添加新印花信息
|
||||
designItemDetailPrintService.deleteByDesignItemDetailId(designItemDetailTypeIdMap.get(designSingleItem.getType()));
|
||||
}
|
||||
DesignItemDetailPrint designItemDetailPrint = new DesignItemDetailPrint();
|
||||
designItemDetailPrint.setDesignItemDetailId(designItemDetailTypeIdMap.get(designSingleItem.getType()));
|
||||
designItemDetailPrint.setPath(print.getPath());
|
||||
designItemDetailPrint.setScale(print.getScale());
|
||||
designItemDetailPrint.setSingleOrOverall(printObject.getIfSingle() ? "single" : "overall");
|
||||
designItemDetailPrint.setCreateDate(LocalDateTime.now(ZoneId.of(timeZone)));
|
||||
// single模式下才有position、angle和priority
|
||||
if (designItemDetailPrint.getSingleOrOverall().equals("single")){
|
||||
designItemDetailPrint.setPosition(print.getLocation().toString());
|
||||
designItemDetailPrint.setAngle(print.getAngle());
|
||||
designItemDetailPrint.setPriority(print.getPriority());
|
||||
}
|
||||
designItemDetailPrints.add(designItemDetailPrint);
|
||||
});
|
||||
}
|
||||
});
|
||||
return designItemDetailPrints;
|
||||
}
|
||||
|
||||
private List<OutfitDetailPythonItem> convertToOutfitDetailPythonItemList(List<DesignPythonOutfitVO> layers){
|
||||
ArrayList<OutfitDetailPythonItem> composeLayerPythonItem = new ArrayList<>();
|
||||
layers.forEach(layer -> {
|
||||
composeLayerPythonItem.add(new OutfitDetailPythonItem(layer.getImageCategory(),
|
||||
layer.getPosition(),
|
||||
layer.getImageSize(),
|
||||
layer.getScale(),
|
||||
layer.getImageUrl(),
|
||||
layer.getMaskUrl()));
|
||||
});
|
||||
return composeLayerPythonItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
|
||||
private PanToneService panToneService;
|
||||
@Resource
|
||||
private PythonTAllInfoService pythonTAllInfoService;
|
||||
@Resource
|
||||
private DesignItemDetailPrintService designItemDetailPrintService;
|
||||
|
||||
@Resource
|
||||
private TDesignPythonOutfitMapper designPythonOutfitMapper;
|
||||
@@ -834,16 +836,25 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
|
||||
List<DesignItemDetail> filterDetail = designItemDetails.stream()
|
||||
.filter(f -> OUTWEAR_DRESS_BLOUSE.contains(f.getType()) || SKIRT_TROUSERS.contains(f.getType()))
|
||||
.collect(Collectors.toList());
|
||||
response.setClothes(CopyUtil.copyList(filterDetail, DesignItemClothesDetailVO.class, (o, d) -> {
|
||||
d.setId(o.getBusinessId());
|
||||
response.setClothes(CopyUtil.copyList(filterDetail,DesignItemClothesDetailVO.class,(o,d)->{
|
||||
d.setId(o.getId());
|
||||
d.setPath(minIoUtil.splitThenGetPreviewUrl(o.getPath(),480));
|
||||
d.setMinIOPath(o.getPath());
|
||||
d.setLevel1Type(converTypeToLevel1(o.getType()));
|
||||
String printJson = o.getPrintJson();
|
||||
if (StringUtils.isEmpty(printJson)) {
|
||||
d.setPrintObject(new DesignPythonItemPrint(o.getPrintPath(),
|
||||
CollectionLevel1TypeEnum.PRINT_BOARD.getRealName(), 0.3f, Boolean.FALSE));
|
||||
} else {
|
||||
d.setPrintObject(JSON.parseObject(printJson, DesignPythonItemPrint.class));
|
||||
// 根据designItemDetailId获取印花
|
||||
List<DesignItemDetailPrint> prints = designItemDetailPrintService.getByDesignItemDetailId(o.getId());
|
||||
// 判断有无印花
|
||||
if (CollectionUtil.isNotEmpty(prints)){
|
||||
// 有印花
|
||||
d.setPrintObject(convertToDesignSinglePrintDTO(prints));
|
||||
}
|
||||
// String printJson = o.getPrintJson();
|
||||
// if (StringUtils.isEmpty(printJson)) {
|
||||
// d.setPrintObject(new DesignPythonItemPrint(o.getPrintPath(),
|
||||
// CollectionLevel1TypeEnum.PRINT_BOARD.getRealName(), 0.3f, Boolean.FALSE));
|
||||
// } else {
|
||||
// d.setPrintObject(JSON.parseObject(printJson, DesignPythonItemPrint.class));
|
||||
// }
|
||||
}));
|
||||
//single 和 Models(模特)时候 系统元素为空
|
||||
List<DesignItemDetail> filterDetail2 = designItemDetails.stream()
|
||||
@@ -852,10 +863,12 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
|
||||
.collect(Collectors.toList());
|
||||
response.setOthers(CopyUtil.copyList(filterDetail2, DesignItemOthersDetailVO.class, (o, d) -> {
|
||||
d.setId(o.getBusinessId());
|
||||
d.setPath(minIoUtil.splitThenGetPreviewUrl(o.getPath(),480));
|
||||
d.setMinIOPath(o.getPath());
|
||||
d.setPrintObject(new DesignPythonItemPrint());
|
||||
}));
|
||||
return editDesignItemLayer(flag,designPythonOutfit,
|
||||
minIoUtil.splitThenGetPreviewUrl(designItem.getDesignUrl(),480),
|
||||
minIoUtil.splitThenGetPreviewUrl(designPythonOutfit.getDesignUrl(),480),
|
||||
editResponseColor(designItemDetails,response));
|
||||
}
|
||||
|
||||
@@ -898,50 +911,36 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
|
||||
return design.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 避免多次连接数据,所这里一次查多条颜色并利用designItemDetailId保持颜色与vo的对应关系
|
||||
* @param designItemDetails
|
||||
* @param designItemDetailVO
|
||||
* @return
|
||||
*/
|
||||
private DesignItemDetailVO editResponseColor(List<DesignItemDetail> designItemDetails, DesignItemDetailVO designItemDetailVO) {
|
||||
/*designItemDetails.forEach(d -> {
|
||||
if (!StringUtil.isNullOrEmpty(d.getColor())){
|
||||
PantoneVO pantoneByRgb = panToneService.getPantoneByRgb(d.getColor());
|
||||
DesignItemClothesDetailVO clothesDetailVO = designItemDetailVO.getClothes().stream()
|
||||
.filter(v -> v.getId().equals(d.getBusinessId()))
|
||||
.findFirst().orElse(null);
|
||||
if (Objects.nonNull(clothesDetailVO)){
|
||||
clothesDetailVO.setColor(pantoneByRgb);
|
||||
} else {
|
||||
DesignItemOthersDetailVO othersDetailVO = designItemDetailVO.getOthers().stream()
|
||||
.filter(v -> v.getId().equals(d.getBusinessId()))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
if (Objects.nonNull(othersDetailVO)) {
|
||||
othersDetailVO.setColor(pantoneByRgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
HashMap<Long, String> businessIdColor = new HashMap<>();
|
||||
// 使用designItemDetailId做映射
|
||||
HashMap<Long, String> designItemDetailIdColor = new HashMap<>();
|
||||
designItemDetails.forEach(designItemDetail -> {
|
||||
if (!StringUtil.isNullOrEmpty(designItemDetail.getColor())) {
|
||||
businessIdColor.put(designItemDetail.getBusinessId(), designItemDetail.getColor());
|
||||
designItemDetailIdColor.put(designItemDetail.getId(), designItemDetail.getColor());
|
||||
}
|
||||
});
|
||||
|
||||
Map<String, PantoneVO> pantoneByRgbBatch = panToneService.getPantoneByRgbBatch(new ArrayList<>(businessIdColor.values()));
|
||||
Map<String, PantoneVO> pantoneByRgbBatch = panToneService.getPantoneByRgbBatch(new ArrayList<>(designItemDetailIdColor.values()));
|
||||
|
||||
designItemDetailVO.getClothes().forEach(c -> {
|
||||
PantoneVO pantoneVO = pantoneByRgbBatch.get(businessIdColor.get(c.getId()));
|
||||
PantoneVO pantoneVO = pantoneByRgbBatch.get(designItemDetailIdColor.get(c.getId()));
|
||||
c.setColor(pantoneVO);
|
||||
});
|
||||
|
||||
designItemDetailVO.getOthers().forEach(o -> {
|
||||
PantoneVO pantoneVO = pantoneByRgbBatch.get(businessIdColor.get(o.getId()));
|
||||
PantoneVO pantoneVO = pantoneByRgbBatch.get(designItemDetailIdColor.get(o.getId()));
|
||||
o.setColor(pantoneVO);
|
||||
});
|
||||
|
||||
return designItemDetailVO;
|
||||
}
|
||||
|
||||
|
||||
private DesignItemDetailVO editDesignItemLayer(Boolean flag, TDesignPythonOutfit designPythonOutfit, String designItemUrl, DesignItemDetailVO designItemDetailVO) {
|
||||
ArrayList<DesignPythonOutfitVO> detailsVO = new ArrayList<>();
|
||||
|
||||
@@ -976,6 +975,50 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
|
||||
} else {
|
||||
designItemDetailVO.setDesignItemUrl(designItemUrl);
|
||||
}
|
||||
|
||||
return designItemDetailVO;
|
||||
}
|
||||
|
||||
private DesignSinglePrintDTO convertToDesignSinglePrintDTO(List<DesignItemDetailPrint> designItemDetailPrints){
|
||||
DesignSinglePrintDTO designSinglePrintDTO = new DesignSinglePrintDTO();
|
||||
List<DesignSinglePrint> prints = new ArrayList<>();
|
||||
|
||||
// 只有一个印花
|
||||
if (designItemDetailPrints.size() == 1){
|
||||
DesignItemDetailPrint detailPrint = designItemDetailPrints.get(0);
|
||||
DesignSinglePrint designSinglePrint = new DesignSinglePrint();
|
||||
// overall 模式下只需要返回印花url和scale
|
||||
if (detailPrint.getSingleOrOverall().equals("overall")){
|
||||
designSinglePrintDTO.setIfSingle(Boolean.FALSE);
|
||||
}else {
|
||||
designSinglePrintDTO.setIfSingle(Boolean.TRUE);
|
||||
designSinglePrint.setLocation(JSONArray.parseArray(detailPrint.getPosition(),Double.class));
|
||||
designSinglePrint.setScale(detailPrint.getScale());
|
||||
designSinglePrint.setAngle(detailPrint.getAngle());
|
||||
designSinglePrint.setPriority(detailPrint.getPriority());
|
||||
}
|
||||
designSinglePrint.setPath(minIoUtil.splitThenGetPreviewUrl(detailPrint.getPath(),480));
|
||||
designSinglePrint.setMinIOPath(detailPrint.getPath());
|
||||
designSinglePrint.setScale(detailPrint.getScale());
|
||||
prints.add(designSinglePrint);
|
||||
}else {
|
||||
// single模式下多个印花
|
||||
designSinglePrintDTO.setIfSingle(Boolean.TRUE);
|
||||
designItemDetailPrints.forEach(print -> {
|
||||
if (print.getSingleOrOverall().equals("single")){
|
||||
prints.add(new DesignSinglePrint(
|
||||
minIoUtil.splitThenGetPreviewUrl(print.getPath(),480),
|
||||
print.getPath(),
|
||||
JSONArray.parseArray(print.getPosition(),Double.class),
|
||||
print.getScale(),
|
||||
print.getAngle(),
|
||||
print.getPriority()));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
designSinglePrintDTO.setPrints(prints);
|
||||
return designSinglePrintDTO;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.ai.da.common.enums.*;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.utils.CopyUtil;
|
||||
import com.ai.da.common.utils.DateUtil;
|
||||
import com.ai.da.common.utils.FileUtil;
|
||||
import com.ai.da.common.utils.MinioUtil;
|
||||
import com.ai.da.mapper.LibraryMapper;
|
||||
import com.ai.da.mapper.entity.*;
|
||||
|
||||
@@ -87,6 +87,7 @@ public class PanToneServiceImpl extends ServiceImpl<PanToneMapper, PanTone> impl
|
||||
});
|
||||
List<ColorLookupTable> colorValueList = colorLoopUpTableService.getByColorValueList(values);
|
||||
colorValueList.forEach(colorValue ->{
|
||||
// 不同的colorValue可能会有相同的colorIndex
|
||||
colorIndexRgb.put(colorValue.getColorIndex(),colorValueRgb.get(colorValue.getColorValue()));
|
||||
});
|
||||
|
||||
@@ -98,7 +99,15 @@ public class PanToneServiceImpl extends ServiceImpl<PanToneMapper, PanTone> impl
|
||||
|
||||
HashMap<String, PantoneVO> colorPantoneVO = new HashMap<>();
|
||||
pantoneVOS.forEach(pantoneVO -> {
|
||||
colorPantoneVO.put(colorIndexRgb.get(pantoneVO.getId()),pantoneVO);
|
||||
int colorIndex = pantoneVO.getId();
|
||||
List<ColorLookupTable> collect = colorValueList.stream().filter(colorValue -> colorValue.getColorIndex().equals(colorIndex)).collect(Collectors.toList());
|
||||
if (collect.size() > 1){
|
||||
for (ColorLookupTable colorLookupTable : collect) {
|
||||
colorPantoneVO.put(colorValueRgb.get(colorLookupTable.getColorValue()), pantoneVO);
|
||||
}
|
||||
}else if (collect.size() == 1){
|
||||
colorPantoneVO.put(colorIndexRgb.get(pantoneVO.getId()),pantoneVO);
|
||||
}
|
||||
});
|
||||
|
||||
return colorPantoneVO;
|
||||
|
||||
@@ -3,12 +3,14 @@ package com.ai.da.service.impl;
|
||||
import com.ai.da.common.utils.CopyUtil;
|
||||
import com.ai.da.common.utils.MinioUtil;
|
||||
import com.ai.da.mapper.TDesignPythonOutfitDetailMapper;
|
||||
import com.ai.da.mapper.entity.DesignItemDetail;
|
||||
import com.ai.da.mapper.entity.TDesignPythonOutfitDetail;
|
||||
import com.ai.da.model.vo.DesignPythonOutfitVO;
|
||||
import com.ai.da.model.vo.TDesignPythonOutfitDetailVO;
|
||||
import com.ai.da.service.ITDesignPythonOutfitDetailService;
|
||||
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.extension.service.impl.ServiceImpl;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -52,24 +54,22 @@ public class TDesignPythonOutfitDetailServiceImpl extends ServiceImpl<TDesignPyt
|
||||
DesignPythonOutfitVO designPythonOutfitVO = CopyUtil.copyObject(detail,DesignPythonOutfitVO.class);
|
||||
designPythonOutfitVO.setPosition(StringUtil.isNullOrEmpty(detail.getPosition()) ? null : (List<Long>) JSON.parse(detail.getPosition()));
|
||||
designPythonOutfitVO.setImageSize(StringUtil.isNullOrEmpty(detail.getImageSize()) ? null : (List<Long>) JSON.parse(detail.getImageSize()));
|
||||
if (detail.getImageCategory().equals("body")){
|
||||
designPythonOutfitVO.setImageUrl(StringUtil.isNullOrEmpty(detail.getImageUrl()) ? null : minIoUtil.splitThenGetPreviewUrl(detail.getImageUrl(),480));
|
||||
}else {
|
||||
designPythonOutfitVO.setImageUrl(StringUtil.isNullOrEmpty(detail.getImageUrl()) ? null : minIoUtil.splitThenGetPreviewUrl(detail.getImageUrl(),480));
|
||||
}
|
||||
designPythonOutfitVO.setImageUrl(StringUtil.isNullOrEmpty(detail.getImageUrl()) ? null : minIoUtil.splitThenGetPreviewUrl(detail.getImageUrl(),480));
|
||||
designPythonOutfitVO.setMaskUrl(StringUtil.isNullOrEmpty(detail.getMaskUrl()) ? null : minIoUtil.splitThenGetPreviewUrl(detail.getMaskUrl(),480));
|
||||
return designPythonOutfitVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByDesignPythonOutfitId(Long designPythonOutfitId){
|
||||
QueryWrapper<TDesignPythonOutfitDetail> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("design_python_outfit_id",designPythonOutfitId);
|
||||
// QueryWrapper<TDesignPythonOutfitDetail> queryWrapper = new QueryWrapper<>();
|
||||
// queryWrapper.eq("design_python_outfit_id",designPythonOutfitId);
|
||||
// TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail();
|
||||
// tDesignPythonOutfitDetail.setIsDeleted(1);
|
||||
UpdateWrapper<TDesignPythonOutfitDetail> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("design_python_outfit_id", designPythonOutfitId);
|
||||
updateWrapper.set("is_deleted",(byte)1);
|
||||
|
||||
TDesignPythonOutfitDetail tDesignPythonOutfitDetail = new TDesignPythonOutfitDetail();
|
||||
tDesignPythonOutfitDetail.setIsDeleted(1);
|
||||
|
||||
baseMapper.update(tDesignPythonOutfitDetail,queryWrapper);
|
||||
baseMapper.update(null,updateWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ spring.security.jwtTokenPrefix=Bearer-
|
||||
spring.security.jwtExpiration=8640000000
|
||||
#spring security权限设置 认证了token还要认证权限 不然报错Full authentication is required to access this resource
|
||||
spring.security.ignorePaths=/,/favicon.ico,/doc.html,/webjars/**,/swagger-resources,/v2/api-docs,\
|
||||
/api/account/**,/api/element/**,/api/python/**,/api/design/**,/api/history/**,/api/library/**,/api/third/party/**,/api/generate/**
|
||||
/api/account/**,/api/element/**,/api/python/**,/api/design/**,/api/history/**,/api/library/**,/api/third/party/**,/api/generate/**,/api/workspace/**
|
||||
spring.security.authApi=/auth/login
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ rsa.private_key=MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8
|
||||
mybatis-plus.global-config.banner=false
|
||||
mybatis-plus.mapper-locations=classpath:mapper/*Mapper.xml
|
||||
#mybatis-plus.configuration.log-impl= org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mybatis-plus.global-config.db-config.logic-delete-field=isDeleted
|
||||
mybatis-plus.global-config.db-config.logic-delete-value=1
|
||||
mybatis-plus.global-config.db-config.logic-not-delete-value=0
|
||||
|
||||
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
|
||||
|
||||
@@ -46,10 +49,11 @@ access.python.ip=http://43.198.80.117
|
||||
minio.endpoint=http://18.167.251.121:9000
|
||||
minio.accessKey=minioadmin
|
||||
minio.secretKey=minioadmin
|
||||
minio.bucketName=aida-results
|
||||
minio.bucketName2=aida-clothing
|
||||
minio.bucketName3=aida-mannequins
|
||||
minio.bucketName4=aida-users
|
||||
minio.bucketName.clothing=aida-clothing
|
||||
minio.bucketName.mannequins=aida-mannequins
|
||||
minio.bucketName.results=aida-results
|
||||
minio.bucketName.sysImage=aida-sys-image
|
||||
minio.bucketName.users=aida-users
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#<23><><EFBFBD><EFBFBD>application-test<73>ļ<EFBFBD>(<28><><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD>)
|
||||
spring.profiles.active=prod
|
||||
spring.profiles.active=test
|
||||
|
||||
#<23><><EFBFBD><EFBFBD>application-prod<6F>ļ<EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
#spring.profiles.active=prod
|
||||
|
||||
Reference in New Issue
Block a user