Merge branch 'dev/dev_xp' into dev/dev
# Conflicts: # src/main/java/com/ai/da/python/PythonService.java
This commit is contained in:
@@ -1,24 +1,22 @@
|
||||
package com.ai.da.common.RabbitMQ;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.constant.CommonConstant;
|
||||
import com.ai.da.common.utils.RedisUtil;
|
||||
import com.ai.da.model.dto.GenerateThroughImageTextDTO;
|
||||
import com.ai.da.model.vo.GenerateResultVO;
|
||||
import com.ai.da.model.vo.PoseTransformationVO;
|
||||
import com.ai.da.service.GenerateService;
|
||||
import com.ai.da.service.UserLikeGroupService;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.gson.Gson;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.tomcat.jni.Time;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
@@ -258,6 +256,55 @@ public class GenerateConsumer {
|
||||
log.info("============ProcessRelightResult End listening==========");
|
||||
}
|
||||
|
||||
public void processPoseTransformResult(Message msg, Channel channel) {
|
||||
log.info("============ProcessPoseTransformResult listening==========");
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Map<String, String> generateResult = JSONObject.parseObject(msg.getBody(), Map.class);
|
||||
log.info("PoseTransformation response : {}", generateResult);
|
||||
|
||||
try {
|
||||
log.info("tasks_id : {} start ", generateResult.get("tasks_id"));
|
||||
if (generateResult.get("status").equals("SUCCESS")) {
|
||||
String gifUrl = generateResult.get("gif_url");
|
||||
String taskId = generateResult.get("tasks_id");
|
||||
String videoUrl = generateResult.get("video_url");
|
||||
String imageUrl = generateResult.get("image_url");
|
||||
generateService.processPoseTransformResult(taskId, gifUrl, videoUrl, imageUrl);
|
||||
} else {
|
||||
// 修改redis中的数据状态为exception
|
||||
String key = generateResultKey + ":" + generateResult.get("tasks_id");
|
||||
redisUtil.addToString(key, new Gson().toJson(new PoseTransformationVO(null, generateResult.get("tasks_id"),null, null, null, (byte)0, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
|
||||
// 将异常信息存到exception中
|
||||
HashMap<String, String> exceptionInfo = new HashMap<>();
|
||||
exceptionInfo.put(generateResult.get("tasks_id"), generateResult.get("message"));
|
||||
// 存redis
|
||||
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
try {
|
||||
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
|
||||
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
|
||||
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.get("tasks_id"));
|
||||
} catch (IOException exception) {
|
||||
log.error("手动确认,取消返回队列,不再重新消费");
|
||||
}
|
||||
// 将入参和错误信息存入数据库
|
||||
String exceptionMessage = JSONObject.toJSONString(generateResult) +
|
||||
" Exception message : " + e.getMessage();
|
||||
HashMap<String, String> exceptionInfo = new HashMap<>();
|
||||
exceptionInfo.put(String.valueOf(generateResult.get("tasks_id")), exceptionMessage);
|
||||
// 存redis
|
||||
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
|
||||
}
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start));
|
||||
log.info("============ProcessPoseTransformResult End listening==========");
|
||||
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer1(Message msg, Channel channel) {
|
||||
@@ -329,4 +376,10 @@ public class GenerateConsumer {
|
||||
public void getRelightResult(Message msg, Channel channel) {
|
||||
processRelightResult(msg, channel);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransform}")
|
||||
@RabbitHandler
|
||||
public void getPoseTransformationResult(Message msg, Channel channel) {
|
||||
processPoseTransformResult(msg, channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ public class RabbitMQProperties {
|
||||
private String generateResult;
|
||||
private String toProductImageResult;
|
||||
private String relightResult;
|
||||
private String poseTransform;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@@ -30,6 +30,8 @@ public class CommonConstant {
|
||||
|
||||
public static final String GENERATE_LOGO_SINGLE_CANCEL = "/api/generate_single_logo_cancel/";
|
||||
|
||||
public static final String POSE_TRANSFORMATION_CANCEL = "/api/pose_transform_cancel/";
|
||||
|
||||
public static final String PYTHON_PORT_9996 = "9996";
|
||||
|
||||
public static final String PYTHON_PORT_9997 = "9997";
|
||||
|
||||
@@ -35,6 +35,7 @@ public enum CreditsEventsEnum {
|
||||
RELIGHT("Relight","5"),
|
||||
QUESTIONNAIRE("Questionnaire","100"),
|
||||
IMAGE_TO_SKETCH("ImageToSketch","5"),
|
||||
POSE_TRANSFORMATION("PoseTransformation","10"),
|
||||
|
||||
OTHER("Other","5");
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||
URL url = new URL(path);
|
||||
return url.openStream();
|
||||
} catch (IOException ioException) {
|
||||
log.error("获取文件尺寸异常###{}###path##{}", ExceptionUtil.stacktraceToString(ioException), path);
|
||||
log.error("获取源文件异常###{}###path##{}", ExceptionUtil.stacktraceToString(ioException), path);
|
||||
throw new BusinessException("get.file.failed");
|
||||
}
|
||||
}
|
||||
|
||||
168
src/main/java/com/ai/da/common/utils/MailUtil.java
Normal file
168
src/main/java/com/ai/da/common/utils/MailUtil.java
Normal file
@@ -0,0 +1,168 @@
|
||||
package com.ai.da.common.utils;
|
||||
|
||||
import com.ai.da.model.dto.BasicEmailParamDTO;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.sun.mail.smtp.SMTPTransport;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.InputStreamSource;
|
||||
import org.springframework.mail.MailException;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.*;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MailUtil {
|
||||
|
||||
@Resource
|
||||
private JavaMailSender javaMailSender;
|
||||
|
||||
@Resource
|
||||
private TemplateEngine templateEngine;
|
||||
|
||||
/**
|
||||
* 发送邮件 - 默认发件人
|
||||
*
|
||||
* @param basicEmailParamDTO 发送邮件所需参数
|
||||
* @param inputStreamSource 附件(如果有)
|
||||
*/
|
||||
public int sendMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
|
||||
MimeMessage mimeMessage = createSimpleMail(basicEmailParamDTO, fileName, inputStreamSource);
|
||||
// 提取配置
|
||||
String host;
|
||||
String username;
|
||||
String password;
|
||||
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
|
||||
host = ((JavaMailSenderImpl) javaMailSender).getHost();
|
||||
} else {
|
||||
host = basicEmailParamDTO.getServiceAddress();
|
||||
}
|
||||
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getSenderUser())) {
|
||||
username = ((JavaMailSenderImpl) javaMailSender).getUsername();
|
||||
} else {
|
||||
username = basicEmailParamDTO.getSenderUser();
|
||||
}
|
||||
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
|
||||
password = ((JavaMailSenderImpl) javaMailSender).getPassword();
|
||||
} else {
|
||||
password = basicEmailParamDTO.getPassword();
|
||||
}
|
||||
return sendMail(mimeMessage, host, username, password);
|
||||
}
|
||||
|
||||
private int sendMail(MimeMessage mimeMessage, String host, String username, String password) throws MessagingException {
|
||||
SMTPTransport transport = null;
|
||||
try {
|
||||
// 获取 SMTPTransport
|
||||
transport = (SMTPTransport) mimeMessage.getSession().getTransport("smtp");
|
||||
// 连接到 SMTP 服务器
|
||||
transport.connect(host, username, password);
|
||||
// 发送邮件
|
||||
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
|
||||
// 获取 SMTP 服务器的响应
|
||||
String lastServerResponse = transport.getLastServerResponse();
|
||||
int lastReturnCode = transport.getLastReturnCode();
|
||||
|
||||
log.info("SMTP 状态码: {}, SMTP 服务器响应: {}", lastReturnCode, lastServerResponse);
|
||||
return lastReturnCode;
|
||||
} catch (MailException | MessagingException e) {
|
||||
// 记录日志或执行其他补偿逻辑
|
||||
log.info("邮件发送失败:{}", e.getMessage());
|
||||
} finally {
|
||||
// 关闭连接
|
||||
assert transport != null;
|
||||
transport.close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一封邮件
|
||||
*
|
||||
* @param basicEmailParamDTO 创建邮件需要的参数
|
||||
* @param inputStreamSource 附件(如果有)
|
||||
* @return 一封邮件
|
||||
*/
|
||||
private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
|
||||
// 创建邮件对象
|
||||
MimeMessage message = javaMailSender.createMimeMessage();
|
||||
// 使用 MimeMessageHelper 简化邮件内容和附件的设置
|
||||
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
|
||||
// 设置发件人
|
||||
mimeMessageHelper.setFrom(new InternetAddress(basicEmailParamDTO.getSenderUserMail()));
|
||||
// 设置收件人
|
||||
mimeMessageHelper.setTo(basicEmailParamDTO.getMailTo());
|
||||
// 设置抄送人
|
||||
if (basicEmailParamDTO.getCc() != null && basicEmailParamDTO.getCc().length > 0) {
|
||||
mimeMessageHelper.setCc(basicEmailParamDTO.getCc());
|
||||
}
|
||||
// 设置暗送人
|
||||
if (basicEmailParamDTO.getBcc() != null && basicEmailParamDTO.getBcc().length > 0) {
|
||||
mimeMessageHelper.setBcc(basicEmailParamDTO.getBcc());
|
||||
}
|
||||
// 设置邮件主题
|
||||
mimeMessageHelper.setSubject(basicEmailParamDTO.getSubject());
|
||||
// 设置邮件内容(HTML 格式)
|
||||
mimeMessageHelper.setText(basicEmailParamDTO.getContent(), true);
|
||||
// 设置附件
|
||||
if (inputStreamSource != null) {
|
||||
mimeMessageHelper.addAttachment(fileName, inputStreamSource);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置实体参数
|
||||
*
|
||||
* @param mailTo 接收邮件的邮箱地址
|
||||
* @param jsonObject 模板中变量的值
|
||||
* @return 返回一个MailEntity
|
||||
* @throws AddressException 邮箱地址值异常
|
||||
*/
|
||||
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, JSONObject jsonObject, String templatePath, String title) throws AddressException {
|
||||
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
|
||||
basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
|
||||
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
|
||||
basicEmailParamDTO.setSubject(title);
|
||||
// todo 邮件模板不存在的报错与重试机制
|
||||
basicEmailParamDTO.setContent(setContent(jsonObject, templatePath));
|
||||
return basicEmailParamDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将地址转换为InternetAddress类型
|
||||
*
|
||||
* @param addressList 普通的地址字符串列表
|
||||
* @return InternetAddress类型的地址列表
|
||||
* @throws AddressException 地址异常
|
||||
*/
|
||||
public InternetAddress[] getInternetAddressList(List<String> addressList) throws AddressException {
|
||||
InternetAddress[] toAddress = new InternetAddress[addressList.size()];
|
||||
for (String address : addressList) {
|
||||
toAddress[addressList.indexOf(address)] = new InternetAddress(address);
|
||||
}
|
||||
return toAddress;
|
||||
}
|
||||
|
||||
public String setContent(JSONObject jsonObject, String templatePath) {
|
||||
Context context = new Context();
|
||||
if (Objects.nonNull(jsonObject)) {
|
||||
for (String key : jsonObject.keySet()) {
|
||||
context.setVariable(key, jsonObject.get(key));
|
||||
}
|
||||
}
|
||||
return templateEngine.process(templatePath, context);
|
||||
}
|
||||
|
||||
}
|
||||
43
src/main/java/com/ai/da/controller/EmailController.java
Normal file
43
src/main/java/com/ai/da/controller/EmailController.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.model.dto.BasicEmailParamDTO;
|
||||
import com.ai.da.service.EmailService;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.thymeleaf.context.Context;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
|
||||
@Api(tags = "邮件模块")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/email")
|
||||
public class EmailController {
|
||||
|
||||
@Resource
|
||||
private EmailService emailService;
|
||||
|
||||
@GetMapping("/loadSingleTemplate")
|
||||
public void loadSingleEmailTemplate(){
|
||||
emailService.loadSingleEmailTemplate("templates\\upgrade\\122899_AiDA发版完成通知中文版.html");
|
||||
}
|
||||
|
||||
@GetMapping("/loadTemplate")
|
||||
public void loadTemplatesFromResources(){
|
||||
emailService.loadTemplatesFromResources("templates");
|
||||
}
|
||||
|
||||
@GetMapping("/sendEmailTest")
|
||||
public void sendEmailTest(){
|
||||
Context context = new Context();
|
||||
context.setVariable("username", "小白");
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("username", "小白");
|
||||
emailService.sendEmail(Collections.singletonList("xupei3360@163.com"), jsonObject, "132124_affiliate_accepted_en.html", "测试邮件", null, null );
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
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.dto.*;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.ai.da.service.GenerateService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -12,11 +9,11 @@ import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author XP
|
||||
*/
|
||||
@@ -88,7 +85,7 @@ public class GenerateController {
|
||||
@ApiOperation(value = "imageToSketch")
|
||||
@PostMapping("/imageToSketch")
|
||||
public Response<GenerateResultVO> imageToSketch(@Valid @RequestBody ImageToSketchDTO imageToSketchDTO) {
|
||||
return Response.success(generateService.imageToSketch(imageToSketchDTO));
|
||||
return Response.success(generateService.imageToSketch(imageToSketchDTO, null, null));
|
||||
}
|
||||
|
||||
// modifySketch
|
||||
@@ -98,4 +95,50 @@ public class GenerateController {
|
||||
return Response.success(generateService.modifySketch(generateModifyDTO));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "请求进行姿势变换")
|
||||
@GetMapping("/poseTransform")
|
||||
public Response<String> poseTransform(@ApiParam("projectId") @RequestParam Long projectId,
|
||||
@ApiParam("productImage") @RequestParam String productImage,
|
||||
@ApiParam("poseId") @RequestParam int poseId) {
|
||||
return Response.success(generateService.poseTransform(projectId, productImage, poseId));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取姿势变换生成结果")
|
||||
@GetMapping("/poseTransformResult")
|
||||
public Response<PoseTransformationVO> getPoseTransformationResults(@ApiParam("taskId") @RequestParam String taskId) {
|
||||
PoseTransformationVO generateResult = generateService.getPoseTransformationResult(taskId);
|
||||
return Response.success(generateResult);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "修改模特比例")
|
||||
@PostMapping("/modifyProportion")
|
||||
public Response<String> modifyModelProportion(@Valid @RequestBody ModifyModelProportionDTO proportionDTO){
|
||||
String path = generateService.modifyModelProportion(proportionDTO);
|
||||
return Response.success(path);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "拼贴图生成线稿")
|
||||
@PostMapping("/genSketchRecon")
|
||||
public Response<GenerateResultVO> sketchReconstructionGenerate(@Valid @RequestBody SketchReconstructionDTO sketchReconstructionDTO){
|
||||
GenerateResultVO generateResultVO = generateService.sketchReconstructionGenerate(sketchReconstructionDTO);
|
||||
return Response.success(generateResultVO);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "拼贴图画布保存")
|
||||
@GetMapping("/saveReconCanvas")
|
||||
public Response<String> sketchReconstructionSave(@RequestParam("file") MultipartFile file, @RequestParam("projectId") Long projectId){
|
||||
generateService.sketchReconstructionSave(file, projectId);
|
||||
return Response.success("success");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取拼贴图画布")
|
||||
@GetMapping("/getReconCanvas")
|
||||
public Response<SketchReconstructionVO> getSketchReconstruction(@RequestParam("projectId") Long projectId){
|
||||
SketchReconstructionVO sketchReconstruction = generateService.getSketchReconstruction(projectId);
|
||||
return Response.success(sketchReconstruction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.primary.entity.EmailLog;
|
||||
|
||||
public interface EmailLogMapper extends CommonMapper<EmailLog> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.primary.entity.EmailTemplate;
|
||||
|
||||
public interface EmailTemplateMapper extends CommonMapper<EmailTemplate> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||
import com.ai.da.mapper.primary.entity.PoseTransformation;
|
||||
|
||||
public interface PoseTransformationMapper extends CommonMapper<PoseTransformation> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.mapper.primary.entity.SketchReconstruction;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface SketchReconstructionMapper extends BaseMapper<SketchReconstruction> {
|
||||
}
|
||||
35
src/main/java/com/ai/da/mapper/primary/entity/EmailLog.java
Normal file
35
src/main/java/com/ai/da/mapper/primary/entity/EmailLog.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("t_email_log")
|
||||
public class EmailLog extends BaseEntity {
|
||||
|
||||
private Long templateId;
|
||||
|
||||
private String parameter;
|
||||
|
||||
// from是SQL关键字,直接使用会报错
|
||||
private String sender;
|
||||
|
||||
private String recipients;
|
||||
|
||||
private String cc = null;
|
||||
|
||||
private String bcc = null;
|
||||
|
||||
private String subject;
|
||||
|
||||
/**
|
||||
* failed 邮件发送失败(如网络问题、邮件服务器问题等)。
|
||||
* retrying 邮件发送失败后,正在重试发送。
|
||||
* delivered 邮件已成功投递到收件人的邮箱服务器。
|
||||
*/
|
||||
private String status;
|
||||
|
||||
private int retryCount = 0;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("t_email_template")
|
||||
public class EmailTemplate extends BaseEntity {
|
||||
|
||||
// 考虑添加唯一索引
|
||||
private String templateName;
|
||||
|
||||
private String templatePath;
|
||||
|
||||
private String content;
|
||||
|
||||
private int version;
|
||||
|
||||
private String language;
|
||||
|
||||
private byte isDeleted = 0;
|
||||
}
|
||||
@@ -85,6 +85,15 @@ public class Generate {
|
||||
*/
|
||||
private Long styleImageElementId;
|
||||
|
||||
/**
|
||||
* 由拼贴图生成线稿的项目id
|
||||
*/
|
||||
private Long projectId;
|
||||
/**
|
||||
* 输入模型的拼贴图
|
||||
*/
|
||||
private String inputImageUrl;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("t_pose_transformation")
|
||||
@Data
|
||||
public class PoseTransformation extends BaseEntity {
|
||||
|
||||
private Long projectId;
|
||||
|
||||
private Long accountId;
|
||||
|
||||
private String uniqueId;
|
||||
|
||||
private String productImage;
|
||||
|
||||
private int poseId;
|
||||
|
||||
private String gifUrl;
|
||||
|
||||
private String videoUrl;
|
||||
// GIF第一帧截图
|
||||
private String imageUrl;
|
||||
|
||||
private byte isLiked;
|
||||
|
||||
private byte isDeleted;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ai.da.mapper.primary.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("t_sketch_reconstruction")
|
||||
public class SketchReconstruction extends BaseEntity{
|
||||
|
||||
private Long projectId;
|
||||
// 最后一次拼贴图生成的sketch
|
||||
private String collageImgSketchUrl;
|
||||
|
||||
private Long generateDetailId;
|
||||
|
||||
private String canvasUrl;
|
||||
|
||||
}
|
||||
29
src/main/java/com/ai/da/model/dto/BasicEmailParamDTO.java
Normal file
29
src/main/java/com/ai/da/model/dto/BasicEmailParamDTO.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
@Data
|
||||
public class BasicEmailParamDTO {
|
||||
/** 邮箱服务器 */
|
||||
private String serviceAddress;
|
||||
/** 邮箱服务器端口 */
|
||||
private String servicePort;
|
||||
/** 发件人邮箱地址 */
|
||||
private String senderUserMail;
|
||||
/** 发件人账号 */
|
||||
private String senderUser;
|
||||
/** 发件人密码 */
|
||||
private String password;
|
||||
/** 邮件标题 */
|
||||
private String subject;
|
||||
/** 邮件内容 */
|
||||
private String content;
|
||||
/** 收件人邮箱地址 */
|
||||
private InternetAddress[] mailTo;
|
||||
/** 抄送人 */
|
||||
private InternetAddress[] cc;
|
||||
/** 暗抄送人 */
|
||||
private InternetAddress[] bcc;
|
||||
}
|
||||
@@ -19,4 +19,13 @@ public class ImageToSketchDTO {
|
||||
|
||||
@ApiModelProperty("性别")
|
||||
private String gender;
|
||||
|
||||
public ImageToSketchDTO() {
|
||||
}
|
||||
|
||||
public ImageToSketchDTO(Long elementId, String style, String gender) {
|
||||
this.elementId = elementId;
|
||||
this.style = style;
|
||||
this.gender = gender;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
@ApiModel("ModifyModelProportionDTO")
|
||||
public class ModifyModelProportionDTO {
|
||||
@ApiModelProperty("模特id")
|
||||
@NotNull(message = "model id cannot be empty")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("Library || System")
|
||||
@NotBlank(message = "model type cannot be empty")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("top")
|
||||
@NotNull(message = "top cannot be empty")
|
||||
private Integer top;
|
||||
|
||||
@ApiModelProperty("bottom")
|
||||
@NotNull(message = "bottom cannot be empty")
|
||||
private Integer bottom;
|
||||
|
||||
@ApiModelProperty("stretch")
|
||||
@NotNull(message = "stretch cannot be empty")
|
||||
private Float stretch;
|
||||
|
||||
@ApiModelProperty("模特minio地址")
|
||||
@NotBlank(message = "modelPath type cannot be empty")
|
||||
private String modelPath;
|
||||
|
||||
@NotNull(message = "handLeft cannot be null")
|
||||
@NotEmpty(message = "handLeft cannot be empty")
|
||||
@ApiModelProperty("handLeft")
|
||||
private Float[] handLeft;
|
||||
|
||||
@NotNull(message = "handRight cannot be null")
|
||||
@NotEmpty(message = "handRight cannot be empty")
|
||||
@ApiModelProperty("handRight")
|
||||
private Float[] handRight;
|
||||
|
||||
@NotNull(message = "shoulderLeft cannot be null")
|
||||
@NotEmpty(message = "shoulderLeft cannot be empty")
|
||||
@ApiModelProperty("shoulderLeft")
|
||||
private Float[] shoulderLeft;
|
||||
|
||||
@NotNull(message = "shoulderRight cannot be null")
|
||||
@NotEmpty(message = "shoulderRight cannot be empty")
|
||||
@ApiModelProperty("shoulderRight")
|
||||
private Float[] shoulderRight;
|
||||
|
||||
@NotNull(message = "waistbandLeft cannot be null")
|
||||
@NotEmpty(message = "waistbandLeft cannot be empty")
|
||||
@ApiModelProperty("waistbandLeft")
|
||||
private Float[] waistbandLeft;
|
||||
|
||||
@NotNull(message = "waistbandRight cannot be null")
|
||||
@NotEmpty(message = "waistbandRight cannot be empty")
|
||||
@ApiModelProperty("waistbandRight")
|
||||
private Float[] waistbandRight;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ai.da.model.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel(value = "sketch拼贴")
|
||||
public class SketchReconstructionDTO {
|
||||
|
||||
@ApiModelProperty("项目id")
|
||||
private Long projectId;
|
||||
|
||||
@ApiModelProperty("拼贴图的base64数据")
|
||||
private String collagePicture;
|
||||
// 识别衣服类型用
|
||||
@ApiModelProperty("性别")
|
||||
private String gender;
|
||||
}
|
||||
25
src/main/java/com/ai/da/model/vo/PoseTransformationVO.java
Normal file
25
src/main/java/com/ai/da/model/vo/PoseTransformationVO.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PoseTransformationVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String taskId;
|
||||
|
||||
private String gifUrl;
|
||||
|
||||
private String videoUrl;
|
||||
// GIF第一帧截图
|
||||
private String imageUrl;
|
||||
|
||||
private byte isLiked;
|
||||
|
||||
private String status;
|
||||
}
|
||||
15
src/main/java/com/ai/da/model/vo/SketchReconstructionVO.java
Normal file
15
src/main/java/com/ai/da/model/vo/SketchReconstructionVO.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.ai.da.model.vo;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SketchReconstructionVO {
|
||||
|
||||
private JSONObject canvasFile;
|
||||
|
||||
private String collageSketchUrl;
|
||||
|
||||
private boolean isLiked;
|
||||
|
||||
}
|
||||
@@ -3966,4 +3966,124 @@ public class PythonService {
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean poseTransformation(String productImage, int poseId, String taskId) {
|
||||
OkHttpClient client = new OkHttpClient().newBuilder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒)
|
||||
.readTimeout(60, TimeUnit.SECONDS)//读取超时(单位:秒)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒)
|
||||
.build();
|
||||
MediaType mediaType = MediaType.parse("application/json");
|
||||
Map<String, String> content = Maps.newHashMap();
|
||||
content.put("image_url", productImage);
|
||||
content.put("tasks_id", taskId);
|
||||
content.put("pose_id", String.valueOf(poseId));
|
||||
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content));
|
||||
|
||||
log.info("poseTransformation 请求地址: {}", accessPythonIp + ":" + accessPythonPort + "/api/pose_transform");
|
||||
Request request = new Request.Builder()
|
||||
.url(accessPythonIp + ":" + accessPythonPort + "/api/pose_transform")
|
||||
.method("POST", body)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.build();
|
||||
Response response = null;
|
||||
String bodyString;
|
||||
try {
|
||||
log.info("poseTransformation请求入参content###{}", JSON.toJSONString(content));
|
||||
response = client.newCall(request).execute();
|
||||
} catch (IOException ioException) {
|
||||
log.error("PythonService##poseTransformation异常###{}", ExceptionUtil.getThrowableList(ioException));
|
||||
throw new BusinessException(ioException.getMessage());
|
||||
}
|
||||
|
||||
// 判断是否生成失败
|
||||
if (Objects.isNull(response.body())) {
|
||||
log.error("PythonService##poseTransformation异常###{}", "response or body is empty!");
|
||||
throw new BusinessException("PythonService##poseTransformation异常###: response or body is empty!");
|
||||
} else if (response.code() != HttpURLConnection.HTTP_OK) {
|
||||
log.error("PythonService##poseTransformation异常###{}", "Response error!Response code ## " + response.code() + " ##");
|
||||
throw new BusinessException("PythonService##poseTransformation异常### Response error!Response code ## " + response.code() + " ##");
|
||||
} else {
|
||||
try {
|
||||
bodyString = response.body().string();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
throw new BusinessException(e.getMessage());
|
||||
}
|
||||
}
|
||||
JSONObject jsonObject = JSON.parseObject(bodyString);
|
||||
Boolean result = JSON.parseObject(JSON.toJSONString(response)).getBoolean("successful");
|
||||
|
||||
if (result && jsonObject.get("code").equals(200)) {
|
||||
log.info("poseTransformation##responseObject###{}", jsonObject);
|
||||
return Boolean.TRUE;
|
||||
} else {
|
||||
log.info("poseTransformation失败###{}", jsonObject);
|
||||
log.info("poseTransformation Exception! Code : {}", jsonObject.get("code"));
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
public String modifyModelProportion(String mannequinPath, Float scale, String name, int top, int bottom) {
|
||||
OkHttpClient client = new OkHttpClient().newBuilder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒)
|
||||
.readTimeout(60, TimeUnit.SECONDS)//读取超时(单位:秒)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒)
|
||||
.build();
|
||||
|
||||
MediaType mediaType = MediaType.parse("application/json");
|
||||
Map<String, String> content = Maps.newHashMap();
|
||||
// 模特的minio地址
|
||||
content.put("mannequins", mannequinPath);
|
||||
// 缩放比
|
||||
content.put("scale", scale.toString());
|
||||
// 结果存放桶名
|
||||
content.put("bucket_name", "aida-users");
|
||||
// 模特名uuid
|
||||
content.put("mannequin_name", name);
|
||||
content.put("top", String.valueOf(top));
|
||||
content.put("bottom", String.valueOf(bottom));
|
||||
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content));
|
||||
|
||||
log.info("modifyModelProportion 请求地址: {},\n 参数:{}", accessPythonIp + ":" + accessPythonPort + "/api/mannequins_edit", JSON.toJSONString(content));
|
||||
Request request = new Request.Builder()
|
||||
.url(accessPythonIp + ":" + accessPythonPort + "/api/mannequins_edit")
|
||||
.method("POST", body)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.build();
|
||||
Response response = null;
|
||||
try {
|
||||
response = client.newCall(request).execute();
|
||||
} catch (IOException ioException) {
|
||||
log.error("PythonService##modifyModelProportion异常###{}", 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("modifyModelProportion 失败。 Response code {}", responseCode);
|
||||
throw new BusinessException("modifyModelProportion 失败。 Response code " + responseCode);
|
||||
}
|
||||
JSONObject jsonObject = JSON.parseObject(bodyString);
|
||||
if (response.isSuccessful() && jsonObject.get("msg").equals("OK!")) {
|
||||
String modifiedModel = jsonObject.get("data").toString();
|
||||
log.info("modifyModelProportion 结果 : {}", modifiedModel);
|
||||
return modifiedModel;
|
||||
}else {
|
||||
log.info("modifyModelProportion 失败。 Response code {}", responseCode);
|
||||
throw new BusinessException("modifyModelProportion 失败。 Response code " + responseCode);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("modifyModelProportion 失败; error message => {}", e.getMessage());
|
||||
response.close();
|
||||
throw new BusinessException("generate.interface.error");
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
138
src/main/java/com/ai/da/service/EmailService.java
Normal file
138
src/main/java/com/ai/da/service/EmailService.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.mapper.primary.entity.TrialOrder;
|
||||
import com.ai.da.model.dto.AffiliateEmailParamsDTO;
|
||||
import com.ai.da.model.dto.BasicEmailParamDTO;
|
||||
import com.ai.da.model.dto.SubscriptionEmailParamsDTO;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.core.io.InputStreamSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface EmailService {
|
||||
|
||||
|
||||
void loadSingleEmailTemplate(String templatePath);
|
||||
|
||||
void loadTemplatesFromResources(String resourcesPath);
|
||||
|
||||
/**
|
||||
* 发邮件
|
||||
*
|
||||
* @param mailTo 收件人邮箱
|
||||
* @param jsonObject 动态邮件模板参数
|
||||
* @param templateName 邮件模板名(只有文件名且需要带文件后缀)
|
||||
* @param title 邮件标题
|
||||
* @param fileName 附件文件名。没有附件置为null
|
||||
* @param inputStreamSource 附件文件数据。没有附件置为null
|
||||
*/
|
||||
|
||||
void sendEmail(List<String> mailTo, JSONObject jsonObject, String templateName, String title, String fileName, InputStreamSource inputStreamSource);
|
||||
|
||||
/**
|
||||
* 适用于 : 需要自定义发件人信息
|
||||
*
|
||||
* @param jsonObject 模板参数
|
||||
* @param basicEmailParamDTO 包含发件人信息、邮件标题、收件人信息
|
||||
* @param templateName 使用的模板文件名
|
||||
* @param fileName 附件文件名
|
||||
* @param inputStreamSource 附件文件信息
|
||||
*/
|
||||
|
||||
void sendEmail(JSONObject jsonObject, BasicEmailParamDTO basicEmailParamDTO, String templateName, String fileName, InputStreamSource inputStreamSource);
|
||||
|
||||
// 登入模板id
|
||||
String LOGIN_TEMPLATE_ID = "58020_login_aida_en.html";
|
||||
// 修改密码模板id
|
||||
String UPDATE_PWD_TEMPLATE_ID = "58022_update_password.html";
|
||||
// 异常ip模板id
|
||||
String EXCEPTION_ID_TEMPLATE_ID = "58021_exception_ip.html";
|
||||
// 绑定邮箱模板id
|
||||
String BIND_MAILBOX_TEMPLATE_ID = "132754_绑定邮箱.html";
|
||||
// 更换绑定邮箱
|
||||
String CHANGE_MAILBOX_TEMPLATE_ID = "128210_change_mailbox_en.html";
|
||||
|
||||
/**
|
||||
* 发送登录相关的邮件
|
||||
*
|
||||
* @param receiverAddress 收件地址
|
||||
* @param ip 请求ip
|
||||
* @param templateId 模板ID名
|
||||
* @param verifyCode 验证码
|
||||
*/
|
||||
Boolean send(String receiverAddress, String ip, String templateId, String verifyCode);
|
||||
|
||||
/**
|
||||
* 发送试用订单相关的邮件
|
||||
*
|
||||
* @param receiverAddress 收件人邮箱地址
|
||||
* @param trialOrder 试用订单相关参数
|
||||
* @param emailType 邮件类型:1 - 提交试用请求,2 - 审批通过,3 - 试用请求通过通知
|
||||
* @param country 通过城市判断邮件模板的语言
|
||||
* @param link ?
|
||||
*/
|
||||
void sendCustomEmail(String receiverAddress, TrialOrder trialOrder, int emailType, String country, Boolean link);
|
||||
|
||||
/**
|
||||
* 发送昨日的试用订单用户数据
|
||||
*
|
||||
* @param receiverAddress 收件人地址
|
||||
* @param fileName 附件文件名
|
||||
* @param inputStreamSource 附件文件数据
|
||||
*/
|
||||
void sendExcelEmail(List<String> receiverAddress, String fileName, InputStreamSource inputStreamSource);
|
||||
|
||||
/**
|
||||
* 发送昨日的试用订单用户数据--无试用订单情况
|
||||
*
|
||||
* @param receiverAddress 收件人地址
|
||||
*/
|
||||
void sendNoExcelEmail(List<String> receiverAddress);
|
||||
|
||||
/**
|
||||
* 向账号快要到期的用户发送提醒邮件
|
||||
*
|
||||
* @param account 账号信息
|
||||
*/
|
||||
void sendWillBeExpiredEmail(Account account);
|
||||
|
||||
/**
|
||||
* 发送系统升级通知邮件
|
||||
*
|
||||
* @param account 用户信息
|
||||
* @param senderAddress 发件人邮件
|
||||
* @param type 邮件类型
|
||||
*/
|
||||
void sendUpgradeNotification(Account account, String senderAddress, Integer type);
|
||||
|
||||
/**
|
||||
* 通知在Code_Create上付费的用户,AiDA账号的更新
|
||||
*
|
||||
* @param receiverAddress 收件人地址
|
||||
* @param emailType 邮件类型
|
||||
* @param country 国家(确定发送邮件的语言)
|
||||
* @param userName 用户名
|
||||
* @param date 账号到期时间
|
||||
*/
|
||||
void notificationForPaidUser(String receiverAddress, int emailType, String country, String userName, String date);
|
||||
|
||||
/**
|
||||
* 广场用户注册通知邮件
|
||||
*
|
||||
* @param userEmail
|
||||
* @param randomVerifyCode
|
||||
* @return
|
||||
*/
|
||||
Boolean designWorksRegister(String userEmail, String randomVerifyCode);
|
||||
|
||||
void uploadTimeoutReminder(String userName, String time);
|
||||
|
||||
boolean subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress);
|
||||
|
||||
void affiliateEmailReminder(List<String> receiverAddress, AffiliateEmailParamsDTO paramsDTO, String type);
|
||||
|
||||
void creditsPurchaseReminder(String username, String quantity, String amount);
|
||||
|
||||
void commonExceptionReminder(String functionName, List<String> destination);
|
||||
}
|
||||
@@ -2,12 +2,10 @@ 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.dto.*;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -44,7 +42,21 @@ public interface GenerateService extends IService<Generate> {
|
||||
|
||||
List<Map<String, Object>> getCountByUserAndTime(String startTime, String endTime, List<Long> accountIdList);
|
||||
|
||||
GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO);
|
||||
GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO, String collagePictureUrl, Long projectId);
|
||||
|
||||
GenerateResultVO modifySketch(GenerateModifyDTO generateModifyDTO);
|
||||
|
||||
String poseTransform(Long projectId, String productImage, int poseId);
|
||||
|
||||
void processPoseTransformResult(String taskId, String gifUrl, String videoUrl, String imageUrl);
|
||||
|
||||
PoseTransformationVO getPoseTransformationResult(String taskId);
|
||||
|
||||
String modifyModelProportion(ModifyModelProportionDTO proportionDTO);
|
||||
|
||||
GenerateResultVO sketchReconstructionGenerate(SketchReconstructionDTO sketchReconstructionDTO);
|
||||
|
||||
String sketchReconstructionSave(MultipartFile multipartFile, Long projectId);
|
||||
|
||||
SketchReconstructionVO getSketchReconstruction(Long projectId);
|
||||
}
|
||||
|
||||
664
src/main/java/com/ai/da/service/impl/EmailServiceImpl.java
Normal file
664
src/main/java/com/ai/da/service/impl/EmailServiceImpl.java
Normal file
@@ -0,0 +1,664 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.utils.DateUtil;
|
||||
import com.ai.da.common.utils.MailUtil;
|
||||
import com.ai.da.mapper.primary.EmailLogMapper;
|
||||
import com.ai.da.mapper.primary.EmailTemplateMapper;
|
||||
import com.ai.da.mapper.primary.entity.*;
|
||||
import com.ai.da.model.dto.AffiliateEmailParamsDTO;
|
||||
import com.ai.da.model.dto.BasicEmailParamDTO;
|
||||
import com.ai.da.model.dto.SubscriptionEmailParamsDTO;
|
||||
import com.ai.da.service.EmailService;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.tencentcloudapi.common.Credential;
|
||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||
import com.tencentcloudapi.common.profile.ClientProfile;
|
||||
import com.tencentcloudapi.common.profile.HttpProfile;
|
||||
import com.tencentcloudapi.ses.v20201002.SesClient;
|
||||
import com.tencentcloudapi.ses.v20201002.models.SendEmailRequest;
|
||||
import com.tencentcloudapi.ses.v20201002.models.SendEmailResponse;
|
||||
import com.tencentcloudapi.ses.v20201002.models.Template;
|
||||
import jdk.nashorn.internal.ir.ObjectNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.InputStreamSource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.AddressException;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class EmailServiceImpl implements EmailService {
|
||||
|
||||
@Resource
|
||||
private MailUtil mailUtil;
|
||||
@Resource
|
||||
private EmailTemplateMapper emailTemplateMapper;
|
||||
@Resource
|
||||
private EmailLogMapper emailLogMapper;
|
||||
|
||||
public void loadSingleEmailTemplate(String templatePath){
|
||||
// 获取 ClassLoader
|
||||
ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
// 获取文件的 URL
|
||||
URL resourceUrl = classLoader.getResource(templatePath);
|
||||
|
||||
if (resourceUrl == null) {
|
||||
System.out.println("File not found: " + templatePath);
|
||||
return;
|
||||
}
|
||||
// 获取文件名
|
||||
String fileName = templatePath.substring(templatePath.lastIndexOf("\\") + 1);
|
||||
// 获取文件内容
|
||||
try (InputStream inputStream = resourceUrl.openStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||
StringBuilder content = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
content.append(line).append("\n");
|
||||
}
|
||||
// 调用方法将数据存入数据库
|
||||
saveTemplateToDatabase(fileName, removePrefixAndFileExtension(templatePath), String.valueOf(content));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadTemplatesFromResources(String resourcesPath) {
|
||||
try {
|
||||
// 获取 ClassLoader
|
||||
ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
// 获取 resources 文件夹的路径
|
||||
Path path = Paths.get(classLoader.getResource(resourcesPath).toURI());
|
||||
|
||||
// 遍历文件夹
|
||||
try (Stream<Path> paths = Files.walk(path)) {
|
||||
paths.filter(Files::isRegularFile)
|
||||
.forEach(file -> {
|
||||
try {
|
||||
// 读取文件内容
|
||||
String content = new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
|
||||
// 获取文件名和路径
|
||||
String fileName = file.getFileName().toString();
|
||||
// 去除文件后缀
|
||||
String filePath = removePrefixAndFileExtension(file.toString());
|
||||
// 调用方法将数据存入数据库
|
||||
saveTemplateToDatabase(fileName, filePath, content);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 去掉文件路径的前缀和后缀
|
||||
*
|
||||
* @param filePath 文件路径(可以包含路径)
|
||||
* @return 去掉后缀的文件名
|
||||
*/
|
||||
private static String removePrefixAndFileExtension(String filePath) {
|
||||
String keyword = "templates\\";
|
||||
int index = filePath.indexOf(keyword);
|
||||
if (index == -1) {
|
||||
return null; // 如果路径中不包含 templates/,返回空
|
||||
}
|
||||
int lastDotIndex = filePath.lastIndexOf('.');
|
||||
if (lastDotIndex == -1) {
|
||||
return filePath.substring(index + keyword.length()); // 没有后缀,直接返回
|
||||
}
|
||||
return filePath.substring(index+ keyword.length(), lastDotIndex);
|
||||
}
|
||||
|
||||
public void saveTemplateToDatabase(String fileName, String filePath, String content) {
|
||||
// 这里实现将数据存入数据库的逻辑
|
||||
// 使用 JDBC 或 JPA 将 fileName、filePath 和 content 插入到 email_template 表
|
||||
log.info("Saving to database: {}", fileName);
|
||||
|
||||
EmailTemplate emailTemplate = new EmailTemplate();
|
||||
emailTemplate.setTemplateName(fileName);
|
||||
emailTemplate.setTemplatePath(filePath);
|
||||
emailTemplate.setContent(content);
|
||||
emailTemplate.setVersion(1);
|
||||
emailTemplate.setCreateTime(LocalDateTime.now());
|
||||
if (fileName.endsWith("en.html")){
|
||||
emailTemplate.setLanguage("EN");
|
||||
}else {
|
||||
emailTemplate.setLanguage("CN");
|
||||
}
|
||||
|
||||
emailTemplateMapper.insert(emailTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发邮件
|
||||
* @param mailTo 收件人邮箱
|
||||
* @param jsonObject 动态邮件模板【参数】
|
||||
* @param templateName 邮件模板名(只有文件名且需要带文件后缀)
|
||||
* @param title 邮件标题
|
||||
* @param fileName 附件文件名
|
||||
* @param inputStreamSource 附件
|
||||
*/
|
||||
public void sendEmail(List<String> mailTo, JSONObject jsonObject, String templateName, String title, String fileName, InputStreamSource inputStreamSource) {
|
||||
EmailTemplate emailTemplate = getEmailTemplateByName(templateName);
|
||||
if (Objects.isNull(emailTemplate)){
|
||||
log.error("Email template: {}, dose not exist!", templateName);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
BasicEmailParamDTO basicEmailParamDTO = mailUtil.setBasicEmailParams(mailTo, jsonObject, emailTemplate.getTemplatePath(), title);
|
||||
int lastReturnCode = mailUtil.sendMail(basicEmailParamDTO, fileName, inputStreamSource);
|
||||
|
||||
if (lastReturnCode == 250) {
|
||||
log.info("邮件发送成功!Subject : {}", basicEmailParamDTO.getSubject());
|
||||
} else if (lastReturnCode == 450) {
|
||||
log.info("目标邮箱 {} 暂时不可用,请稍后重试", mailTo);
|
||||
} else if (lastReturnCode == 550) {
|
||||
log.info("目标邮箱 {} 不可用,邮件发送失败", mailTo);
|
||||
} else {
|
||||
log.info("邮件发送失败,Subject : {}, 状态码: {}", basicEmailParamDTO.getSubject(), lastReturnCode);
|
||||
}
|
||||
|
||||
EmailLog emailLog = new EmailLog();
|
||||
emailLog.setTemplateId(emailTemplate.getId());
|
||||
if (Objects.nonNull(jsonObject)) emailLog.setParameter(jsonObject.toString());
|
||||
emailLog.setSender("info@aida.com.hk");
|
||||
emailLog.setRecipients(mailTo.toString());
|
||||
emailLog.setSubject(title);
|
||||
emailLog.setCreateTime(LocalDateTime.now());
|
||||
switch (lastReturnCode) {
|
||||
case 0:
|
||||
break;
|
||||
case 250:
|
||||
emailLog.setStatus("delivered");
|
||||
break;
|
||||
case 450:
|
||||
emailLog.setStatus("retrying");
|
||||
break;
|
||||
case 550:
|
||||
emailLog.setStatus("failed");
|
||||
break;
|
||||
}
|
||||
emailLogMapper.insert(emailLog);
|
||||
|
||||
} catch (MessagingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 适用于 : 需要自定义发件人信息
|
||||
* @param jsonObject 模板参数
|
||||
* @param basicEmailParamDTO 包含发件人信息、邮件标题、收件人信息
|
||||
* @param templateName 使用的模板文件名
|
||||
* @param fileName 附件文件名
|
||||
* @param inputStreamSource 附件文件信息
|
||||
*/
|
||||
public void sendEmail(JSONObject jsonObject, BasicEmailParamDTO basicEmailParamDTO, String templateName, String fileName, InputStreamSource inputStreamSource) {
|
||||
EmailTemplate emailTemplate = getEmailTemplateByName(templateName);
|
||||
if (Objects.isNull(emailTemplate)){
|
||||
log.error("Email template: {}, dose not exist!", templateName);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
basicEmailParamDTO.setContent(mailUtil.setContent(jsonObject, emailTemplate.getTemplatePath()));
|
||||
int lastReturnCode = mailUtil.sendMail(basicEmailParamDTO, fileName, inputStreamSource);
|
||||
EmailLog emailLog = new EmailLog();
|
||||
emailLog.setTemplateId(emailTemplate.getId());
|
||||
if (Objects.nonNull(jsonObject)) emailLog.setParameter(jsonObject.toString());
|
||||
emailLog.setSender(basicEmailParamDTO.getSenderUser());
|
||||
emailLog.setRecipients(basicEmailParamDTO.getMailTo().toString());
|
||||
emailLog.setSubject(basicEmailParamDTO.getSubject());
|
||||
emailLog.setCreateTime(LocalDateTime.now());
|
||||
switch (lastReturnCode) {
|
||||
case 0:
|
||||
break;
|
||||
case 250:
|
||||
emailLog.setStatus("delivered");
|
||||
break;
|
||||
case 450:
|
||||
emailLog.setStatus("retrying");
|
||||
break;
|
||||
case 550:
|
||||
emailLog.setStatus("failed");
|
||||
break;
|
||||
}
|
||||
emailLogMapper.insert(emailLog);
|
||||
|
||||
} catch (MessagingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public EmailTemplate getEmailTemplateByName(String templateName) {
|
||||
QueryWrapper<EmailTemplate> qw = new QueryWrapper<>();
|
||||
qw.eq("template_name", templateName).orderByDesc("id");
|
||||
List<EmailTemplate> emailTemplates = emailTemplateMapper.selectList(qw);
|
||||
if (emailTemplates.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return emailTemplates.get(0);
|
||||
}
|
||||
|
||||
// 登入主题
|
||||
public final String LOGIN_SUBJECT = "Log on";
|
||||
// 忘记密码主题
|
||||
public final String FORGET_PWD_SUBJECT = "Reset password";
|
||||
// 异常ip
|
||||
public final String EXCEPTION_ID_SUBJECT = "Exception ip";
|
||||
// 绑定邮箱
|
||||
public final String BIND_MAILBOX_SUBJECT = "绑定邮箱";
|
||||
// 更换邮箱
|
||||
public final String CHANGE_MAILBOX_SUBJECT = "Change Mailbox";
|
||||
|
||||
// 登入模板id
|
||||
// public final String LOGIN_TEMPLATE_ID = "58020_login_aida_en.html";
|
||||
// 修改密码模板id
|
||||
// public final String UPDATE_PWD_TEMPLATE_ID = "58022_update_password.html";
|
||||
// 异常ip模板id
|
||||
// public final String EXCEPTION_ID_TEMPLATE_ID = "58021_exception_ip.html";
|
||||
// 绑定邮箱模板id
|
||||
// public final String BIND_MAILBOX_TEMPLATE_ID = "132754_绑定邮箱.html";
|
||||
// 更换绑定邮箱
|
||||
// public final String CHANGE_MAILBOX_TEMPLATE_ID = "128210_change_mailbox_en.html";
|
||||
|
||||
public Boolean send(String receiverAddress, String ip, String templateId, String verifyCode) {
|
||||
String subject = Objects.equals(templateId, LOGIN_TEMPLATE_ID) ? LOGIN_SUBJECT :
|
||||
Objects.equals(templateId, UPDATE_PWD_TEMPLATE_ID) ? FORGET_PWD_SUBJECT :
|
||||
Objects.equals(templateId, EXCEPTION_ID_TEMPLATE_ID) ? EXCEPTION_ID_SUBJECT :
|
||||
Objects.equals(templateId, CHANGE_MAILBOX_TEMPLATE_ID) ? CHANGE_MAILBOX_SUBJECT : BIND_MAILBOX_SUBJECT;
|
||||
|
||||
JSONObject jsonObject = contractTemplate(templateId, verifyCode, ip);
|
||||
sendEmail(Collections.singletonList(receiverAddress), jsonObject, templateId, subject, null, null);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
private static JSONObject contractTemplate(String templateId, String verifyCode, String ip) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
if (templateId == EXCEPTION_ID_TEMPLATE_ID) {
|
||||
jsonObject.put("exceptionIp", ip);
|
||||
jsonObject.put("loginTime", DateUtil.dateToStr(new Date(), DateUtil.YYYY_MM_DD_HH_MM_SS));
|
||||
} else {
|
||||
jsonObject.put("code", verifyCode);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
|
||||
private final static String YOUR_TRIAL_TEMPLATE_ID = "117214_trailOrderTemplate.html";
|
||||
private final static String APPROVAL_TEMPLATE_ID = "117215_trailOrderApprovalTemplate.html";
|
||||
private final static String NOTIFICATION_TEMPLATE_ID = "117216_notificationTemplate.html";
|
||||
private final static String NOTIFICATION_CHINESE_TEMPLATE_ID = "122229_notificationChineseTemplate.html";
|
||||
|
||||
/**
|
||||
* 发送不同类型的邮件
|
||||
*
|
||||
* @param receiverAddress 收件人邮箱地址
|
||||
* @param emailType 邮件类型:1 - 提交试用请求,2 - 审批通过,3 - 试用请求通过通知
|
||||
* @return 发送结果
|
||||
*/
|
||||
// 由于原本的参数【String senderAddress】在实际使用过程中都是空,即使用默认发件地址,故这里删除该参数
|
||||
// todo 确认入参能否被删除
|
||||
public void sendCustomEmail(String receiverAddress, TrialOrder trialOrder, int emailType, String country, Boolean link) {
|
||||
|
||||
// 根据邮件类型设置不同的主题和模板
|
||||
String subject = "";
|
||||
String templateId = "";
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
switch (emailType) {
|
||||
case 1:
|
||||
subject = "试用订单请求";
|
||||
templateId = YOUR_TRIAL_TEMPLATE_ID;
|
||||
jsonObject = buildTrialOrderData(trialOrder, null);
|
||||
break;
|
||||
case 2:
|
||||
subject = "试用订单审批通过";
|
||||
templateId = APPROVAL_TEMPLATE_ID;
|
||||
jsonObject = buildTrialOrderData(trialOrder, null);
|
||||
break;
|
||||
case 3:
|
||||
subject = "Approval Confirmation for AiDA System Trial Access";
|
||||
if (country.equals("China")) {
|
||||
templateId = NOTIFICATION_CHINESE_TEMPLATE_ID;
|
||||
} else {
|
||||
templateId = NOTIFICATION_TEMPLATE_ID;
|
||||
}
|
||||
jsonObject = buildTrialOrderData(trialOrder, link);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// 发送邮件
|
||||
sendEmail(Collections.singletonList(receiverAddress), jsonObject, templateId, subject, null, null);
|
||||
}
|
||||
|
||||
// 构建试用订单数据
|
||||
private JSONObject buildTrialOrderData(TrialOrder trialOrder, Boolean link) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
// 设置试用订单通过通知相关数据
|
||||
jsonObject.put("title", trialOrder.getTitle());
|
||||
jsonObject.put("surname", trialOrder.getSurname());
|
||||
jsonObject.put("givenName", trialOrder.getGivenName());
|
||||
jsonObject.put("userName", trialOrder.getUserName());
|
||||
jsonObject.put("email", trialOrder.getEmail());
|
||||
if (Objects.nonNull(link)) {
|
||||
if (link) {
|
||||
jsonObject.put("days", 14);
|
||||
} else {
|
||||
jsonObject.put("days", 5);
|
||||
}
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
private final static String TRIAL_ORDER_LIST_ID = "122273_trailOrderData.html";
|
||||
public void sendExcelEmail(List<String> receiverAddress, String fileName, InputStreamSource inputStreamSource) {
|
||||
// 根据邮件类型设置不同的主题和模板
|
||||
String subject = "昨日试用订单数据";
|
||||
// 发送邮件
|
||||
sendEmail(receiverAddress, null, TRIAL_ORDER_LIST_ID, subject, fileName, inputStreamSource);
|
||||
}
|
||||
|
||||
private final static String NO_TRIAL_ORDER_LIST_ID = "122591_noTrailOrderTemplate.html";
|
||||
public void sendNoExcelEmail(List<String> receiverAddress) {
|
||||
// 根据邮件类型设置不同的主题和模板
|
||||
String subject = "昨日试用订单数据";
|
||||
// 发送邮件
|
||||
sendEmail(receiverAddress, null, NO_TRIAL_ORDER_LIST_ID, subject, null, null);
|
||||
}
|
||||
|
||||
private final static String WILLBEEXPIRED_TEMPLATE_ID = "118178_willBeExpiredNotification.html";
|
||||
public void sendWillBeExpiredEmail(Account account) {
|
||||
// 根据邮件类型设置不同的主题和模板
|
||||
String subject = "Renewal notice";
|
||||
// 发送邮件
|
||||
sendEmail(Collections.singletonList(account.getUserEmail()), buildAccountData(account), WILLBEEXPIRED_TEMPLATE_ID, subject, null, null);
|
||||
}
|
||||
|
||||
private static JSONObject buildAccountData(Account account) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
// 设置试用订单相关数据
|
||||
jsonObject.put("userName", account.getUserName());
|
||||
|
||||
// 用户到期时间戳
|
||||
Long timestamp = account.getValidEndTime(); // 替换为你的时间戳
|
||||
if (null != timestamp) {
|
||||
// 获取当前时间戳
|
||||
Long currentTimestamp = System.currentTimeMillis();
|
||||
// 计算时间差(毫秒)
|
||||
long timeDifference = currentTimestamp - timestamp;
|
||||
// 向上取整计算天数
|
||||
long days = (timeDifference + 24 * 60 * 60 * 1000 - 1) / (24 * 60 * 60 * 1000);
|
||||
jsonObject.put("days", days);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
private final static String UPGRADE_SUCCESS_NOTIFICATION_ID = "118856_AiDA发版完成通知英文版.html";
|
||||
private final static String UPGRADE_SUCCESS_NOTIFICATION_ID_CHINESE = "122899_AiDA发版完成通知中文版.html";
|
||||
|
||||
// todo 将这里的发件人信息包装为枚举类,枚举类中包含发件邮箱的服务地址,密码,发件人邮箱
|
||||
public void sendUpgradeNotification(Account account, String senderAddress, Integer type) {
|
||||
try {
|
||||
// 根据邮件类型设置不同的主题和模板
|
||||
String subject = "";
|
||||
String templateId = "";
|
||||
|
||||
if (type == 1) {
|
||||
subject = "Successful System Upgrade and New Features in AiDA 3.0";
|
||||
templateId = UPGRADE_SUCCESS_NOTIFICATION_ID;
|
||||
}else {
|
||||
subject = "系统升级成功和AiDA 3.0新功能";
|
||||
templateId = UPGRADE_SUCCESS_NOTIFICATION_ID_CHINESE;
|
||||
}
|
||||
|
||||
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
|
||||
basicEmailParamDTO.setServiceAddress("mail.code-create.com.hk.");
|
||||
basicEmailParamDTO.setSenderUserMail("info@code-create.com.hk");
|
||||
basicEmailParamDTO.setSenderUser("info@code-create.com.hk");
|
||||
basicEmailParamDTO.setPassword("???");
|
||||
basicEmailParamDTO.setSubject(subject);
|
||||
basicEmailParamDTO.setMailTo(mailUtil.getInternetAddressList(Collections.singletonList(account.getUserEmail())));
|
||||
|
||||
// 发送邮件
|
||||
sendEmail(buildAccountData(account), basicEmailParamDTO, templateId, null, null);
|
||||
|
||||
} catch (AddressException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final static String NEW_USER_PAYMENT_NOTIFICATION_EN = "124889_new_user_payment_notification_en.html";
|
||||
private final static String NEW_USER_PAYMENT_NOTIFICATION_CN = "124888_new_user_payment_notification_cn.html";
|
||||
private final static String RENEWAL_NOTIFICATION_FOR_OLD_USER_EN = "124892_renewal_notification_for_old_user_en.html";
|
||||
private final static String RENEWAL_NOTIFICATION_FOR_OLD_USER_CN = "124891_renewal_notification_for_old_user_cn.html";
|
||||
|
||||
public void notificationForPaidUser(String receiverAddress, int emailType, String country, String userName, String date) {
|
||||
// 根据邮件类型设置不同的主题和模板
|
||||
String subject = "";
|
||||
String templateId = "";
|
||||
JSONObject parameter = new JSONObject();
|
||||
switch (emailType) {
|
||||
// 新用户
|
||||
case 1:
|
||||
subject = "Welcome to AiDA!";
|
||||
if (country.equals("China")) {
|
||||
templateId = NEW_USER_PAYMENT_NOTIFICATION_CN;
|
||||
} else {
|
||||
templateId = NEW_USER_PAYMENT_NOTIFICATION_EN;
|
||||
}
|
||||
parameter.put("userName", userName);
|
||||
parameter.put("email", receiverAddress);
|
||||
break;
|
||||
// 续费用户
|
||||
case 2:
|
||||
subject = "Account renewal notification";
|
||||
if (country.equals("China")) {
|
||||
templateId = RENEWAL_NOTIFICATION_FOR_OLD_USER_CN;
|
||||
} else {
|
||||
templateId = RENEWAL_NOTIFICATION_FOR_OLD_USER_EN;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
parameter.put("userName", userName);
|
||||
parameter.put("date", date);
|
||||
// 发送邮件
|
||||
sendEmail(Collections.singletonList(receiverAddress), parameter, templateId, subject, null, null);
|
||||
}
|
||||
|
||||
private final static String PORTFOLIO_REGISTER_ID = "124847_portfolio-account-register.html";
|
||||
public Boolean designWorksRegister(String userEmail, String randomVerifyCode) {
|
||||
String subject = "Tourist registration";
|
||||
sendEmail(Collections.singletonList(userEmail), contractTemplate(PORTFOLIO_REGISTER_ID, randomVerifyCode, null), PORTFOLIO_REGISTER_ID, subject, null, null);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
private final static String UPLOAD_TIMEOUT_REMINDER = "128324_upload_timeout_reminder.html";
|
||||
public void uploadTimeoutReminder(String userName, String time) {
|
||||
String xp = "xupei3360@163.com";
|
||||
String shb = "shahaibodd99@gmail.com";
|
||||
String wxd = "X1627315083@163.com";
|
||||
String pkc = "kaicpang.pang@connect.polyu.hk";
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("username", userName);
|
||||
param.put("time", time);
|
||||
|
||||
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
||||
sendEmail(Arrays.asList(shb, xp, wxd, pkc), param, UPLOAD_TIMEOUT_REMINDER, "上传图片超时提醒", null, null);
|
||||
}
|
||||
|
||||
private final static String CANCEL_MERCHANT_EN = "130720_cancel-merchant-en.html";
|
||||
private final static String NEW_MERCHANT_EN = "135190_new-merchant-en-updated01.html";
|
||||
private final static String NEW_USER_EN = "135189_new-user-en-updated01.html";
|
||||
private final static String NEW_USER_CN = "135186_new-user-cn-updated01.html";
|
||||
private final static String RENEWAL_MERCHANT_EN = "130724_renewal-merchant-en.html";
|
||||
private final static String RENEWAL_USER_EN = "130725_renewal-user-en.html";
|
||||
private final static String RENEWAL_USER_CN = "130726_renewal-user-cn.html";
|
||||
private final static String RENEWAL_REMINDER_USER_EN = "130727_renewal-reminder-user-en.html";
|
||||
private final static String RENEWAL_REMINDER_USER_CN = "130728_renewal-reminder-user-cn.html";
|
||||
private final static String PAYMENT_FAILED_NEW_MERCHANT_EN = "131230_payment_failed_new_merchant_en.html";
|
||||
private final static String PAYMENT_FAILED_RENEWAL_MERCHANT_EN = "131225_payment_failed_renewal_merchant_en.html";
|
||||
private final static String PAYMENT_FAILED_RENEWAL_USER_EN = "131563_payment_failed_renewal_user_en.html";
|
||||
private final static String PAYMENT_FAILED_RENEWAL_USER_CN = "131564_payment_failed_renewal_user_cn.html";
|
||||
|
||||
public boolean subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress) {
|
||||
try {
|
||||
String merchantEmail = "kimwong@code-create.com.hk";
|
||||
String developer = "xupei3360@163.com";
|
||||
List<String> merchantReceiver = Arrays.asList(/*merchantEmail, */developer);
|
||||
|
||||
String merchantSubject = null;
|
||||
String merchantTemplate = null;
|
||||
String userSubject = null;
|
||||
String userTemplate = null;
|
||||
switch (type) {
|
||||
case "cancel":
|
||||
merchantSubject = "[Code-Create] Subscription Cancelled";
|
||||
merchantTemplate = CANCEL_MERCHANT_EN;
|
||||
break;
|
||||
case "fail_new":
|
||||
merchantSubject = "[Code-Create] Payment Failed : New Order (" + subscriptionEmailParamsDTO.getOrderId() + ")";
|
||||
merchantTemplate = PAYMENT_FAILED_NEW_MERCHANT_EN;
|
||||
break;
|
||||
case "fail_renewal":
|
||||
merchantSubject = "[Code-Create] Payment Failed : Renewal Order (" + subscriptionEmailParamsDTO.getOrderId() + ")";
|
||||
merchantTemplate = PAYMENT_FAILED_RENEWAL_MERCHANT_EN;
|
||||
if (language.equals("ENGLISH")) {
|
||||
userSubject = "[Code-Create] Payment Failed : Renewal Order (" + subscriptionEmailParamsDTO.getOrderId() + ")";
|
||||
userTemplate = PAYMENT_FAILED_RENEWAL_USER_EN;
|
||||
} else {
|
||||
userSubject = "[Code-Create] 自动续费失败 (" + subscriptionEmailParamsDTO.getOrderId() + ")";
|
||||
userTemplate = PAYMENT_FAILED_RENEWAL_USER_CN;
|
||||
}
|
||||
break;
|
||||
case "new":
|
||||
merchantSubject = "[Code-Create] New Order(" + subscriptionEmailParamsDTO.getOrderId() + ")";
|
||||
merchantTemplate = NEW_MERCHANT_EN;
|
||||
if (language.equals("ENGLISH")) {
|
||||
userSubject = "[Code-Create] You have successfully subscribed to AiDA";
|
||||
userTemplate = NEW_USER_EN;
|
||||
} else {
|
||||
userSubject = "[Code-Create] 您已成功订阅AiDA";
|
||||
userTemplate = NEW_USER_CN;
|
||||
}
|
||||
break;
|
||||
case "renewal":
|
||||
merchantSubject = "[Code-Create] New subscription renewal order (" + subscriptionEmailParamsDTO.getOrderId() + ")";
|
||||
merchantTemplate = RENEWAL_MERCHANT_EN;
|
||||
if (language.equals("ENGLISH")) {
|
||||
userSubject = "[Code-Create] AiDA Renewal Successful";
|
||||
userTemplate = RENEWAL_USER_EN;
|
||||
} else {
|
||||
userSubject = "[Code-Create] AiDA续订成功";
|
||||
userTemplate = RENEWAL_USER_CN;
|
||||
}
|
||||
break;
|
||||
case "reminder":
|
||||
if (language.equals("ENGLISH")) {
|
||||
userSubject = "[Code-Create] AiDA Subscription Renewal Reminder";
|
||||
userTemplate = RENEWAL_REMINDER_USER_EN;
|
||||
} else {
|
||||
userSubject = "[Code-Create] AiDA续订提醒";
|
||||
userTemplate = RENEWAL_REMINDER_USER_CN;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log.error("unknown subscription email type");
|
||||
return false;
|
||||
}
|
||||
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(subscriptionEmailParamsDTO));
|
||||
|
||||
// 排除不向用户发送邮件的情况
|
||||
if (!type.equals("cancel") && !type.equals("fail_new")) {
|
||||
sendEmail(Collections.singletonList(receiverAddress), jsonObject, userTemplate, userSubject, null, null);
|
||||
}
|
||||
// 排除不向商家发送邮件的情况
|
||||
if (!type.equals("reminder")) {
|
||||
sendEmail(merchantReceiver, jsonObject, merchantTemplate, merchantSubject, null, null);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("邮件发送失败,{}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private final static String NEW_REGISTRATION = "132123_affiliate_registration_en.html";
|
||||
private final static String AFFILIATE_ACCEPTED = "132124_affiliate_accepted_en.html";
|
||||
private final static String AFFILIATE_REFUSED = "132125_affiliate_refused_en.html";
|
||||
private final static String AFFILIATE_MONTHLY_SUMMARY = "132126_affiliate_monthly_summary_en.html";
|
||||
|
||||
public void affiliateEmailReminder(List<String> receiverAddress, AffiliateEmailParamsDTO paramsDTO, String type) {
|
||||
String subject = "";
|
||||
String templateId = "";
|
||||
switch (type) {
|
||||
case "new":
|
||||
subject = "New Affiliate Registration";
|
||||
templateId = NEW_REGISTRATION;
|
||||
break;
|
||||
case "accepted":
|
||||
subject = "Affiliate Application Accepted";
|
||||
templateId = AFFILIATE_ACCEPTED;
|
||||
break;
|
||||
case "refused":
|
||||
subject = "Affiliate Application Refused";
|
||||
templateId = AFFILIATE_REFUSED;
|
||||
break;
|
||||
case "summary":
|
||||
subject = "Your Monthly AffiliateWP Summary for AiDA";
|
||||
templateId = AFFILIATE_MONTHLY_SUMMARY;
|
||||
break;
|
||||
}
|
||||
|
||||
// 将 DTO 转换为 JSONObject
|
||||
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(paramsDTO);
|
||||
sendEmail(receiverAddress, jsonObject, templateId, subject, null, null);
|
||||
}
|
||||
|
||||
private final static String CREDITS_PURCHASE_MERCHANT = "133275_AiDA 积分购买通知-merchant.html";
|
||||
public void creditsPurchaseReminder(String username, String quantity, String amount) {
|
||||
String merchantEmail = "kimwong@code-create.com.hk";
|
||||
String developerEmail = "xupei@code-create.com.hk";
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
// 设置试用订单相关数据
|
||||
jsonObject.put("username", username);
|
||||
jsonObject.put("quantity", quantity);
|
||||
jsonObject.put("totalFee", amount);
|
||||
|
||||
sendEmail(Arrays.asList(/*merchantEmail,*/developerEmail), jsonObject, CREDITS_PURCHASE_MERCHANT, "New Credit Purchase Order", null, null);
|
||||
}
|
||||
|
||||
private final static String COMMON_EXCEPTION_REMINDER = "135279_common-exception-reminder.html";
|
||||
public void commonExceptionReminder(String functionName, List<String> destination) {
|
||||
// 邮件内容 {{function}}处理异常,请及时查看
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("function", functionName);
|
||||
|
||||
sendEmail(destination, param, COMMON_EXCEPTION_REMINDER, "AiDA发生异常,请及时处理", null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.ai.da.model.vo.*;
|
||||
import com.ai.da.python.PythonService;
|
||||
import com.ai.da.service.*;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
|
||||
@@ -26,14 +28,17 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
import static com.ai.da.common.enums.CollectionLevel1TypeEnum.*;
|
||||
import static com.ai.da.service.impl.UserLikeGroupServiceImpl.convert;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -59,6 +64,8 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
private RedisUtil redisUtil;
|
||||
@Resource
|
||||
private GenerateCancelMapper generateCancelMapper;
|
||||
@Resource
|
||||
private SketchReconstructionMapper sketchReconstructionMapper;
|
||||
|
||||
@Value("${redis.key.orderForGenerate}")
|
||||
private String consumptionOrderKey;
|
||||
@@ -715,6 +722,8 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
String path;
|
||||
if (type.equals("Logo")) {
|
||||
path = CommonConstant.GENERATE_LOGO_SINGLE_CANCEL;
|
||||
} else if(type.equals("PoseTransformation")){
|
||||
path =CommonConstant.POSE_TRANSFORMATION_CANCEL;
|
||||
} else {
|
||||
path = CommonConstant.GENERATE_CANCEL;
|
||||
}
|
||||
@@ -810,7 +819,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO) {
|
||||
public GenerateResultVO imageToSketch(ImageToSketchDTO imageToSketchDTO, String collagePictureUrl, Long projectId) {
|
||||
|
||||
String bucket = userBucket;
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
@@ -823,8 +832,13 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
throw new BusinessException("remaining.credits.insufficient", ResultEnum.PROMPT.getCode());
|
||||
}
|
||||
|
||||
CollectionElement collectionElement = collectionElementService.getById(imageToSketchDTO.getElementId());
|
||||
String imagePath = collectionElement.getUrl();
|
||||
String imagePath;
|
||||
if (StringUtil.isNullOrEmpty(collagePictureUrl)){
|
||||
CollectionElement collectionElement = collectionElementService.getById(imageToSketchDTO.getElementId());
|
||||
imagePath = collectionElement.getUrl();
|
||||
}else {
|
||||
imagePath = collagePictureUrl;
|
||||
}
|
||||
|
||||
log.info(minioUtil.getPreSignedUrl(imagePath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
String imageName = UUID.randomUUID().toString();
|
||||
@@ -852,7 +866,9 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
generate.setElementId(imageToSketchDTO.getElementId());
|
||||
generate.setGenerateType("image");
|
||||
generate.setSketchStyle(styleCode);
|
||||
generate.setStyleImageElementId(imageToSketchDTO.getElementId());
|
||||
generate.setStyleImageElementId(imageToSketchDTO.getStyleImageId());
|
||||
generate.setProjectId(projectId);
|
||||
generate.setInputImageUrl(collagePictureUrl);
|
||||
generate.setCreateDate(new Date());
|
||||
baseMapper.insert(generate);
|
||||
|
||||
@@ -920,4 +936,255 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
|
||||
return new GenerateResultVO(generateDetailId, minioUtil.getPreSignedUrl(minioPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME, true), "Success", category);
|
||||
}
|
||||
|
||||
public String poseTransform(Long projectId, String productImage, int poseId){
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
|
||||
// 1、判断用户当前积分是否够本次生成消耗
|
||||
CreditsEventsEnum creditsEventsEnum = CreditsEventsEnum.POSE_TRANSFORMATION;
|
||||
Boolean preDeduction = creditsService.creditsPreDeduction(creditsEventsEnum, 1);
|
||||
if (!preDeduction) {
|
||||
throw new BusinessException("remaining.credits.insufficient", ResultEnum.WARNING.getCode());
|
||||
}
|
||||
|
||||
// 3、生成唯一id 使用uuid,由于uuid重复的几率很小,故取消对uuid重复性的校验
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
String taskId = uuid + "-" + accountId;
|
||||
|
||||
PoseTransformation poseTransformation = new PoseTransformation();
|
||||
poseTransformation.setProjectId(projectId);
|
||||
poseTransformation.setAccountId(accountId);
|
||||
poseTransformation.setUniqueId(taskId);
|
||||
poseTransformation.setProductImage(productImage);
|
||||
poseTransformation.setPoseId(poseId);
|
||||
poseTransformation.setCreateTime(LocalDateTime.now());
|
||||
poseTransformationMapper.insert(poseTransformation);
|
||||
|
||||
Boolean b = pythonService.poseTransformation(productImage, poseId, taskId);
|
||||
if (b){
|
||||
// 6、添加预扣除积分到redis
|
||||
creditsService.addRecordToCreditsDeduction(accountId, uuid, creditsEventsEnum);
|
||||
// 6.1 添加积分扣除记录到db
|
||||
creditsService.preInsert(accountId, creditsEventsEnum.getName(), uuid, Boolean.TRUE, null);
|
||||
return taskId;
|
||||
}
|
||||
throw new BusinessException("pose transformation error", ResultEnum.ERROR.getCode());
|
||||
}
|
||||
|
||||
@Resource
|
||||
private PoseTransformationMapper poseTransformationMapper;
|
||||
|
||||
public void processPoseTransformResult(String taskId, String gifUrl, String videoUrl, String imageUrl){
|
||||
// 1、存储模型返回的数据
|
||||
PoseTransformation poseTransformation;
|
||||
QueryWrapper<PoseTransformation> qw = new QueryWrapper<>();
|
||||
qw.eq("unique_id", taskId);
|
||||
List<PoseTransformation> poseTransformations = poseTransformationMapper.selectList(qw);
|
||||
if (poseTransformations != null && poseTransformations.size() > 1){
|
||||
log.warn("通过taskId {} 查询到的PoseTransformation的结果不止一条", taskId);
|
||||
}else if (poseTransformations == null || poseTransformations.isEmpty()){
|
||||
return ;
|
||||
}
|
||||
poseTransformation = poseTransformations.get(0);
|
||||
poseTransformation.setGifUrl(gifUrl);
|
||||
poseTransformation.setVideoUrl(videoUrl);
|
||||
poseTransformation.setImageUrl(imageUrl);
|
||||
poseTransformation.setUpdateTime(LocalDateTime.now());
|
||||
poseTransformationMapper.updateById(poseTransformation);
|
||||
|
||||
String key = generateResultKey + ":" + taskId;
|
||||
PoseTransformationVO poseTransformationVO = new PoseTransformationVO(
|
||||
poseTransformation.getId(), taskId, gifUrl, videoUrl, imageUrl, (byte) 0, "Success");
|
||||
|
||||
// 2、更新redis
|
||||
redisUtil.addToString(key, new Gson().toJson(poseTransformationVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
|
||||
|
||||
// 3、执行积分扣除
|
||||
String accountId = taskId.substring(taskId.lastIndexOf("-") + 1);
|
||||
String uuid = taskId.substring(0, taskId.lastIndexOf("-"));
|
||||
Boolean flag = creditsService.taskCreditsDeduction(Long.parseLong(accountId), uuid);
|
||||
if (flag) creditsService.updateChangedCredits(accountId, uuid);
|
||||
}
|
||||
|
||||
public PoseTransformationVO getPoseTransformationResult(String taskId){
|
||||
String key = generateResultKey + ":" + taskId;
|
||||
String resultJson = redisUtil.getFromString(key);
|
||||
|
||||
if (!StringUtil.isNullOrEmpty(resultJson)){
|
||||
PoseTransformationVO poseTransformationVO = new Gson().fromJson(redisUtil.getFromString(key), PoseTransformationVO.class);
|
||||
if (poseTransformationVO.getStatus().equals("Success")){
|
||||
poseTransformationVO.setGifUrl(minioUtil.getPreSignedUrl(poseTransformationVO.getGifUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
poseTransformationVO.setVideoUrl(minioUtil.getPreSignedUrl(poseTransformationVO.getVideoUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
poseTransformationVO.setImageUrl(minioUtil.getPreSignedUrl(poseTransformationVO.getImageUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
}
|
||||
return poseTransformationVO;
|
||||
}else {
|
||||
return new PoseTransformationVO();
|
||||
}
|
||||
}
|
||||
|
||||
@Resource
|
||||
private SysFileService sysFileService;
|
||||
|
||||
@Resource
|
||||
private LibraryModelPointService libraryModelPointService;
|
||||
public String modifyModelProportion(ModifyModelProportionDTO proportionDTO){
|
||||
log.info("modifyModelProportion params: {}", proportionDTO);
|
||||
String name;
|
||||
String gender;
|
||||
Library model = null;
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
// 所有修改的图片都另存为,不覆盖原图
|
||||
if (proportionDTO.getType().equals("Library")){
|
||||
model = libraryService.getById(proportionDTO.getId());
|
||||
String url = model.getUrl();
|
||||
name = url.substring(url.indexOf("/") + 1, url.lastIndexOf("/")) + "/" + uuid;
|
||||
gender = model.getLevel2Type();
|
||||
}else {
|
||||
SysFileVO sysModel = sysFileService.getById(proportionDTO.getId());
|
||||
gender = sysModel.getLevel2Type();
|
||||
name = accountId + "/models/" + gender.toLowerCase() + "/" + uuid;
|
||||
}
|
||||
// 只需要将结果存入library
|
||||
String modifiedModel = pythonService.modifyModelProportion(proportionDTO.getModelPath(), proportionDTO.getStretch(), name, proportionDTO.getTop(), proportionDTO.getBottom());
|
||||
List<Integer> imagesWidthAndHeight = minioUtil.getImagesWidthAndHeight(modifiedModel);
|
||||
|
||||
// 存储修改后的模特到个人library
|
||||
model = new Library();
|
||||
model.setAccountId(accountId);
|
||||
model.setLevel1Type(LibraryLevel1TypeEnum.MODELS.getRealName());
|
||||
model.setLevel2Type(gender);
|
||||
model.setName(uuid);
|
||||
model.setUrl(modifiedModel);
|
||||
model.setMd5(MD5Utils.encryptFile(minioUtil.getPreSignedUrl(modifiedModel, 24 * 60),false));
|
||||
model.setWidth(imagesWidthAndHeight.get(0));
|
||||
model.setHigh(imagesWidthAndHeight.get(1));
|
||||
model.setCreateDate(new Date());
|
||||
libraryService.save(model);
|
||||
|
||||
// 新建模特点位信息
|
||||
LibraryModelPoint libraryModelPoint = new LibraryModelPoint();
|
||||
libraryModelPoint.setModelType("Library");
|
||||
libraryModelPoint.setRelationId(model.getId());
|
||||
libraryModelPoint.setShoulderLeft(Arrays.toString(proportionDTO.getShoulderLeft()));
|
||||
libraryModelPoint.setShoulderRight(Arrays.toString(proportionDTO.getShoulderRight()));
|
||||
libraryModelPoint.setWaistbandLeft(Arrays.toString(proportionDTO.getWaistbandLeft()));
|
||||
libraryModelPoint.setWaistbandRight(Arrays.toString(proportionDTO.getWaistbandRight()));
|
||||
libraryModelPoint.setHandLeft(Arrays.toString(proportionDTO.getHandLeft()));
|
||||
libraryModelPoint.setHandRight(Arrays.toString(proportionDTO.getHandRight()));
|
||||
libraryModelPoint.setCreateDate(new Date());
|
||||
libraryModelPointService.save(libraryModelPoint);
|
||||
return minioUtil.getPreSignedUrl(modifiedModel, CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* String collagePicture(Base64)
|
||||
* List<DTO(id, type)> elements
|
||||
* File file
|
||||
* @return
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public GenerateResultVO sketchReconstructionGenerate(SketchReconstructionDTO sketchReconstructionDTO){
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 1、线稿生成
|
||||
String collagePictureBase64 = sketchReconstructionDTO.getCollagePicture();
|
||||
String path = accountId + "/CollagePicture/" + UUID.randomUUID();
|
||||
String minioPath = minioUtil.base64UploadToPath(collagePictureBase64, userBucket, path);
|
||||
|
||||
Long projectId = sketchReconstructionDTO.getProjectId();
|
||||
|
||||
GenerateResultVO generateResultVO = imageToSketch(new ImageToSketchDTO(null, "2", sketchReconstructionDTO.getGender()), minioPath, projectId);
|
||||
QueryWrapper<SketchReconstruction> qw = new QueryWrapper<>();
|
||||
qw.eq("project_id", projectId);
|
||||
SketchReconstruction sketchReconstruction = sketchReconstructionMapper.selectOne(qw);
|
||||
|
||||
String url = generateResultVO.getUrl();
|
||||
// 找到路径的起始位置(从"://"之后查找第一个"/")
|
||||
int pathStartIndex = url.indexOf("/", url.indexOf("://") + 3);
|
||||
// 找到查询参数的起始位置("?" 的位置)
|
||||
int queryStartIndex = url.indexOf("?");
|
||||
// 截取目标部分
|
||||
String targetPath = url.substring(pathStartIndex + 1, queryStartIndex);
|
||||
|
||||
if (Objects.isNull(sketchReconstruction)){
|
||||
sketchReconstruction = new SketchReconstruction();
|
||||
sketchReconstruction.setProjectId(projectId);
|
||||
sketchReconstruction.setCollageImgSketchUrl(targetPath);
|
||||
sketchReconstruction.setGenerateDetailId(generateResultVO.getId());
|
||||
sketchReconstruction.setCreateTime(LocalDateTime.now());
|
||||
sketchReconstructionMapper.insert(sketchReconstruction);
|
||||
}else {
|
||||
sketchReconstruction.setCollageImgSketchUrl(targetPath);
|
||||
sketchReconstruction.setGenerateDetailId(generateResultVO.getId());
|
||||
sketchReconstructionMapper.updateById(sketchReconstruction);
|
||||
}
|
||||
|
||||
return generateResultVO;
|
||||
}
|
||||
|
||||
public String sketchReconstructionSave(MultipartFile multipartFile, Long projectId){
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
// 元素都在画布上,不用额外保存
|
||||
String object = accountId + "/CollageSketchFile/" + projectId;
|
||||
String canvasFilePath = minioUtil.upload("aida-users", object, multipartFile,null);
|
||||
|
||||
// 将画布文件上传到minio,地址保存到project表中
|
||||
QueryWrapper<SketchReconstruction> qw = new QueryWrapper<>();
|
||||
qw.eq("project_id", projectId).isNotNull("canvas_url").orderByDesc("id");
|
||||
SketchReconstruction sketchReconstruction = sketchReconstructionMapper.selectOne(qw);
|
||||
if (Objects.isNull(sketchReconstruction)){
|
||||
sketchReconstruction = new SketchReconstruction();
|
||||
sketchReconstruction.setProjectId(projectId);
|
||||
sketchReconstruction.setCanvasUrl(canvasFilePath);
|
||||
sketchReconstruction.setCreateTime(LocalDateTime.now());
|
||||
sketchReconstructionMapper.insert(sketchReconstruction);
|
||||
}else if (StringUtil.isNullOrEmpty(sketchReconstruction.getCanvasUrl())){
|
||||
sketchReconstruction.setCanvasUrl(canvasFilePath);
|
||||
sketchReconstructionMapper.updateById(sketchReconstruction);
|
||||
}
|
||||
|
||||
// 需要返回哪些信息呢?
|
||||
return null;
|
||||
}
|
||||
|
||||
public SketchReconstructionVO getSketchReconstruction(Long projectId){
|
||||
QueryWrapper<SketchReconstruction> qw = new QueryWrapper<>();
|
||||
qw.eq("project_id", projectId);
|
||||
SketchReconstruction sketchReconstruction = sketchReconstructionMapper.selectOne(qw);
|
||||
if (Objects.isNull(sketchReconstruction) || StringUtil.isNullOrEmpty(sketchReconstruction.getCanvasUrl())){
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream download = minioUtil.download(sketchReconstruction.getCanvasUrl());
|
||||
String convert = convert(download);
|
||||
JSONObject jsonObject = JSONObject.parseObject(convert);
|
||||
JSONArray objects = jsonObject.getJSONArray("objects");
|
||||
for (int i = 0; i < objects.size(); i++) {
|
||||
JSONObject jsonObject1 = objects.getJSONObject(i);
|
||||
String type = jsonObject1.getString("type");
|
||||
if (type.equals("image")) {
|
||||
String minioUrl = jsonObject1.getString("minioUrl");
|
||||
jsonObject1.put("src", minioUtil.getPreSignedUrl(minioUrl, 24 * 60));
|
||||
}
|
||||
objects.set(i, jsonObject1);
|
||||
}
|
||||
jsonObject.put("objects", objects);
|
||||
log.info(String.valueOf(jsonObject));
|
||||
|
||||
// 除返回jsonObject之外,还要返回最后一次生成的线稿图以及like状态
|
||||
SketchReconstructionVO vo = new SketchReconstructionVO();
|
||||
vo.setCanvasFile(jsonObject);
|
||||
if (Objects.nonNull(sketchReconstruction.getGenerateDetailId())){
|
||||
GenerateDetail generateDetail = generateDetailMapper.selectById(sketchReconstruction.getGenerateDetailId());
|
||||
vo.setCollageSketchUrl(minioUtil.getPreSignedUrl(generateDetail.getUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
vo.setLiked(generateDetail.getIsLike().equals((byte)1));
|
||||
}
|
||||
return vo;
|
||||
}catch (Exception e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ rabbitmq.queues.srResult=SuperResolution-dev
|
||||
rabbitmq.queues.generateResult=GenerateImage-dev
|
||||
rabbitmq.queues.toProductImageResult=ToProductImage-dev
|
||||
rabbitmq.queues.relightResult=Relight-dev
|
||||
rabbitmq.queues.poseTransform=PoseTransform-dev
|
||||
rabbitmq.exchange.generate=generate-exchange
|
||||
|
||||
orderList.link=https://develop.aida.com.hk/home/homePage?order=
|
||||
|
||||
@@ -107,6 +107,7 @@ rabbitmq.queues.srResult=SuperResolution-prod
|
||||
rabbitmq.queues.generateResult=GenerateImage-prod
|
||||
rabbitmq.queues.toProductImageResult=ToProductImage-prod
|
||||
rabbitmq.queues.relightResult=Relight-prod
|
||||
rabbitmq.queues.poseTransform=PoseTransform-prod
|
||||
rabbitmq.exchange.generate=generate-exchange
|
||||
|
||||
orderList.link=https://aida.com.hk/home/homePage?order=
|
||||
|
||||
Reference in New Issue
Block a user