82 Commits

Author SHA1 Message Date
9bd10581f4 BUGFIX:获取relight结果时删除了排序记录 2026-04-10 23:03:15 +08:00
5d3692a204 BUGFIX:支付失败后的邮件通知类型错误(临时处理) 2026-04-08 13:52:38 +08:00
litianxiang
1da6b7728c Merge remote-tracking branch 'origin/dev/3.1_release_merge' into release/3.1 2026-03-30 17:05:43 +08:00
litianxiang
0faf77899b fix:PRINTBOARD_HIGH_I2I与PRINTBOARD_ADVANCED_I2I使用模型一致导致积分扣除错误 2026-03-27 16:49:10 +08:00
litianxiang
e4940019bf 框选适配py 2026-03-27 15:19:38 +08:00
litianxiang
0da66ff210 print t2i模型替换 2026-03-27 15:16:33 +08:00
litianxiang
5dd862ff79 MOOD_BOARD high 去掉翻译 2026-03-26 16:13:43 +08:00
litianxiang
edaec9884d TO PROD 2026-03-25 22:28:44 +08:00
litianxiang
76eeb2be53 moodboard基础模型修改 2026-03-25 10:39:22 +08:00
litianxiang
cb6f94d2d4 py api fix 2026-03-25 10:19:06 +08:00
litianxiang
28656c44c8 FIX FLUX2 2026-03-24 16:24:43 +08:00
litianxiang
6757a89d04 Pattern模式参数fix 2026-03-24 15:54:53 +08:00
litianxiang
9be1a1e307 加锁解决不同线程读取前还未保存的问题 2026-03-24 15:49:16 +08:00
litianxiang
2168978f61 print pattern也改为flux2 2026-03-24 15:32:06 +08:00
litianxiang
54466b935d debug 2026-03-24 15:23:33 +08:00
litianxiang
c970ebe691 debug 2026-03-24 15:15:59 +08:00
litianxiang
1c5a3a12b9 debug 2026-03-24 15:04:40 +08:00
litianxiang
6e06000083 debug 2026-03-24 14:46:01 +08:00
litianxiang
dea2b3be42 debug 2026-03-24 14:29:08 +08:00
litianxiang
bcf51aea23 debug 2026-03-24 14:20:39 +08:00
litianxiang
0c9d5404c6 flux2失败状态判断 2026-03-24 14:05:27 +08:00
litianxiang
93429839c0 本地flux改为flux2 2026-03-24 13:39:38 +08:00
litianxiang
27859c3e28 Merge remote-tracking branch 'origin/release/3.1' into dev/3.1_release_merge 2026-03-23 14:11:33 +08:00
litianxiang
f02c0930a6 日志切面(controller层报错打印) 2026-03-23 13:56:47 +08:00
litianxiang
d57bb83b25 Merge remote-tracking branch 'origin/release/3.1' into release/3.1 2026-03-23 13:50:44 +08:00
731e34f133 TO DEV 2026-03-23 13:38:10 +08:00
75eca8d6ba Merge branch 'release/3.1' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/python/PythonService.java
2026-03-23 13:22:18 +08:00
3e53401f76 TASK:返回符合查询条件的金额总计 2026-03-23 11:55:07 +08:00
litianxiang
b6a068ebcd SKETCHBOARD传入的text改为获取第一个,为分割获取style的方式 2026-03-23 11:50:24 +08:00
litianxiang
dc291ea086 加入非空校验 2026-03-14 01:50:39 +08:00
litianxiang
2e846e671a romantic风格缺少下装fix 2026-03-13 10:06:26 +08:00
litianxiang
a5093311f9 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 19:06:54 +08:00
litianxiang
aed338a6d7 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:59:17 +08:00
litianxiang
8bdb49d25c 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:49:57 +08:00
litianxiang
5d53a8cd42 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:49:28 +08:00
litianxiang
61b7f3072f 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:36:21 +08:00
litianxiang
a1f489f3a1 比赛url修改 2026-03-12 17:39:05 +08:00
litianxiang
fc3fd877a8 transpose和rotate获取位置修改 2026-03-05 16:58:17 +08:00
litianxiang
fc72d2c430 transpose和rotate获取位置修改 2026-03-05 13:29:14 +08:00
litianxiang
1ac01dd090 测试token恢复 2026-02-25 16:36:06 +08:00
litianxiang
3bbdf7c672 fix:按编号导出参赛选手文件 2026-02-09 10:33:25 +08:00
litianxiang
0646484fba 按编号导出参赛选手文件 2026-02-09 10:21:40 +08:00
litianxiang
96b8613741 映射temp到服务器 2026-02-06 17:29:42 +08:00
litianxiang
cf30226a51 映射temp到服务器 2026-02-06 17:24:43 +08:00
litianxiang
3c15a3ff68 映射temp到服务器 2026-02-06 17:21:07 +08:00
litianxiang
0c904be227 测试临时token 2026-02-06 11:42:34 +08:00
litianxiang
7759b56123 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-02-05 17:39:15 +08:00
litianxiang
d5bfaa8822 fix:允许图生图不带提示词 2026-02-05 17:38:38 +08:00
967c0cbc01 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-02-05 16:55:24 +08:00
417e34b41a BUGFIX:1.首次design没有使用library和生成的印花2.design overall印花太小 2026-02-05 16:54:45 +08:00
litianxiang
d51aa84647 fix:参赛者根据链接返回文件参数 2026-02-05 09:41:10 +08:00
litianxiang
5895bc6ab6 Revert "fix:参赛者根据链接返回文件参数"
This reverts commit 3301869f20.
2026-02-05 09:40:35 +08:00
litianxiang
3301869f20 fix:参赛者根据链接返回文件参数 2026-02-05 09:40:15 +08:00
litianxiang
1ec42f4ad5 fix:参赛者id逻辑更改 2026-02-04 17:20:22 +08:00
cc506ff7e9 Merge branch 'dev/3.1_release_merge' into release/3.1 2026-02-04 17:05:59 +08:00
litianxiang
f2d43f06f4 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-02-04 15:28:08 +08:00
litianxiang
9251df49f8 比赛新增文件大小和视频时长 2026-02-04 15:27:51 +08:00
430156f4e8 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-02-04 14:48:38 +08:00
litianxiang
d1123aedcc fix:导出为页面下载 2026-02-04 14:45:11 +08:00
8c007077a3 BUGFIX: detail中的merge模式下没有存储partialDesign的图片 2026-02-04 14:43:29 +08:00
litianxiang
d63b4b4e63 fix:参赛选手加入编号 2026-02-04 14:03:30 +08:00
litianxiang
b826f0bf39 参赛选手加入编号,增加导出功能 2026-02-04 13:41:16 +08:00
litianxiang
1decd8e258 参赛选手加入编号,增加导出功能 2026-02-04 13:41:09 +08:00
litianxiang
1286e84488 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx 2026-02-04 13:21:19 +08:00
a252fdf7f9 BUGFIX: detail中的default模式报错 2026-02-03 16:56:15 +08:00
807d802178 TASK:motion 参数数据类型变更 2026-02-02 15:30:04 +08:00
53f1b548be CONFIG 2026-02-02 15:28:54 +08:00
45dd78032a BUGFIX: 1.token过期,重新登录无法解决 2.motion生成参数数据类型变更 2026-02-02 15:04:27 +08:00
c160da5132 BUGFIX: token过期,重新登录无法解决 2026-02-02 14:57:32 +08:00
b23faeeee2 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-02-02 13:32:55 +08:00
67789abca4 TASK:getAllPose id的数据类型改为整型 2026-02-02 13:32:27 +08:00
1c78d66aab Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-30 17:14:50 +08:00
528bc69923 BUGFIX: design single merge模式下取消传递print及elements等元素 2026-01-30 17:10:37 +08:00
litianxiang
22880d128d Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx 2026-01-30 15:40:25 +08:00
9c56a102cc Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-29 14:38:20 +08:00
2f59fe074f BUGFIX: 管理员修改用户身份为游客 2026-01-29 14:37:54 +08:00
9c61b1c8fe Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-29 10:12:47 +08:00
e30fdf7401 BUGFIX:模特上传,事务管理不统一导致library出现孤儿数据 2026-01-29 10:10:21 +08:00
ba2d10afbc paymentMethodConfiguration切换 2026-01-28 15:41:52 +08:00
6146112d04 TO PROD 2026-01-27 16:39:39 +08:00
412550df27 BUGFIX:管理员查design频次与chart中获取到的数量有区别 2026-01-27 14:59:39 +08:00
litianxiang
3e334d7956 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx 2026-01-26 11:16:46 +08:00
43 changed files with 1697 additions and 846 deletions

View File

@@ -99,6 +99,8 @@ jobs:
volumes: volumes:
# 数据挂载 # 数据挂载
- ./log:/log - ./log:/log
- ./temp:/temp
- ./uploads:/temp/uploads
ports: ports:
- '10090:5567' - '10090:5567'
restart: always restart: always

View File

@@ -427,6 +427,11 @@
<artifactId>bcpkix-jdk18on</artifactId> <artifactId>bcpkix-jdk18on</artifactId>
<version>1.78.1</version> <version>1.78.1</version>
</dependency> </dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -28,6 +28,11 @@ public class MQPublisher {
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getSr(), mm); amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getSr(), mm);
} }
public void sendGenerateResultMessage(String mm) {
log.info("send generate result message: {}", mm);
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getGenerateResult(), mm);
}
/** /**
* *
* @param mailParams 含有的字段 * @param mailParams 含有的字段

View File

@@ -0,0 +1,170 @@
package com.ai.da.common.aspect;
import com.ai.da.common.context.UserContext;
import com.ai.da.model.vo.AuthPrincipalVo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
/**
* Controller日志切面
* 记录所有Controller接口的请求参数和用户信息
*/
@Aspect
@Component
public class ControllerLoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(ControllerLoggingAspect.class);
/**
* 定义切点所有Controller方法
*/
@Pointcut("execution(* com.ai.da.controller..*(..))")
public void controllerMethods() {
}
/**
* Controller方法执行前记录日志
*/
// @Before("controllerMethods()")
public void logControllerBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
// 获取当前用户ID
Long userId = null;
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
if (authPrincipalVo != null) {
userId = authPrincipalVo.getId();
}
// 获取请求参数
Map<String, Object> params = getRequestParams(joinPoint, request);
logger.info("=== 请求开始 ===");
logger.info("用户ID: {}", userId);
logger.info("请求URL: {}", request.getRequestURL().toString());
logger.info("请求方法: {}", request.getMethod());
logger.info("请求IP: {}", getClientIpAddress(request));
logger.info("调用方法: {}.{}", joinPoint.getSignature().getDeclaringType().getSimpleName(), joinPoint.getSignature().getName());
logger.info("请求参数: {}", params);
}
}
/**
* 获取请求参数
*/
private Map<String, Object> getRequestParams(JoinPoint joinPoint, HttpServletRequest request) {
Map<String, Object> params = new HashMap<>();
// 1. 获取Query String参数
String queryString = request.getQueryString();
if (queryString != null && !queryString.isEmpty()) {
params.put("queryString", queryString);
}
// 2. 获取方法参数(包含 @PathVariable, @RequestParam, @RequestBody 等)
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
Map<String, Object> methodParams = new HashMap<>();
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
// 过滤掉不可序列化的参数
if (arg != null) {
if (isIgnorable(arg)) {
// 对于可忽略的类型,记录类型名
methodParams.put("arg" + i, "[" + arg.getClass().getSimpleName() + "]");
} else {
try {
methodParams.put("arg" + i, arg);
} catch (Exception e) {
methodParams.put("arg" + i, arg.toString());
}
}
}
}
if (!methodParams.isEmpty()) {
params.put("methodParams", methodParams);
}
}
return params;
}
/**
* 判断是否需要过滤的参数类型
*/
private boolean isIgnorable(Object obj) {
return obj instanceof HttpServletRequest
|| obj instanceof HttpServletResponse
|| obj instanceof MultipartFile
|| obj instanceof MultipartFile[];
}
/**
* Controller方法抛出异常时记录日志
*/
@AfterThrowing(pointcut = "controllerMethods()", throwing = "exception")
public void logControllerAfterThrowing(JoinPoint joinPoint, Throwable exception) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
Long userId = null;
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
if (authPrincipalVo != null) {
userId = authPrincipalVo.getId();
}
// 获取请求参数
Map<String, Object> params = new HashMap<>();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
params = getRequestParams(joinPoint, request);
}
logger.error("=== 请求异常 ===");
logger.error("用户ID: {}", userId);
logger.error("调用方法: {}.{}", joinPoint.getSignature().getDeclaringType().getSimpleName(), joinPoint.getSignature().getName());
logger.error("请求参数: {}", params);
logger.error("异常信息: ", exception);
logger.error("=== 异常结束 ===");
}
/**
* 获取客户端真实IP地址
*/
private String getClientIpAddress(HttpServletRequest request) {
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
return xForwardedFor.split(",")[0];
}
String xRealIp = request.getHeader("X-Real-IP");
if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
return xRealIp;
}
String proxyClientIp = request.getHeader("Proxy-Client-IP");
if (proxyClientIp != null && !proxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(proxyClientIp)) {
return proxyClientIp;
}
String wlProxyClientIp = request.getHeader("WL-Proxy-Client-IP");
if (wlProxyClientIp != null && !wlProxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(wlProxyClientIp)) {
return wlProxyClientIp;
}
return request.getRemoteAddr();
}
}

View File

@@ -202,7 +202,7 @@ public class MyTaskScheduler {
} }
} }
// @Scheduled(cron = "0 0 9 * * ?") @Scheduled(cron = "0 0 9 * * ?")
public void sendTrialOrderExcelToManagements() { public void sendTrialOrderExcelToManagements() {
// 获取前一天日期 // 获取前一天日期
LocalDate yesterday = LocalDate.now().minusDays(1); LocalDate yesterday = LocalDate.now().minusDays(1);

View File

@@ -23,6 +23,7 @@ public class CommonConstant {
} }
public static final String GENERATE_PATH = "/api/generate_image"; public static final String GENERATE_PATH = "/api/generate_image";
public static final String GENERATE_PATH_FLUX2_KLEIN = "/api/generate_image_flux2_klein";
public static final String GENERATE_SINGLE_LOGO = "/api/generate_single_logo"; public static final String GENERATE_SINGLE_LOGO = "/api/generate_single_logo";

View File

@@ -20,7 +20,7 @@ public class ModelConstants {
public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image"; public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image";
public static final String MOODBOARD_ADVANCED = "doubao-seedream-3-0-t2i-250415"; public static final String MOODBOARD_ADVANCED = "doubao-seedream-3-0-t2i-250415";
public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-3-0-t2i-250415"; public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-3-0-t2i-250415";
public static final String PRINTBOARD_HIGH_I2I = "doubao-seededit-3-0-i2i-250628"; public static final String PRINTBOARD_HIGH_I2I = "doubao-seedream-4-0-250828-fast";
public static final String PRINTBOARD_ADVANCED_I2I = "doubao-seedream-4-0-250828"; public static final String PRINTBOARD_ADVANCED_I2I = "doubao-seedream-4-0-250828";
public static final String IMAGEN_MODEL = "imagen-4.0-generate-001"; public static final String IMAGEN_MODEL = "imagen-4.0-generate-001";
public static final String NANO_BANANA = "gemini-2.5-flash-image"; public static final String NANO_BANANA = "gemini-2.5-flash-image";

View File

@@ -63,7 +63,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
//GlobalAwardController //GlobalAwardController
"/api/global-award/uploads/pdf/init", "/api/global-award/uploads/pdf/chunk", "/api/global-award/uploads/pdf/complete", "/api/global-award/uploads/pdf/status", "/api/global-award/uploads/pdf/init", "/api/global-award/uploads/pdf/chunk", "/api/global-award/uploads/pdf/complete", "/api/global-award/uploads/pdf/status",
"/api/global-award/uploads/video/init", "/api/global-award/uploads/video/chunk", "/api/global-award/uploads/video/complete", "/api/global-award/uploads/video/status", "/api/global-award/uploads/video/init", "/api/global-award/uploads/video/chunk", "/api/global-award/uploads/video/complete", "/api/global-award/uploads/video/status",
"/api/global-award/contestants/save", "/api/global-award/contestants/by-email", "/api/global-award/checkEmail", "/api/global-award/checkCode" "/api/global-award/contestants/save", "/api/global-award/contestants/by-email", "/api/global-award/checkEmail", "/api/global-award/checkCode","/api/global-award/contestants/export",
"/api/global-award/contestants/export/files"
); );
@Override @Override

View File

@@ -34,7 +34,7 @@ public class AccountTask {
accountService.refreshCreditsMonthly(); accountService.refreshCreditsMonthly();
} }
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
public void getPaidUser() { public void getPaidUser() {
// 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单 // 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单
accountService.extendValidityForCC(); accountService.extendValidityForCC();

View File

@@ -45,7 +45,7 @@ public class PaymentTask {
@Resource @Resource
private PayPalCheckoutService payPalCheckoutService; private PayPalCheckoutService payPalCheckoutService;
// @Scheduled(cron = "0/30 * * * * ?") @Scheduled(cron = "0/30 * * * * ?")
public void orderConfirmForPaypal() throws SerializeException { public void orderConfirmForPaypal() throws SerializeException {
// log.info("PayPal orderConfirm 被执行......"); // log.info("PayPal orderConfirm 被执行......");
@@ -109,7 +109,7 @@ public class PaymentTask {
affiliateService.syncLinkViewCountToDB(); affiliateService.syncLinkViewCountToDB();
} }
// @Scheduled(cron = "0 0 8 28-31 * ?") @Scheduled(cron = "0 0 8 28-31 * ?")
public void commissionSummaryReminder(){ public void commissionSummaryReminder(){
// 每个月末的最后一天的早上八点执行 // 每个月末的最后一天的早上八点执行
LocalDate today = LocalDate.now(); LocalDate today = LocalDate.now();

View File

@@ -40,7 +40,7 @@ public class SubscriptionReminderTask {
REMINDER_DAYS_CONFIG.put("year", 14); REMINDER_DAYS_CONFIG.put("year", 14);
} }
// @Scheduled(cron = "0 0 9 * * ?") @Scheduled(cron = "0 0 9 * * ?")
public void subscriptionReminder() { public void subscriptionReminder() {
// 获取所有需要通知的订阅 // 获取所有需要通知的订阅
List<SubscriptionInfo> subscriptionInfos = getDueSubscriptions(); List<SubscriptionInfo> subscriptionInfos = getDueSubscriptions();
@@ -97,7 +97,7 @@ public class SubscriptionReminderTask {
return subscriptionInfoMapper.selectList(qw); return subscriptionInfoMapper.selectList(qw);
} }
// @Scheduled(cron = "0 0 9 * * ?") @Scheduled(cron = "0 0 9 * * ?")
public void trialReminder() { public void trialReminder() {
// 今天的 00:00:00 和 23:59:59 // 今天的 00:00:00 和 23:59:59
LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay();

File diff suppressed because it is too large Load Diff

View File

@@ -767,7 +767,7 @@ public class SendEmailUtil {
try { try {
String merchantEmail = "kimwong@code-create.com.hk"; String merchantEmail = "kimwong@code-create.com.hk";
String developer = "xupei3360@163.com"; String developer = "xupei3360@163.com";
String[] receiverEmail = {/*merchantEmail,*/ developer}; String[] receiverEmail = {merchantEmail, developer};
Credential cred = new Credential(SECRET_ID, SECRET_KEy); Credential cred = new Credential(SECRET_ID, SECRET_KEy);
// 实例化一个http选项可选的没有特殊需求可以跳过 // 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile(); HttpProfile httpProfile = new HttpProfile();
@@ -968,7 +968,7 @@ public class SendEmailUtil {
req.setFromEmailAddress(SEND_ADDRESS); req.setFromEmailAddress(SEND_ADDRESS);
String merchantEmail = "kimwong@code-create.com.hk"; String merchantEmail = "kimwong@code-create.com.hk";
String developerEmail = "xupei@code-create.com.hk"; String developerEmail = "xupei@code-create.com.hk";
req.setDestination(new String[]{/*merchantEmail,*/ developerEmail}); req.setDestination(new String[]{merchantEmail, developerEmail});
Template template = new Template(); Template template = new Template();
req.setSubject("New Credit Purchase Order"); req.setSubject("New Credit Purchase Order");
template.setTemplateID(CREDITS_PURCHASE_MERCHANT); template.setTemplateID(CREDITS_PURCHASE_MERCHANT);

View File

@@ -11,6 +11,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -163,6 +164,24 @@ public class GlobalAwardController {
return Response.success(globalAwardService.checkCode(email, code)); return Response.success(globalAwardService.checkCode(email, code));
} }
@GetMapping("/contestants/export")
@ApiOperation(value = "导出参赛者列表为Excel", notes = "导出所有参赛者信息为xlsx并触发下载")
public void exportContestants(HttpServletResponse response) throws Exception {
byte[] data = globalAwardService.exportContestants();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=\"contestants.xlsx\"");
response.setContentLength(data.length);
response.getOutputStream().write(data);
response.getOutputStream().flush();
}
@PostMapping("/contestants/export/files")
@ApiOperation(value = "导出参赛者文件到本地", notes = "根据参赛者编号范围导出PDF和视频文件到本地temp/uploads/contestants目录")
public Response<Integer> exportContestantFiles(@ApiParam(value = "参赛者文件导出请求", required = true) @RequestBody ContestantExportRequest request) throws Exception {
int exportedCount = globalAwardService.exportContestantFiles(request.getMinContestantNumber(), request.getMaxContestantNumber());
return Response.success(exportedCount);
}
} }

View File

@@ -19,7 +19,7 @@ public interface DesignMapper extends CommonMapper<Design> {
Long insertDesign(Design design); Long insertDesign(Design design);
List<UserDesignStatisticDTO> getDesignStatistic(String startTime, String endTime, List<Long> ids, String email, List<UserDesignStatisticDTO> getDesignStatistic(String startTime, String endTime, List<Long> ids, String email,
String role, String organizationName); String role, String organizationName, boolean filterBySecond);
List<Design> selectDeleteList(); List<Design> selectDeleteList();
} }

View File

@@ -26,6 +26,9 @@ public class Contestant {
private String email; private String email;
@TableField("contestant_number")
private Integer contestantNumber;
@TableField("first_name") @TableField("first_name")
private String firstName; private String firstName;
@@ -56,6 +59,15 @@ public class Contestant {
@TableField("video_path") @TableField("video_path")
private String videoPath; private String videoPath;
@TableField("video_duration")
private Integer videoDuration;
@TableField("video_size")
private Long videoSize;
@TableField("pdf_size")
private Long pdfSize;
@TableField("created_at") @TableField("created_at")
private LocalDateTime createdAt; private LocalDateTime createdAt;

View File

@@ -49,6 +49,15 @@ public class ContestantDTO {
@ApiModelProperty(value = "视频文件路径", required = false, example = "contestants/user@example.com/2024/01/video_1234567890.mp4") @ApiModelProperty(value = "视频文件路径", required = false, example = "contestants/user@example.com/2024/01/video_1234567890.mp4")
private String videoPath; private String videoPath;
@ApiModelProperty(value = "视频时长(秒)", required = false, example = "120")
private Integer videoDuration;
@ApiModelProperty(value = "视频大小(字节)", required = false, example = "10485760")
private Long videoSize;
@ApiModelProperty(value = "PDF 文件大小(字节)", required = false, example = "524288")
private Long pdfSize;
// /** // /**
// * 是否确认覆盖已存在记录false 表示发现已有记录时仅返回 existingRecord不覆盖 // * 是否确认覆盖已存在记录false 表示发现已有记录时仅返回 existingRecord不覆盖
@@ -58,6 +67,8 @@ public class ContestantDTO {
@NotBlank @NotBlank
private String secureToken; private String secureToken;
} }

View File

@@ -0,0 +1,19 @@
package com.ai.da.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 参赛者文件导出请求DTO
*/
@Data
@ApiModel(value = "参赛者文件导出请求", description = "用于导出指定范围的参赛者文件")
public class ContestantExportRequest {
@ApiModelProperty(value = "最小参赛者编号", required = true, example = "10000")
private Integer minContestantNumber;
@ApiModelProperty(value = "最大参赛者编号", required = true, example = "10010")
private Integer maxContestantNumber;
}

View File

@@ -0,0 +1,55 @@
package com.ai.da.model.dto;
import lombok.Builder;
import lombok.Data;
import java.util.List;
/**
* 图片处理请求体
*/
@Data
@Builder
public class ImageProcessRequest {
/**
* OSS桶名bucket_name
*/
private String bucket_name;
/**
* OSS对象名object_name
*/
private String object_name;
/**
* 输入图片路径列表input_image_paths
*/
private List<String> input_image_paths;
/**
* 图像宽度width
*/
private Integer width;
/**
* 图像高度height
*/
private Integer height;
/**
* 文本提示prompt
*/
private String prompt;
/**
* 推理步数steps
*/
private Integer steps;
/**
* 引导系数guidance
*/
private Double guidance;
}

View File

@@ -2,8 +2,10 @@ package com.ai.da.python;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.exceptions.ExceptionUtil;
import com.ai.da.common.RabbitMQ.RabbitMQProperties;
import com.ai.da.common.config.FileProperties; import com.ai.da.common.config.FileProperties;
import com.ai.da.common.config.exception.BusinessException; import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.constant.CommonConstant;
import com.ai.da.common.context.UserContext; import com.ai.da.common.context.UserContext;
import com.ai.da.common.enums.*; import com.ai.da.common.enums.*;
import com.ai.da.common.utils.*; import com.ai.da.common.utils.*;
@@ -20,6 +22,7 @@ import com.ai.da.model.vo.*;
import com.ai.da.python.vo.*; import com.ai.da.python.vo.*;
import com.ai.da.service.DesignHistoryService; import com.ai.da.service.DesignHistoryService;
import com.ai.da.service.PythonTAllInfoService; import com.ai.da.service.PythonTAllInfoService;
import com.ai.da.service.RabbitMQService;
import com.ai.da.service.SysFileService; import com.ai.da.service.SysFileService;
import com.alibaba.fastjson.*; import com.alibaba.fastjson.*;
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.serializer.SerializerFeature;
@@ -39,6 +42,7 @@ import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
@@ -68,6 +72,8 @@ public class PythonService {
private String accessPythonPort; private String accessPythonPort;
@Value("${minio.bucketName.gradient}") @Value("${minio.bucketName.gradient}")
private String gradientBucketName; private String gradientBucketName;
@Value("${minio.bucketName.users}")
private String userBucketName;
@Value("${access.python.generate_sr_port}") @Value("${access.python.generate_sr_port}")
private String srServicePort; private String srServicePort;
@@ -83,6 +89,12 @@ public class PythonService {
@Resource @Resource
private RedisUtil redisUtil; private RedisUtil redisUtil;
@Resource
private RabbitMQService rabbitMQService;
@Resource
private RabbitMQProperties rabbitMQProperties;
/** /**
* 生成打印的图片 二合一 (废弃于2024/01/02) * 生成打印的图片 二合一 (废弃于2024/01/02)
* *
@@ -279,7 +291,7 @@ public class PythonService {
if (isDuplicate) { if (isDuplicate) {
elementVO.setHasUseMd5List(beforeAssemblyHasUseMd5List); elementVO.setHasUseMd5List(beforeAssemblyHasUseMd5List);
i --; i--;
switch (designPrintPictureType) { switch (designPrintPictureType) {
case PIN: case PIN:
@@ -406,13 +418,14 @@ public class PythonService {
// if (CollectionUtil.isEmpty(pinData)) { // if (CollectionUtil.isEmpty(pinData)) {
// return 0; // return 0;
// } // }
//// long topNum = sketchBoardElements.stream()
//// .filter(skecth -> skecth.getHasPin() == 1 /// / long topNum = sketchBoardElements.stream()
//// && DesignPythonItem.OUTWEAR_DRESS_BLOUSE.contains(skecth.getLevel2Type())).count(); /// / .filter(skecth -> skecth.getHasPin() == 1
//// long bottomNum = sketchBoardElements.stream() /// / && DesignPythonItem.OUTWEAR_DRESS_BLOUSE.contains(skecth.getLevel2Type())).count();
//// .filter(skecth -> skecth.getHasPin() == 1 /// / long bottomNum = sketchBoardElements.stream()
//// && DesignPythonItem.SKIRT_TROUSERS.contains(skecth.getLevel2Type())).count(); /// / .filter(skecth -> skecth.getHasPin() == 1
//// int num = Arrays.asList(topNum, bottomNum).stream().max(Comparator.comparing(Long::valueOf)).get().intValue(); /// / && DesignPythonItem.SKIRT_TROUSERS.contains(skecth.getLevel2Type())).count();
/// / int num = Arrays.asList(topNum, bottomNum).stream().max(Comparator.comparing(Long::valueOf)).get().intValue();
// int num = pinData.size(); // int num = pinData.size();
// return Math.min(num, 8); // return Math.min(num, 8);
// } // }
@@ -560,12 +573,12 @@ public class PythonService {
return 0; return 0;
} else { } else {
long pinNum = printBoardElements.stream().filter(f -> f.getHasPin() == 1).count(); long pinNum = printBoardElements.stream().filter(f -> f.getHasPin() == 1).count();
if (designNum - pinNum < 0){ if (designNum - pinNum < 0) {
return RandomsUtil.randomSysFile(0L, (long) (pinNum/2 + 1)); return RandomsUtil.randomSysFile(0L, (long) (pinNum / 2 + 1));
} else if (designNum - pinNum < designNum/2) { } else if (designNum - pinNum < designNum / 2) {
return RandomsUtil.randomSysFile(0L, designNum - pinNum + 1); return RandomsUtil.randomSysFile(0L, designNum - pinNum + 1);
} else { } else {
return RandomsUtil.randomSysFile(0L, (long) (designNum/2 + 1)); return RandomsUtil.randomSysFile(0L, (long) (designNum / 2 + 1));
} }
} }
} }
@@ -680,8 +693,7 @@ public class PythonService {
// 其他所有情况,都回退到使用系统推荐 // 其他所有情况,都回退到使用系统推荐
String categoryParam = elementVO.getModelSex().toLowerCase() + "_" + styleCategory.toLowerCase(); String categoryParam = elementVO.getModelSex().toLowerCase() + "_" + styleCategory.toLowerCase();
List<String> recommentdUrlList = getSystemSketchByCategory(categoryParam, elementVO.getBrandId(), elementVO.getBrandScale(),elementVO.getStyle()); List<String> recommentdUrlList = getSystemSketchByCategory(categoryParam, elementVO.getBrandId(), elementVO.getBrandScale(), elementVO.getStyle());
if (CollectionUtils.isEmpty(recommentdUrlList)) { if (CollectionUtils.isEmpty(recommentdUrlList)) {
throw new BusinessException("failed.to.obtain.system.sketch.recommendation"); throw new BusinessException("failed.to.obtain.system.sketch.recommendation");
} }
@@ -1039,7 +1051,7 @@ public class PythonService {
if (!CollectionUtils.isEmpty(recommentdUrlList)) { if (!CollectionUtils.isEmpty(recommentdUrlList)) {
String recommendSystemSketch = recommentdUrlList.get(0); String recommendSystemSketch = recommentdUrlList.get(0);
return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO); return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO);
}else { } else {
throw new BusinessException("failed.to.obtain.system.sketch.recommendation"); throw new BusinessException("failed.to.obtain.system.sketch.recommendation");
} }
// JSONObject attributeRecognition = getAttributeRecognitionBySameCategory(element, validateElementVO.getModelSex()); // JSONObject attributeRecognition = getAttributeRecognitionBySameCategory(element, validateElementVO.getModelSex());
@@ -1062,7 +1074,7 @@ public class PythonService {
if (!CollectionUtils.isEmpty(recommentdUrlList)) { if (!CollectionUtils.isEmpty(recommentdUrlList)) {
String recommendSystemSketch = recommentdUrlList.get(0); String recommendSystemSketch = recommentdUrlList.get(0);
return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO); return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO);
}else { } else {
throw new BusinessException("failed.to.obtain.system.sketch.recommendation"); throw new BusinessException("failed.to.obtain.system.sketch.recommendation");
} }
@@ -1098,7 +1110,7 @@ public class PythonService {
if (!CollectionUtils.isEmpty(recommentdUrlList)) { if (!CollectionUtils.isEmpty(recommentdUrlList)) {
String recommendSystemSketch = recommentdUrlList.get(0); String recommendSystemSketch = recommentdUrlList.get(0);
return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO); return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO);
}else { } else {
throw new BusinessException("failed.to.obtain.system.sketch.recommendation"); throw new BusinessException("failed.to.obtain.system.sketch.recommendation");
} }
// JSONObject attributeRecognition = getAttributeRecognitionBySameCategory(element, validateElementVO.getModelSex()); // JSONObject attributeRecognition = getAttributeRecognitionBySameCategory(element, validateElementVO.getModelSex());
@@ -1122,7 +1134,7 @@ public class PythonService {
if (!CollectionUtils.isEmpty(recommentdUrlList)) { if (!CollectionUtils.isEmpty(recommentdUrlList)) {
String recommendSystemSketch = recommentdUrlList.get(0); String recommendSystemSketch = recommentdUrlList.get(0);
return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO); return coverSystemSketchUrlToDesignPythonItem(recommendSystemSketch, category, validateElementVO);
}else { } else {
throw new BusinessException("failed.to.obtain.system.sketch.recommendation"); throw new BusinessException("failed.to.obtain.system.sketch.recommendation");
} }
// String tableName = getTableName(validateElementVO.getModelSex(), category); // String tableName = getTableName(validateElementVO.getModelSex(), category);
@@ -2190,7 +2202,7 @@ public class PythonService {
basic.setScale_earrings(0.16); basic.setScale_earrings(0.16);
if (Objects.nonNull(designLibraryModelPointVO)) { if (Objects.nonNull(designLibraryModelPointVO)) {
basic.setBody_point_test(getMap(designLibraryModelPointVO)); basic.setBody_point_test(getMap(designLibraryModelPointVO));
}else { } else {
basic.setBody_point_test(getMap(designLibraryModelPoint)); basic.setBody_point_test(getMap(designLibraryModelPoint));
} }
return basic; return basic;
@@ -2851,13 +2863,17 @@ public class PythonService {
gradientString = JSONObject.toJSONString(designSingleItem.getGradient()); gradientString = JSONObject.toJSONString(designSingleItem.getGradient());
} }
PrintToPython printToPython = resolveDesignSinglePrint(designSingleItem.getPrintObject().getPrints(), PrintToPython printToPython;
printToPython = resolveDesignSinglePrint(designSingleItem.getPrintObject().getPrints(),
designSingleItem.getPartialDesign().getPartialDesignMinioPath()); designSingleItem.getPartialDesign().getPartialDesignMinioPath());
resolveDesignElement(designSingleItem.getTrims(), printToPython); /*PrintToPython printToPython = resolveDesignSinglePrint(designSingleItem.getPrintObject().getPrints(),
log.info("组装参数【服装:{}的maskUrl: {}】",designSingleItem.getType(), designSingleItem.getMaskUrl()); designSingleItem.getPartialDesign().getPartialDesignMinioPath());*/
// resolveDesignElement(designSingleItem.getTrims(), printToPython);
log.info("组装参数【服装:{}的maskUrl: {}】", designSingleItem.getType(), designSingleItem.getMaskUrl());
String mergeImagePath = !StringUtil.isNullOrEmpty(printToPython.getPartial()) String partialDesign = designSingleItem.getPartialDesign().getPartialDesignMinioPath();
? printToPython.getPartial() : designSingleItem.getPath(); String mergeImagePath = !StringUtil.isNullOrEmpty(partialDesign)
? partialDesign : designSingleItem.getPath();
response.add(new DesignPythonItem( response.add(new DesignPythonItem(
designSingleItem.getType(), designSingleItem.getType(),
designSingleItem.getPath(), designSingleItem.getPath(),
@@ -2880,7 +2896,7 @@ public class PythonService {
}); });
if (singleOverall.equals("overall")){ if (singleOverall.equals("overall")) {
String bodyPath; String bodyPath;
if (Objects.nonNull(designLibraryModelPoint)) { if (Objects.nonNull(designLibraryModelPoint)) {
bodyPath = designLibraryModelPoint.getTemplateUrl(); bodyPath = designLibraryModelPoint.getTemplateUrl();
@@ -2896,12 +2912,12 @@ public class PythonService {
private PrintToPython resolveDesignSinglePrint(List<DesignSinglePrint> printObject, String partialDesign) { private PrintToPython resolveDesignSinglePrint(List<DesignSinglePrint> printObject, String partialDesign) {
PrintToPython printToPython = new PrintToPython(); PrintToPython printToPython = new PrintToPython();
DesignPythonItemPrint printSingle = new DesignPythonItemPrint(); // DesignPythonItemPrint printSingle = new DesignPythonItemPrint();
DesignPythonItemPrint printOverall = new DesignPythonItemPrint(); DesignPythonItemPrint printOverall = new DesignPythonItemPrint();
printToPython.setSingle(printSingle); // printToPython.setSingle(printSingle);
printToPython.setOverall(printOverall); printToPython.setOverall(printOverall);
printToPython.setPartial(StringUtil.isNullOrEmpty(partialDesign) ? null : partialDesign); printToPython.setPartial(StringUtil.isNullOrEmpty(partialDesign) ? null : partialDesign);
if (Objects.isNull(printObject) || printObject.isEmpty()){ if (Objects.isNull(printObject) || printObject.isEmpty()) {
return printToPython; return printToPython;
} }
@@ -2932,12 +2948,12 @@ public class PythonService {
Integer priority = p.getPriority(); Integer priority = p.getPriority();
setUriToMinioPath(p); setUriToMinioPath(p);
// todo 下标越界问题 // todo 下标越界问题
if (p.getIfSingle()){ if (p.getIfSingle()) {
locationS.set(priority - 1, p.getLocation()); locationS.set(priority - 1, p.getLocation());
scaleS.set(priority - 1, p.getScale()); scaleS.set(priority - 1, p.getScale());
angleS.set( priority - 1, p.getAngle()); angleS.set(priority - 1, p.getAngle());
pathsS.set(priority - 1, p.getMinIOPath()); pathsS.set(priority - 1, p.getMinIOPath());
}else { } else {
locationO.set(priority - 1, p.getLocation()); locationO.set(priority - 1, p.getLocation());
scaleO.set(priority - 1, p.getScale()); scaleO.set(priority - 1, p.getScale());
angleO.set(priority - 1, p.getAngle()); angleO.set(priority - 1, p.getAngle());
@@ -2945,14 +2961,14 @@ public class PythonService {
} }
// log.info("本次print打点locations###{}###fileVO{}", p.getLocation(), JSON.toJSONString(fileVO)); // log.info("本次print打点locations###{}###fileVO{}", p.getLocation(), JSON.toJSONString(fileVO));
}); });
locationS.removeAll(Collections.singleton(null)); /*locationS.removeAll(Collections.singleton(null));
scaleS.removeAll(Collections.singleton(null)); scaleS.removeAll(Collections.singleton(null));
angleS.removeAll(Collections.singleton(null)); angleS.removeAll(Collections.singleton(null));
pathsS.removeAll(Collections.singleton(null)); pathsS.removeAll(Collections.singleton(null));
printSingle.setLocation(locationS); printSingle.setLocation(locationS);
printSingle.setPrint_scale_list(scaleS); printSingle.setPrint_scale_list(scaleS);
printSingle.setPrint_angle_list(angleS); printSingle.setPrint_angle_list(angleS);
printSingle.setPrint_path_list(pathsS); printSingle.setPrint_path_list(pathsS);*/
locationO.removeAll(Collections.singleton(null)); locationO.removeAll(Collections.singleton(null));
scaleO.removeAll(Collections.singleton(null)); scaleO.removeAll(Collections.singleton(null));
@@ -2967,9 +2983,9 @@ public class PythonService {
} }
// 对印花类型为Generate的图片路径进行特殊处理 // 对印花类型为Generate的图片路径进行特殊处理
private void setUriToMinioPath(DesignSinglePrint print){ private void setUriToMinioPath(DesignSinglePrint print) {
if (!StringUtil.isNullOrEmpty(print.getDesignType()) && print.getDesignType().equals("Generate")){ if (!StringUtil.isNullOrEmpty(print.getDesignType()) && print.getDesignType().equals("Generate")) {
if (!StringUtil.isNullOrEmpty(print.getPath())){ if (!StringUtil.isNullOrEmpty(print.getPath())) {
try { try {
URI uri = new URI(print.getPath()); URI uri = new URI(print.getPath());
String path = uri.getPath(); // 获取路径部分: /aida-users/87/print/9ac32f65-6043-424d-a146-92c9c6d204ee-4-87.png String path = uri.getPath(); // 获取路径部分: /aida-users/87/print/9ac32f65-6043-424d-a146-92c9c6d204ee-4-87.png
@@ -3329,7 +3345,7 @@ public class PythonService {
throw new BusinessException("system error!"); throw new BusinessException("system error!");
} }
public Boolean generateSketchOrPrint(String params, String port, String servicePath) { public Boolean generateSketchOrPrint(String params, String port, String servicePath, String taskId) {
//限流校验 //限流校验
// AccessLimitUtils.validate("generateSketchOrPrint", 5); // AccessLimitUtils.validate("generateSketchOrPrint", 5);
OkHttpClient client = new OkHttpClient().newBuilder() OkHttpClient client = new OkHttpClient().newBuilder()
@@ -3391,12 +3407,36 @@ public class PythonService {
if (result && jsonObject.get("code").equals(200)) { if (result && jsonObject.get("code").equals(200)) {
log.info("Generate##responseObject###{}", jsonObject); log.info("Generate##responseObject###{}", jsonObject);
// return setGenerateImageList(jsonObject.getJSONObject("data")); // return setGenerateImageList(jsonObject.getJSONObject("data"));
if (servicePath == CommonConstant.GENERATE_PATH_FLUX2_KLEIN) {
//放入结果到mq
JSONObject data = jsonObject.getJSONObject("data");
String outputPath = data.getString("output_path");
Map<String, String> mqMessage = new HashMap<>();
mqMessage.put("tasks_id", taskId);
mqMessage.put("status", "SUCCESS");
mqMessage.put("message", "success");
mqMessage.put("image_url", outputPath);
mqMessage.put("category", "");
String mqMessageBody = JSON.toJSONString(mqMessage);
rabbitMQService.publishMessageToGenerateResult(mqMessageBody);
}
return Boolean.TRUE; return Boolean.TRUE;
} else { } else {
log.info("generateSketchOrPrintPrint失败###{}", jsonObject); log.info("generateSketchOrPrintPrint失败###{}", jsonObject);
log.info("Generate Exception! Code : " + jsonObject.get("code")); log.info("Generate Exception! Code : " + jsonObject.get("code"));
Map<String, String> mqMessage = new HashMap<>();
mqMessage.put("tasks_id", taskId);
mqMessage.put("status", "ERROR");
mqMessage.put("message", "");
mqMessage.put("image_url", "");
mqMessage.put("category", "");
String mqMessageBody = JSON.toJSONString(mqMessage);
rabbitMQService.publishMessageToGenerateResult(mqMessageBody);
return Boolean.FALSE; return Boolean.FALSE;
} }
} }
public Response sendPostToModel(String content, String portAndRoute, String functionName) { public Response sendPostToModel(String content, String portAndRoute, String functionName) {
@@ -3438,7 +3478,10 @@ public class PythonService {
return imageUrlList; return imageUrlList;
}*/ }*/
/** 废弃状态 */
/**
* 废弃状态
*/
public String composeLayers(List<OutfitDetailPythonItem> layersDetail) { public String composeLayers(List<OutfitDetailPythonItem> layersDetail) {
HashMap<String, List<OutfitDetailPythonItem>> layers = new HashMap<>(); HashMap<String, List<OutfitDetailPythonItem>> layers = new HashMap<>();
HashMap<String, HashMap<String, List<OutfitDetailPythonItem>>> content = new HashMap<>(); HashMap<String, HashMap<String, List<OutfitDetailPythonItem>>> content = new HashMap<>();
@@ -3749,7 +3792,7 @@ public class PythonService {
throw new BusinessException("relightImage.interface.exception"); throw new BusinessException("relightImage.interface.exception");
} }
public String imageToSketch(String imagePath, String bucket, String objectName, String styleCode, String styleImageUrl){ public String imageToSketch(String imagePath, String bucket, String objectName, String styleCode, String styleImageUrl) {
OkHttpClient client = new OkHttpClient().newBuilder() OkHttpClient client = new OkHttpClient().newBuilder()
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
.pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒) .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒)
@@ -3796,7 +3839,7 @@ public class PythonService {
String sketchResult = jsonObject.get("data").toString(); String sketchResult = jsonObject.get("data").toString();
log.info("ImageToSketch 结果 {}", sketchResult); log.info("ImageToSketch 结果 {}", sketchResult);
return sketchResult; return sketchResult;
}else { } else {
log.info("ImageToSketch 失败。 Response code {}", responseCode); log.info("ImageToSketch 失败。 Response code {}", responseCode);
throw new BusinessException("ImageToSketch 失败。 Response code " + responseCode); throw new BusinessException("ImageToSketch 失败。 Response code " + responseCode);
} }
@@ -3849,7 +3892,7 @@ public class PythonService {
throw new BusinessException("bright.interface.exception"); throw new BusinessException("bright.interface.exception");
} }
public JSONObject attributeRecognition(List<String> pictureUrls,List<String> ids, List<String> category) { public JSONObject attributeRecognition(List<String> pictureUrls, List<String> ids, List<String> category) {
//限流校验 //限流校验
AccessLimitUtils.validate("attributeRecognition", 20); AccessLimitUtils.validate("attributeRecognition", 20);
OkHttpClient client = new OkHttpClient().newBuilder() OkHttpClient client = new OkHttpClient().newBuilder()
@@ -3881,7 +3924,7 @@ public class PythonService {
} catch (IOException ioException) { } catch (IOException ioException) {
log.error("PythonService###attributeRecognition异常##{}", ExceptionUtil.getThrowableList(ioException)); log.error("PythonService###attributeRecognition异常##{}", ExceptionUtil.getThrowableList(ioException));
} }
log.info("识别python对应的属性标签值结果###{}",bodyStr.trim()); log.info("识别python对应的属性标签值结果###{}", bodyStr.trim());
//去除限流 //去除限流
AccessLimitUtils.validateOut("attributeRecognition"); AccessLimitUtils.validateOut("attributeRecognition");
if (Objects.isNull(response)) { if (Objects.isNull(response)) {
@@ -3965,7 +4008,7 @@ public class PythonService {
throw new BusinessException("design.interface.exception"); throw new BusinessException("design.interface.exception");
} }
public List<String> getSystemSketchByCategory(String category, Long brandId, Double brandScale,String style) { public List<String> getSystemSketchByCategory(String category, Long brandId, Double brandScale, String style) {
//******3.1.2版本临时使用java推荐方案去解决style未使用的问题********** //******3.1.2版本临时使用java推荐方案去解决style未使用的问题**********
// try { // try {
// //使用新库attribute_retrieval_style表命名修改为elementVO.getModelSex().toLowerCase() + "_" + styleCategory.toLowerCase()比如female_skirt,与传入的category保持一致 // //使用新库attribute_retrieval_style表命名修改为elementVO.getModelSex().toLowerCase() + "_" + styleCategory.toLowerCase()比如female_skirt,与传入的category保持一致
@@ -3989,6 +4032,14 @@ public class PythonService {
// throw new BusinessException("system.error"); // throw new BusinessException("system.error");
// } // }
//**********************end*********************************** //**********************end***********************************
//临时补丁
if (category != null && style != null) {
String categoryPrefix = category.split("_")[0];
if ("male".equals(categoryPrefix) &&
(style.equalsIgnoreCase("lolita") || style.equalsIgnoreCase("romantic"))) {
style = null;
}
}
AuthPrincipalVo userHolder = UserContext.getUserHolder(); AuthPrincipalVo userHolder = UserContext.getUserHolder();
OkHttpClient client = new OkHttpClient().newBuilder() OkHttpClient client = new OkHttpClient().newBuilder()
@@ -4110,6 +4161,7 @@ public class PythonService {
//生成失败 //生成失败
throw new BusinessException("segProduct.interface.exception"); throw new BusinessException("segProduct.interface.exception");
} }
/** /**
* 转发 seg_anything 请求到 python 服务 * 转发 seg_anything 请求到 python 服务
* 请求 body 由调用方组装(包含 user_id, image_path, type, points, labels, box 等) * 请求 body 由调用方组装(包含 user_id, image_path, type, points, labels, box 等)
@@ -4122,6 +4174,9 @@ public class PythonService {
.writeTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS)
.build(); .build();
MediaType mediaType = MediaType.parse("application/json"); MediaType mediaType = MediaType.parse("application/json");
content.put("bucket", userBucketName);
content.put("object_name", content.get("user_id") + "/" + "segment" + "/" + UUID.randomUUID() + ".png");
content.remove("user_id");
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content)); RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content));
String url = accessPythonIp + ":" + accessPythonPort + "/api/seg_anything"; String url = accessPythonIp + ":" + accessPythonPort + "/api/seg_anything";
@@ -4152,18 +4207,18 @@ public class PythonService {
if (responseObject != null) { if (responseObject != null) {
JSONObject dataObj = responseObject.getJSONObject("data"); JSONObject dataObj = responseObject.getJSONObject("data");
if (dataObj != null) { if (dataObj != null) {
String output = dataObj.getString("output"); String output = dataObj.getString("output");
if (!StringUtil.isNullOrEmpty(output)) { if (!StringUtil.isNullOrEmpty(output)) {
try { try {
String presigned = minioUtil.getPreSignedUrl(output, 24 * 60); String presigned = minioUtil.getPreSignedUrl(output, 24 * 60);
return presigned; return presigned;
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to generate presigned url for {}: {}", output, e.getMessage()); log.error("Failed to generate presigned url for {}: {}", output, e.getMessage());
throw new BusinessException("segAnything.presign.failed"); throw new BusinessException("segAnything.presign.failed");
}
} }
} }
} }
}
} catch (Exception ex) { } catch (Exception ex) {
log.error("PythonService##segAnything post-process error###{}", ex.getMessage()); log.error("PythonService##segAnything post-process error###{}", ex.getMessage());
@@ -4173,7 +4228,7 @@ public class PythonService {
throw new BusinessException("segAnything.missing.output"); throw new BusinessException("segAnything.missing.output");
} }
throw new BusinessException("segAnything.interface.exception"); throw new BusinessException("segAnything.interface.exception");
} catch (IOException |JSONException e) { } catch (IOException | JSONException e) {
log.error("PythonService##segAnything异常###{}", e.getMessage()); log.error("PythonService##segAnything异常###{}", e.getMessage());
throw new BusinessException("segAnything.interface.exception"); throw new BusinessException("segAnything.interface.exception");
} }
@@ -4181,6 +4236,7 @@ public class PythonService {
log.error("PythonService##segAnything异常response###{}", response); log.error("PythonService##segAnything异常response###{}", response);
throw new BusinessException("segAnything.interface.exception"); throw new BusinessException("segAnything.interface.exception");
} }
public Boolean poseTransformation(JSONObject content, String apiUri) { public Boolean poseTransformation(JSONObject content, String apiUri) {
OkHttpClient client = new OkHttpClient().newBuilder() OkHttpClient client = new OkHttpClient().newBuilder()
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
@@ -4284,7 +4340,7 @@ public class PythonService {
String modifiedModel = jsonObject.get("data").toString(); String modifiedModel = jsonObject.get("data").toString();
log.info("modifyModelProportion 结果 {}", modifiedModel); log.info("modifyModelProportion 结果 {}", modifiedModel);
return modifiedModel; return modifiedModel;
}else { } else {
log.info("modifyModelProportion 失败。 Response code {}", responseCode); log.info("modifyModelProportion 失败。 Response code {}", responseCode);
throw new BusinessException("modifyModelProportion 失败。 Response code " + responseCode); throw new BusinessException("modifyModelProportion 失败。 Response code " + responseCode);
} }
@@ -4387,10 +4443,11 @@ public class PythonService {
log.info("imageSegmentation 结果 {}", jsonObject.get("data").toString()); log.info("imageSegmentation 结果 {}", jsonObject.get("data").toString());
List<ImageSegmentation.ImageDate> seg = JSONObject.parseObject( List<ImageSegmentation.ImageDate> seg = JSONObject.parseObject(
jsonObject.get("data").toString(), jsonObject.get("data").toString(),
new TypeReference<List<ImageSegmentation.ImageDate>>() {} new TypeReference<List<ImageSegmentation.ImageDate>>() {
}
); );
return seg; return seg;
}else { } else {
log.info("imageSegmentation 失败。 Response code {}", responseCode); log.info("imageSegmentation 失败。 Response code {}", responseCode);
throw new BusinessException("imageSegmentation 失败。 Response code " + responseCode); throw new BusinessException("imageSegmentation 失败。 Response code " + responseCode);
} }

View File

@@ -1,13 +1,13 @@
package com.ai.da.python.vo; package com.ai.da.python.vo;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@Data @Data
public class DesignPythonItemPrint { public class DesignPythonItemPrint {
@@ -53,7 +53,7 @@ public class DesignPythonItemPrint {
if (ifDesign){ if (ifDesign){
this.print_path_list = print_path_list; this.print_path_list = print_path_list;
this.location = Collections.singletonList(Arrays.asList(0.0f, 0.0f)); this.location = Collections.singletonList(Arrays.asList(0.0f, 0.0f));
this.print_scale_list = Collections.singletonList(Arrays.asList(0.0f, 0.0f)); this.print_scale_list = Collections.singletonList(Arrays.asList(1.0f, 1.0f));
this.print_angle_list = Arrays.asList(0.0, 0.0); this.print_angle_list = Arrays.asList(0.0, 0.0);
} }

View File

@@ -20,6 +20,25 @@ public interface GlobalAwardService {
CheckOTPVO checkCode(String email, String otp); CheckOTPVO checkCode(String email, String otp);
void checkSecurityToken(String email, String securityToken); void checkSecurityToken(String email, String securityToken);
/**
* 导出参赛者列表为 Excel二进制
* @return Excel 文件的字节数组
*/
byte[] exportContestants() throws Exception;
/**
* 将参赛者列表导出并保存到服务端本地目录(使用服务配置的 uploadDir/exports
*/
void saveContestantsToLocal() throws Exception;
/**
* 根据参赛者编号范围导出参赛者文件到本地目录
* @param minContestantNumber 最小参赛者编号
* @param maxContestantNumber 最大参赛者编号
* @return 导出的参赛者数量
*/
int exportContestantFiles(Integer minContestantNumber, Integer maxContestantNumber) throws Exception;
} }

View File

@@ -7,6 +7,8 @@ public interface RabbitMQService {
void publishMessageToGenerate(String message); void publishMessageToGenerate(String message);
void publishMessageToGenerateResult(String message);
void publishMessageToSR(String message); void publishMessageToSR(String message);
Integer getMessageCount(String queueUrl); Integer getMessageCount(String queueUrl);

View File

@@ -244,12 +244,13 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class);
response.setEmail(account.getUserEmail()); response.setEmail(account.getUserEmail());
String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId()));
if (StringUtils.isNotBlank(token)) { /*if (StringUtils.isNotBlank(token)) {
//用户已登入 //用户已登入
response.setToken(token); response.setToken(token);
} else { } else {
response.setToken(createAccountToken(account)); response.setToken(createAccountToken(account));
} }*/
response.setToken(createAccountToken(account));
response.setUserId(account.getId()); response.setUserId(account.getId());
response.setSystemUser(account.getSystemUser()); response.setSystemUser(account.getSystemUser());
// 设置头像 // 设置头像

View File

@@ -82,7 +82,7 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
// 邮件通知审批者 // 邮件通知审批者
String merchantEmail = "kimwong@code-create.com.hk"; String merchantEmail = "kimwong@code-create.com.hk";
String developer = "xupei3360@163.com"; String developer = "xupei3360@163.com";
String[] receiverEmail = {/*merchantEmail,*/ developer}; String[] receiverEmail = {merchantEmail, developer};
SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new"); SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new"); // emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
}else { }else {
@@ -442,7 +442,7 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
String merchantEmail = "kimwong@code-create.com.hk"; String merchantEmail = "kimwong@code-create.com.hk";
String developer = "xupei3360@163.com"; String developer = "xupei3360@163.com";
String[] receiverEmail = {/*merchantEmail,*/ developer}; String[] receiverEmail = {merchantEmail, developer};
// 邮件通知 // 邮件通知
SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary"); SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary");
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary"); // emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary");

View File

@@ -520,9 +520,10 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
.filter(f -> f.getDesignType().equals(DesignTypeEnum.COLLECTION.getRealName())) .filter(f -> f.getDesignType().equals(DesignTypeEnum.COLLECTION.getRealName()))
.map(DesignCollectionPrintElementDTO::getId) .map(DesignCollectionPrintElementDTO::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
List<CollectionElement> printBoardElements = new ArrayList<>();
if (!CollectionUtils.isEmpty(printBoardIds)) { if (!CollectionUtils.isEmpty(printBoardIds)) {
// 从数据库批量查询printBoard元素 // 从数据库批量查询printBoard元素
List<CollectionElement> printBoardElements = collectionElementMapper.selectBatchIds(printBoardIds); printBoardElements = collectionElementMapper.selectBatchIds(printBoardIds);
// 验证查询结果的完整性 // 验证查询结果的完整性
if (CollectionUtil.isEmpty(printBoardElements) || printBoardElements.size() != printBoardIds.size()) { if (CollectionUtil.isEmpty(printBoardElements) || printBoardElements.size() != printBoardIds.size()) {
throw new BusinessException("get.printBoards.data.is.mismatch"); throw new BusinessException("get.printBoards.data.is.mismatch");
@@ -543,7 +544,8 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
Map<Long, DesignCollectionPrintElementDTO> idToMap = designDTO.getPrintBoards() Map<Long, DesignCollectionPrintElementDTO> idToMap = designDTO.getPrintBoards()
.stream() .stream()
.collect(Collectors.toMap(DesignCollectionPrintElementDTO::getId, v -> v)); .collect(Collectors.toMap(DesignCollectionPrintElementDTO::getId, v -> v));
libraryCollectionElements.addAll(covertLibrarysToPrintCollections(librarys, idToMap)); printBoardElements.addAll(covertLibrarysToPrintCollections(librarys, idToMap));
// libraryCollectionElements.addAll(covertLibrarysToPrintCollections(librarys, idToMap));
} }
} }
@@ -559,7 +561,8 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
Map<Long, DesignCollectionPrintElementDTO> idToMap = designDTO.getPrintBoards() Map<Long, DesignCollectionPrintElementDTO> idToMap = designDTO.getPrintBoards()
.stream() .stream()
.collect(Collectors.toMap(DesignCollectionPrintElementDTO::getId, v -> v)); .collect(Collectors.toMap(DesignCollectionPrintElementDTO::getId, v -> v));
generateCollectionElements.addAll(covertGeneratesToPrintCollections(generateDetailList, idToMap)); printBoardElements.addAll(covertGeneratesToPrintCollections(generateDetailList, idToMap));
// generateCollectionElements.addAll(covertGeneratesToPrintCollections(generateDetailList, idToMap));
} }
} }
} }

View File

@@ -33,7 +33,6 @@ import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.*; import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -149,7 +148,17 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
|| ADMIN_IDS.contains(account.getId()) || ADMIN_IDS.contains(account.getId())
|| ADMIN_IDS_READ_ONLY.contains(account.getId()) || ADMIN_IDS_READ_ONLY.contains(account.getId())
)) { )) {
if (StringUtil.isNullOrEmpty(startTime)) startTime = "2024-02-01 00:00:00"; boolean filterBySecond ;
if (StringUtil.isNullOrEmpty(startTime)) {
startTime = "2024-02-01 00:00:00";
filterBySecond = true;
} else {
LocalDateTime thresholdTime = LocalDateTime.of(2024, 5, 1, 0, 0, 0);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startDateTime = LocalDateTime.parse(startTime, formatter);
filterBySecond = startDateTime.isBefore(thresholdTime);
}
if (StringUtil.isNullOrEmpty(endTime)) { if (StringUtil.isNullOrEmpty(endTime)) {
// yyyy-MM-dd HH:mm:ss "HH"表示24小时制 "hh"表示12小时制 // yyyy-MM-dd HH:mm:ss "HH"表示24小时制 "hh"表示12小时制
endTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); endTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
@@ -173,7 +182,7 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
default: default:
throw new BusinessException("have.no.permission", ResultEnum.PROMPT.getCode()); throw new BusinessException("have.no.permission", ResultEnum.PROMPT.getCode());
} }
return designMapper.getDesignStatistic(startTime, endTime, ids, email, role, account.getOrganizationName()); return designMapper.getDesignStatistic(startTime, endTime, ids, email, role, account.getOrganizationName(), filterBySecond);
} else { } else {
throw new BusinessException("have.no.permission", ResultEnum.PROMPT.getCode()); throw new BusinessException("have.no.permission", ResultEnum.PROMPT.getCode());
} }
@@ -695,14 +704,19 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
String username = UserContext.getUserHolder().getUsername(); String username = UserContext.getUserHolder().getUsername();
Account account = new Account(); Account account = new Account();
account.setId(accountId);
// 修改用户有效期截止日期、用户类型、积分 // 修改用户有效期截止日期、用户类型、积分
if (!Objects.isNull(validEndTime)) { if (!Objects.isNull(validEndTime)) {
account.setValidEndTime(validEndTime); account.setValidEndTime(validEndTime);
log.info("管理员:{},修改用户 {} 信息,将账号到期时间置为:{}", username, accountId, validEndTime); log.info("管理员:{},修改用户 {} 信息,将账号到期时间置为:{}", username, accountId, validEndTime);
} }
if (!Objects.isNull(systemUser)) { if (!Objects.isNull(systemUser) && !systemUser.equals(0)) {
account.setSystemUser(systemUser); account.setSystemUser(systemUser);
log.info("管理员:{},修改用户 {} 信息,将账号身份置为:{}", username, accountId, systemUser); log.info("管理员:{},修改用户 {} 信息,将账号身份置为:{}", username, accountId, systemUser);
} else if (systemUser.equals(0)){
// 将用户身份设置为游客
accountService.toVisitor(account);
return true;
} }
/*if (!StringUtils.isNullOrEmpty(systemUser)) { /*if (!StringUtils.isNullOrEmpty(systemUser)) {
int systemUser = 0; int systemUser = 0;
@@ -728,7 +742,6 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
} }
// todo 如果修改管理员账号的积分上限或子账号数量,则其所有子账号的积分上限需要重新计算 // todo 如果修改管理员账号的积分上限或子账号数量,则其所有子账号的积分上限需要重新计算
account.setId(accountId);
account.setUpdateDate(new Date()); account.setUpdateDate(new Date());
return accountMapper.updateById(account) == 1; return accountMapper.updateById(account) == 1;
// accountService.update(account,null); // accountService.update(account,null);
@@ -857,19 +870,20 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl<QuestionnaireMappe
if (!StringUtil.isNullOrEmpty(queryPaymentInfoDTO.getOrder()) && queryPaymentInfoDTO.getOrder().equals("ASC")) { if (!StringUtil.isNullOrEmpty(queryPaymentInfoDTO.getOrder()) && queryPaymentInfoDTO.getOrder().equals("ASC")) {
order = "ASC"; order = "ASC";
} }
String status = StringUtil.isNullOrEmpty(queryPaymentInfoDTO.getStatus()) ? "Success" : queryPaymentInfoDTO.getStatus();
List<PaymentInfoVO> paymentInfoVOS = paymentInfoMapper.queryPaymentInfo(queryPaymentInfoDTO.getPlatform(), queryPaymentInfoDTO.getPayerTotal(), List<PaymentInfoVO> paymentInfoVOS = paymentInfoMapper.queryPaymentInfo(queryPaymentInfoDTO.getPlatform(), queryPaymentInfoDTO.getPayerTotal(),
queryPaymentInfoDTO.getType(), queryPaymentInfoDTO.getStatus(), queryPaymentInfoDTO.getType(), status,
queryPaymentInfoDTO.getCountry(), queryPaymentInfoDTO.getCity(), queryPaymentInfoDTO.getCountry(), queryPaymentInfoDTO.getCity(),
queryPaymentInfoDTO.getStartTime(), queryPaymentInfoDTO.getEndTime(), queryPaymentInfoDTO.getStartTime(), queryPaymentInfoDTO.getEndTime(),
size, offset, order, queryPaymentInfoDTO.getPayer()); size, offset, order, queryPaymentInfoDTO.getPayer());
// 查询数据总量 // 查询数据总量
Long total = paymentInfoMapper.queryPaymentInfoCount(queryPaymentInfoDTO.getPlatform(), queryPaymentInfoDTO.getPayerTotal(), Long total = paymentInfoMapper.queryPaymentInfoCount(queryPaymentInfoDTO.getPlatform(), queryPaymentInfoDTO.getPayerTotal(),
queryPaymentInfoDTO.getType(), queryPaymentInfoDTO.getStatus(), queryPaymentInfoDTO.getType(), status,
queryPaymentInfoDTO.getCountry(), queryPaymentInfoDTO.getCity(), queryPaymentInfoDTO.getCountry(), queryPaymentInfoDTO.getCity(),
queryPaymentInfoDTO.getStartTime(), queryPaymentInfoDTO.getEndTime(), queryPaymentInfoDTO.getPayer()); queryPaymentInfoDTO.getStartTime(), queryPaymentInfoDTO.getEndTime(), queryPaymentInfoDTO.getPayer());
// 查询符合查询条件的总金额 // 查询符合查询条件的总金额
BigDecimal payerTotal = paymentInfoMapper.queryTotalPaymentAmount(queryPaymentInfoDTO.getPlatform(), queryPaymentInfoDTO.getPayerTotal(), BigDecimal payerTotal = paymentInfoMapper.queryTotalPaymentAmount(queryPaymentInfoDTO.getPlatform(), queryPaymentInfoDTO.getPayerTotal(),
queryPaymentInfoDTO.getType(), queryPaymentInfoDTO.getStatus(), queryPaymentInfoDTO.getType(), status,
queryPaymentInfoDTO.getCountry(), queryPaymentInfoDTO.getCity(), queryPaymentInfoDTO.getCountry(), queryPaymentInfoDTO.getCity(),
queryPaymentInfoDTO.getStartTime(), queryPaymentInfoDTO.getEndTime(), queryPaymentInfoDTO.getPayer()); queryPaymentInfoDTO.getStartTime(), queryPaymentInfoDTO.getEndTime(), queryPaymentInfoDTO.getPayer());
// 总页数 // 总页数

View File

@@ -497,6 +497,10 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
.collect(Collectors.toMap(DesignSingleItemDTO::getPriority, DesignSingleItemDTO::getOffset)); .collect(Collectors.toMap(DesignSingleItemDTO::getPriority, DesignSingleItemDTO::getOffset));
} }
// 创建 priority 到 DesignSingleItemDTO 的映射,用于获取 transpose 和 rotate
Map<Integer, DesignSingleItemDTO> priorityToItemDTOMap = designSingleItemDTOList.stream()
.collect(Collectors.toMap(DesignSingleItemDTO::getPriority, dto -> dto, (old, newVal) -> old));
List<TDesignPythonOutfitDetail> list = new ArrayList<>(); List<TDesignPythonOutfitDetail> list = new ArrayList<>();
for (int i = 0; i < layers.size(); i++) { for (int i = 0; i < layers.size(); i++) {
JSONObject jsonObject = layers.getJSONObject(i); JSONObject jsonObject = layers.getJSONObject(i);
@@ -525,8 +529,12 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
designPythonOutfitDetail.setOffset(String.valueOf(priorityOffset.get(Math.abs(priority)))); designPythonOutfitDetail.setOffset(String.valueOf(priorityOffset.get(Math.abs(priority))));
} }
designPythonOutfitDetail.setPriority(priority); designPythonOutfitDetail.setPriority(priority);
designPythonOutfitDetail.setTranspose(jsonObject.getString("transpose")); // 从前端传入的 DesignSingleItemDTO 中获取 transpose 和 rotate不再从 Python 返回的数据获取
designPythonOutfitDetail.setRotate(jsonObject.getDouble("rotate")); DesignSingleItemDTO itemDTO = priorityToItemDTOMap.get(Math.abs(priority));
if (itemDTO != null) {
designPythonOutfitDetail.setTranspose(itemDTO.getTranspose() != null ? Arrays.toString(itemDTO.getTranspose()) : null);
designPythonOutfitDetail.setRotate(itemDTO.getRotate());
}
list.add(designPythonOutfitDetail); list.add(designPythonOutfitDetail);
} }
@@ -1036,7 +1044,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
@Override @Override
public Map<String, List<String>> setPriorityAndUndividedLayer(JSONArray layers, DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO) { public Map<String, List<String>> setPriorityAndUndividedLayer(JSONArray layers, DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO) {
String designType = "default"; String designType = "default";
if (Objects.nonNull(designSingleIncludeLayersDTO)) { if (Objects.nonNull(designSingleIncludeLayersDTO)) {
designType = designSingleIncludeLayersDTO.getDesignType(); designType = designSingleIncludeLayersDTO.getDesignType();
} }

View File

@@ -46,6 +46,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@@ -1669,6 +1670,24 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
.lt("create_date", endTime) .lt("create_date", endTime)
.select("count(id) as count"); .select("count(id) as count");
// 如果startTime早于2024-05-01 00:00:00添加额外的筛选条件
LocalDateTime thresholdTime = LocalDateTime.of(2024, 5, 1, 0, 0, 0);
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startDateTime = LocalDateTime.parse(startTime, formatter);
if (startDateTime.isBefore(thresholdTime)) {
// 使用 notLike 来排除以 ":01" 或 ":02" 结尾的时间
// 方案2.1:使用 apply 方法执行数据库函数 create_date 字段的实际存储格式(可能包含毫秒),所以取最后三个字符进行匹配)
queryWrapper.apply("DATE_FORMAT(create_date, '%s') NOT IN ('01', '02')");
/*queryWrapper.notLike("create_date", "%:01")
.notLike("create_date", "%:02");*/
}
} catch (Exception e) {
log.warn("Failed to parse startTime: {}, skip time-based filtering", startTime, e);
}
if (!Objects.isNull(accountIds) && !accountIds.isEmpty()) { if (!Objects.isNull(accountIds) && !accountIds.isEmpty()) {
queryWrapper.in("account_id", accountIds); queryWrapper.in("account_id", accountIds);
} }
@@ -1676,7 +1695,7 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
List<Map<String, Object>> result = baseMapper.selectMaps(queryWrapper); List<Map<String, Object>> result = baseMapper.selectMaps(queryWrapper);
if (result != null && !result.isEmpty()) { if (result != null && !result.isEmpty()) {
Object countObj = result.get(0).get("count"); Object countObj = result.get(0).get("count");
return (Long) countObj; return countObj != null ? ((Number) countObj).longValue() : 0L;
} else { } else {
return 0L; return 0L;
} }

View File

@@ -587,7 +587,7 @@ public class EmailServiceImpl implements EmailService {
try { try {
String merchantEmail = "kimwong@code-create.com.hk"; String merchantEmail = "kimwong@code-create.com.hk";
String developer = "xupei3360@163.com"; String developer = "xupei3360@163.com";
List<String> merchantReceiver = Arrays.asList(/*merchantEmail,*/ developer); List<String> merchantReceiver = Arrays.asList(merchantEmail, developer);
String merchantSubject = null; String merchantSubject = null;
String merchantTemplate = null; String merchantTemplate = null;
@@ -731,7 +731,7 @@ public class EmailServiceImpl implements EmailService {
jsonObject.put("quantity", quantity); jsonObject.put("quantity", quantity);
jsonObject.put("totalFee", amount); jsonObject.put("totalFee", amount);
sendEmail(Arrays.asList(/*merchantEmail,*/ developerEmail), jsonObject, CREDITS_PURCHASE_MERCHANT, "New Credit Purchase Order", null, null); 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"; private final static String COMMON_EXCEPTION_REMINDER = "135279_common-exception-reminder.html";

View File

@@ -48,6 +48,8 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.*; import okhttp3.*;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
@@ -59,10 +61,12 @@ import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
@@ -194,10 +198,13 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
generate.setText(text); generate.setText(text);
Long elementId = generateThroughImageTextDTO.getCollectionElementId(); Long elementId = generateThroughImageTextDTO.getCollectionElementId();
// validateGeneraType(generate, text, elementId); // validateGeneraType(generate, text, elementId);
if (!StringUtil.isNullOrEmpty(text)) { if (!(generateThroughImageTextDTO.getLevel1Type().equals(MOOD_BOARD.getRealName())&&generateThroughImageTextDTO.getModelName().equals("high"))){
text = modifyPrompt(text, generate, generateThroughImageTextDTO.getLevel1Type(), generateThroughImageTextDTO.getAgeGroup()); if (!StringUtil.isNullOrEmpty(text)) {
text = modifyPrompt(text, generate, generateThroughImageTextDTO.getLevel1Type(), generateThroughImageTextDTO.getAgeGroup());
}
} }
// todo 这一步现在还是有必要的吗? // todo 这一步现在还是有必要的吗?
// 2.1 sketch或print在t_collection_element表/t_library表中的信息是否需要更新 如 level2Type // 2.1 sketch或print在t_collection_element表/t_library表中的信息是否需要更新 如 level2Type
CollectionElement collectionElement = collectionElementService.editLevel2Type(elementId, generateThroughImageTextDTO.getLevel2Type(), generateThroughImageTextDTO.getDesignType()); CollectionElement collectionElement = collectionElementService.editLevel2Type(elementId, generateThroughImageTextDTO.getLevel2Type(), generateThroughImageTextDTO.getDesignType());
@@ -218,6 +225,8 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
version = "fast"; version = "fast";
params.put("version", "fast"); params.put("version", "fast");
} }
// 4、将请求信息落库,将本次generate的请求信息添加到t_generate表中
saveGenerateImmediately(generate);
// 3.1 确定不同类型的印花分别调哪个接口 // 3.1 确定不同类型的印花分别调哪个接口
if (generateThroughImageTextDTO.getLevel1Type().equals(PRINT_BOARD.getRealName())) { if (generateThroughImageTextDTO.getLevel1Type().equals(PRINT_BOARD.getRealName())) {
switch (generateThroughImageTextDTO.getLevel2Type()) { switch (generateThroughImageTextDTO.getLevel2Type()) {
@@ -243,15 +252,28 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
jsonString = JSON.toJSONString(generateToPythonDTO, SerializerFeature.WriteMapNullValue); jsonString = JSON.toJSONString(generateToPythonDTO, SerializerFeature.WriteMapNullValue);
} }
} else { } else {
GenerateToPythonDTO generateToPythonDTO = new GenerateToPythonDTO(generateThroughImageTextDTO.getUniqueId(), text, Objects.isNull(collectionElement) ? "" : collectionElement.getUrl(), if (Objects.equals(version, "fast")) {
mode, category, generateThroughImageTextDTO.getGender(), version); GenerateToPythonDTO generateToPythonDTO = new GenerateToPythonDTO(generateThroughImageTextDTO.getUniqueId(), text, Objects.isNull(collectionElement) ? "" : collectionElement.getUrl(),
jsonString = JSON.toJSONString(generateToPythonDTO, SerializerFeature.WriteMapNullValue); mode, category, generateThroughImageTextDTO.getGender(), version);
jsonString = JSON.toJSONString(generateToPythonDTO, SerializerFeature.WriteMapNullValue);
} else {
path = CommonConstant.GENERATE_PATH_FLUX2_KLEIN;
// 构建object_name: {userId}/{category}/{uuid}.png
String objectName = generateThroughImageTextDTO.getUserId() + "/" + category + "/" + UUID.randomUUID() + ".png";
ImageProcessRequest imageProcessRequest = ImageProcessRequest.builder()
.object_name(objectName)
.bucket_name(userBucket)
.prompt(text).build();
jsonString = JSON.toJSONString(imageProcessRequest);
}
} }
Boolean requestResult = pythonService.generateSketchOrPrint(jsonString, port, path); Boolean requestResult = pythonService.generateSketchOrPrint(jsonString, port, path, generateThroughImageTextDTO.getUniqueId());
// 4、将请求信息落库,将本次generate的请求信息添加到t_generate表中
save(generate);
// 5、将本次请求存入redis // 5、将本次请求存入redis
String key = generateResultKey + ":" + generateThroughImageTextDTO.getUniqueId(); String key = generateResultKey + ":" + generateThroughImageTextDTO.getUniqueId();
@@ -266,6 +288,40 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
public void saveGenerateImmediately(Generate generate) {
save(generate);
// 使用 TransactionSynchronizationManager 在事务真正提交后再设锁
// 否则 save() 完成后事务尚未 commitMQ 消费者立即读到 null
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
String lockKey = "generate:lock:" + generate.getUniqueId();
redisUtil.addToString(lockKey, "1", 60L);
log.debug("Save lock set after commit for uniqueId: {}", generate.getUniqueId());
}
});
}
private void waitForSaveLock(String uniqueId) {
String lockKey = "generate:lock:" + uniqueId;
int maxRetries = 30;
int retryIntervalMs = 200;
for (int i = 0; i < maxRetries; i++) {
if (Boolean.TRUE.equals(redisUtil.hasKey(lockKey))) {
log.debug("Save lock acquired for uniqueId: {} after {} retries", uniqueId, i);
return;
}
try {
Thread.sleep(retryIntervalMs);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("Interrupted while waiting for save lock: {}", uniqueId);
return;
}
}
log.warn("Save lock timeout for uniqueId: {}, proceeding anyway", uniqueId);
}
public GenerateModeEnum getMode(GenerateThroughImageTextDTO generateThroughImageTextDTO) { public GenerateModeEnum getMode(GenerateThroughImageTextDTO generateThroughImageTextDTO) {
if (!StringUtil.isNullOrEmpty(generateThroughImageTextDTO.getText())) { if (!StringUtil.isNullOrEmpty(generateThroughImageTextDTO.getText())) {
if (Objects.nonNull(generateThroughImageTextDTO.getCollectionElementId())) { if (Objects.nonNull(generateThroughImageTextDTO.getCollectionElementId())) {
@@ -284,11 +340,16 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void processGenerateResult(String taskId, String url, String category) { public void processGenerateResult(String taskId, String url, String category) {
log.info("============ProcessGenerateResult listening==========");
log.debug("taskId: " + taskId);
String status = null;
// 1、处理模型返回的数据 // 1、处理模型返回的数据
GenerateDetail generateDetail = new GenerateDetail(); GenerateDetail generateDetail = new GenerateDetail();
GenerateCollectionItemVO generateCollectionItemVO = new GenerateCollectionItemVO(); GenerateCollectionItemVO generateCollectionItemVO = new GenerateCollectionItemVO();
Generate generate; Generate generate;
try { try {
// 等待 HTTP 线程写入完成后再查库
waitForSaveLock(taskId);
generate = selectByUniqueId(taskId); generate = selectByUniqueId(taskId);
} catch (MybatisPlusException e) { } catch (MybatisPlusException e) {
log.error(e.getMessage()); log.error(e.getMessage());
@@ -311,14 +372,15 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
generateDetail.setUrl(url); generateDetail.setUrl(url);
generateDetail.setGenerateId(generate.getId()); generateDetail.setGenerateId(generate.getId());
generateDetail.setCreateDate(LocalDateTime.now()); generateDetail.setCreateDate(LocalDateTime.now());
generateDetail.setMd5(md5); generateDetail.setMd5("");
// 将相应的url保存到数据库 // 将相应的url保存到数据库
generateDetailMapper.insert(generateDetail); generateDetailMapper.insert(generateDetail);
log.debug("generateDetail: " + generateDetail.toString());
// String uuid = taskId.substring(0, taskId.substring(0, taskId.lastIndexOf("-")).lastIndexOf("-")); // String uuid = taskId.substring(0, taskId.substring(0, taskId.lastIndexOf("-")).lastIndexOf("-"));
String key = generateResultKey + ":" + taskId; String key = generateResultKey + ":" + taskId;
String imageName = url.substring(url.lastIndexOf("/") + 1); String imageName = url.substring(url.lastIndexOf("/") + 1);
String status = imageName.equals("white_image.jpg") ? "Invalid" : "Success"; status = imageName.equals("white_image.jpg") ? "Invalid" : "Success";
if (StringUtil.isNullOrEmpty(category)) { if (StringUtil.isNullOrEmpty(category)) {
Generate generateRecord = selectByUniqueId(taskId); Generate generateRecord = selectByUniqueId(taskId);
category = generateRecord.getLevel2Type(); category = generateRecord.getLevel2Type();
@@ -326,6 +388,8 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
GenerateResultVO generateResultVO = new GenerateResultVO(taskId, generateDetail.getId(), url, status, category); GenerateResultVO generateResultVO = new GenerateResultVO(taskId, generateDetail.getId(), url, status, category);
// 更新redis // 更新redis
redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
log.debug("generateResultVO: " + generateResultVO.toString());
// 执行积分扣除 // 执行积分扣除
// ** 注:如果生成的图片都是空白 则不扣积分 // ** 注:如果生成的图片都是空白 则不扣积分
@@ -785,8 +849,9 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
long requestEndTime = System.currentTimeMillis(); long requestEndTime = System.currentTimeMillis();
log.info("HTTP请求完成 - 响应状态: {}, 耗时: {}ms, taskId: {}", log.info("HTTP请求完成 - 响应状态: {}, 耗时: {}ms, taskId: {}",
response.code(), (requestEndTime - requestStartTime), taskId); response.code(), (requestEndTime - requestStartTime), taskId);
String result = response.body().string();
if (!response.isSuccessful()) { if (!response.isSuccessful()) {
log.warn("Google API响应失败状态码: {} for taskId: {}", response.code(), taskId); log.warn("Google API响应失败状态码: {} for taskId: {},结果:{}", response.code(), taskId, result);
if (attempt < maxRetries) { if (attempt < maxRetries) {
Thread.sleep(retryDelay * attempt); // 递增延迟 Thread.sleep(retryDelay * attempt); // 递增延迟
continue; continue;
@@ -795,7 +860,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
} }
String result = response.body().string();
// log.info("Google 响应结果:{}", result); // log.info("Google 响应结果:{}", result);
com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result); com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result);
@@ -1065,6 +1130,12 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
String result = response.body().string(); String result = response.body().string();
if (response.code() != 200) {
log.error("Google API 请求失败 - taskId: {}, 尝试: {}, URL: {}, 状态码: {}, 响应结果: {}",
taskId, attempt, endpoint, response.code(), result);
throw new BusinessException("system.error");
}
// log.info("Google 响应结果:{}", result); // log.info("Google 响应结果:{}", result);
com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result); com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result);
@@ -1203,7 +1274,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
* @param modelName advanced high normal * @param modelName advanced high normal
*/ */
private HashMap<String, String> chooseModelAndPrompt(GenerateThroughImageTextDTO generateDTO, String modelName) { private HashMap<String, String> chooseModelAndPrompt(GenerateThroughImageTextDTO generateDTO, String modelName) {
if (StringUtil.isNullOrEmpty(modelName)){ if (StringUtil.isNullOrEmpty(modelName)) {
throw new BusinessException("system error"); throw new BusinessException("system error");
} }
HashMap<String, String> modelAndPromptMap = new HashMap<>(); HashMap<String, String> modelAndPromptMap = new HashMap<>();
@@ -1221,7 +1292,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
String style = generateDTO.getText().substring(0, firstCommaIndex).trim(); String style = generateDTO.getText().substring(0, firstCommaIndex).trim();
String prompt = generateDTO.getText().substring(firstCommaIndex + 1).trim(); String prompt = generateDTO.getText().substring(firstCommaIndex + 1).trim();
prompt = getPrintboardPrompt(style, prompt,modelName); prompt = getPrintboardPrompt(style, prompt, modelName, isUseImage);
modelAndPromptMap.put(ModelConstants.PROMPT, prompt); modelAndPromptMap.put(ModelConstants.PROMPT, prompt);
@@ -1260,8 +1331,31 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
modelAndPromptMap.put(ModelConstants.USE_MODEL, ModelConstants.LOCAL_MODEL); modelAndPromptMap.put(ModelConstants.USE_MODEL, ModelConstants.LOCAL_MODEL);
} }
} else if (ModelConstants.SKETCHBOARD.equals(generateDTO.getLevel1Type())) { } else if (ModelConstants.SKETCHBOARD.equals(generateDTO.getLevel1Type())) {
String prompt = generateDTO.getText() + "rules:front view sketch only,plain white background, single garment only, orthographic, centered on white background, borderless canvas, thin monochrome black line art.\n" + String style = "";
String userPrompt = "";
// 找到第一个逗号的位置
int firstCommaIndex = generateDTO.getText().indexOf(",");
if (firstCommaIndex != -1) {
// 截取第一个逗号前的内容作为style
style = generateDTO.getText().substring(0, firstCommaIndex).trim();
// 截取第一个逗号后的所有内容作为userPrompt去除首尾空格
userPrompt = generateDTO.getText().substring(firstCommaIndex + 1).trim();
if ("Lolita".equals(style)) {
style = "洛丽塔";
}
} else {
// 兼容无逗号的情况style为空全部内容作为userPrompt
userPrompt = generateDTO.getText().trim();
}
String prompt = userPrompt + "rules:front view sketch only,plain white background, single garment only, orthographic, centered on white background, borderless canvas, thin monochrome black line art.\n" +
" No clothes hanger, no fake clothes hanger, no human-related lines, no color fill, no words, no text, no black background, no boundary or frame."; " No clothes hanger, no fake clothes hanger, no human-related lines, no color fill, no words, no text, no black background, no boundary or frame.";
if (!style.trim().isEmpty() && !"all".equalsIgnoreCase(style)) {
prompt += ".sketch style:" + style.trim();
}
modelAndPromptMap.put(ModelConstants.PROMPT, prompt); modelAndPromptMap.put(ModelConstants.PROMPT, prompt);
if (isUseImage) { if (isUseImage) {
if (ModelConstants.ADVANCED.equals(modelName)) { if (ModelConstants.ADVANCED.equals(modelName)) {
@@ -1459,6 +1553,13 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
if (imagePath != null) { if (imagePath != null) {
requestBuilder.image(finalImagePath1); requestBuilder.image(finalImagePath1);
} }
if (useModel.equals(ModelConstants.PRINTBOARD_HIGH_I2I)) {
GenerateImagesRequest.OptimizePromptOptions optimizePromptOptions = new GenerateImagesRequest.OptimizePromptOptions();
optimizePromptOptions.setMode("fast");
requestBuilder.optimizePromptOptions(optimizePromptOptions);
//由于PRINTBOARD_HIGH_I2I与PRINTBOARD_ADVANCED_I2I使用模型一致为了区别积分扣除PRINTBOARD_HIGH_I2I加入了-fast但传入模型时需要去掉-fast用PRINTBOARD_ADVANCED_I2I的常量做替代
requestBuilder.model(ModelConstants.PRINTBOARD_ADVANCED_I2I);
}
// 保存生成记录到数据库 // 保存生成记录到数据库
Generate generate = new Generate( Generate generate = new Generate(
@@ -1570,7 +1671,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
private String getPrintboardPrompt(String style, String userInput, String modelName) { private String getPrintboardPrompt(String style, String userInput, String modelName, boolean isUseImage) {
String systemPrompt = null; String systemPrompt = null;
String prompt; String prompt;
@@ -1596,12 +1697,16 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
"Flat textile pattern printed directly on fabric surface, no three-dimensional objects, no items placed on cloth. \n" + "Flat textile pattern printed directly on fabric surface, no three-dimensional objects, no items placed on cloth. \n" +
"Real style: fabric print, realistic woven/printed pattern, detailed surface pattern only"; "Real style: fabric print, realistic woven/printed pattern, detailed surface pattern only";
} }
}else { } else {
throw new BusinessException("style error:"+ style); throw new BusinessException("style error:" + style);
} }
if (userInput == null || userInput.trim().isEmpty()) { if (userInput == null || userInput.trim().isEmpty()) {
throw new BusinessException("prompt null"); if (isUseImage) {
prompt = "Theme: Image content" + "\nRequirement: " + systemPrompt;
} else {
throw new BusinessException("prompt null");
}
} else { } else {
prompt = "Theme: " + userInput.trim() + "\nRequirement: " + systemPrompt; prompt = "Theme: " + userInput.trim() + "\nRequirement: " + systemPrompt;
} }
@@ -2001,7 +2106,9 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
public Generate selectByUniqueId(String uniqueId) { public Generate selectByUniqueId(String uniqueId) {
QueryWrapper<Generate> qw = new QueryWrapper<>(); QueryWrapper<Generate> qw = new QueryWrapper<>();
qw.eq("unique_id", uniqueId); qw.eq("unique_id", uniqueId);
log.debug("selectByUniqueId: " + uniqueId);
Generate one = getOne(qw);
log.debug("Generate: " + one);
return getOne(qw); return getOne(qw);
} }
@@ -4172,11 +4279,11 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
// 处理不同状态 // 处理不同状态
switch (statusEnum) { switch (statusEnum) {
case TASK_NOT_FOUND: case TASK_NOT_FOUND:
// 审核没过 // 审核没过
case REQUEST_MODERATED: case REQUEST_MODERATED:
// 审核没过 // 审核没过
case CONTENT_MODERATED: case CONTENT_MODERATED:
// 出错 // 出错
case ERROR: case ERROR:
return "Fail"; return "Fail";
case PENDING_F: case PENDING_F:
@@ -4295,7 +4402,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
MotionModeEnum motionModeEnum = MotionModeEnum.of(poseTransformDTO.getMode()); MotionModeEnum motionModeEnum = MotionModeEnum.of(poseTransformDTO.getMode());
switch (motionModeEnum) { switch (motionModeEnum) {
case POSE_TO_VIDEO: case POSE_TO_VIDEO:
params.put("pose_id", poseTransformDTO.getPoseId()); params.put("pose_id", poseTransformDTO.getPoseId().toString());
params.put("image_url", poseTransformDTO.getProductImage()); params.put("image_url", poseTransformDTO.getProductImage());
break; break;
case PROMPT_TO_VIDEO: case PROMPT_TO_VIDEO:

View File

@@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -29,6 +30,20 @@ import java.io.IOException;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.FileOutputStream;
import java.time.format.DateTimeFormatter;
@Service @Service
@Slf4j @Slf4j
@@ -46,7 +61,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
private final RedisUtil redisUtil; private final RedisUtil redisUtil;
@Value("${file.upload.dir:uploads}") @Value("${file.upload.temp.dir}")
private String uploadDir; private String uploadDir;
private static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy/MM"); private static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy/MM");
@@ -128,6 +143,7 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> saveContestant(ContestantDTO request) { public Map<String, Object> saveContestant(ContestantDTO request) {
Map<String,Object> resp = new HashMap<>(); Map<String,Object> resp = new HashMap<>();
if (request.getEmail() == null) { if (request.getEmail() == null) {
@@ -142,26 +158,59 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
if (existing == null) { if (existing == null) {
Contestant toInsert = Contestant.builder() // 通过行锁 + 重试机制保证 contestant_number 在并发下自增分配
.email(request.getEmail()) final int maxAttempts = 5;
.firstName(request.getFirstName()) for (int attempt = 1; attempt <= maxAttempts; attempt++) {
.lastName(request.getLastName()) try {
.gender(request.getGender()) // 获取当前最大 contestant_number 并加行锁LIMIT 1 FOR UPDATE
.occupation(request.getOccupation()) QueryWrapper<Contestant> qMax = new QueryWrapper<>();
.age(request.getAge()) qMax.isNotNull("contestant_number");
.countryRegionCity(request.getCountryRegionCity()) qMax.orderByDesc("contestant_number");
.phoneNumber(request.getPhoneNumber()) qMax.last("LIMIT 1 FOR UPDATE");
.designTitle(request.getDesignTitle()) Contestant last = contestantMapper.selectOne(qMax);
.designDescription(request.getDesignDescription()) Integer nextNumber = (last == null || last.getContestantNumber() == null) ? 10000 : last.getContestantNumber() + 1;
.pdfPath(request.getPdfPath())
.videoPath(request.getVideoPath()) Contestant toInsert = Contestant.builder()
.createdAt(now) .email(request.getEmail())
.updatedAt(now) .firstName(request.getFirstName())
.build(); .lastName(request.getLastName())
contestantMapper.insert(toInsert); .gender(request.getGender())
resp.put("success", true); .occupation(request.getOccupation())
sendSiteMsg(toInsert.getId(), toInsert.getEmail()); .age(request.getAge())
return resp; .countryRegionCity(request.getCountryRegionCity())
.phoneNumber(request.getPhoneNumber())
.designTitle(request.getDesignTitle())
.designDescription(request.getDesignDescription())
.pdfPath(request.getPdfPath())
.videoPath(request.getVideoPath())
.videoDuration(request.getVideoDuration())
.videoSize(request.getVideoSize())
.pdfSize(request.getPdfSize())
.contestantNumber(nextNumber)
.createdAt(now)
.updatedAt(now)
.build();
contestantMapper.insert(toInsert);
resp.put("success", true);
sendSiteMsg(toInsert.getId(), toInsert.getEmail());
return resp;
} catch (Exception e) {
log.warn("Attempt {} to assign contestant_number failed", attempt, e);
String msg = e.getMessage() == null ? "" : e.getMessage().toLowerCase();
if ((msg.contains("duplicate") || msg.contains("uniq_contestant_number") || msg.contains("contestant_number")) && attempt < maxAttempts) {
try {
Thread.sleep(100L);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
continue;
}
throw e;
}
}
throw new BusinessException("Failed to assign contestant number after retries.");
} else { } else {
// update existing contestant // update existing contestant
existing.setFirstName(request.getFirstName()); existing.setFirstName(request.getFirstName());
@@ -175,6 +224,9 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
existing.setDesignDescription(request.getDesignDescription()); existing.setDesignDescription(request.getDesignDescription());
existing.setPdfPath(request.getPdfPath()); existing.setPdfPath(request.getPdfPath());
existing.setVideoPath(request.getVideoPath()); existing.setVideoPath(request.getVideoPath());
existing.setVideoDuration(request.getVideoDuration());
existing.setVideoSize(request.getVideoSize());
existing.setPdfSize(request.getPdfSize());
existing.setUpdatedAt(now); existing.setUpdatedAt(now);
contestantMapper.updateById(existing); contestantMapper.updateById(existing);
resp.put("success", true); resp.put("success", true);
@@ -182,6 +234,134 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
} }
} }
@Override
public byte[] exportContestants() throws Exception {
List<Contestant> list = contestantMapper.selectList(new QueryWrapper<>());
try (XSSFWorkbook workbook = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
Sheet sheet = workbook.createSheet("contestants");
int rowIdx = 0;
Row header = sheet.createRow(rowIdx++);
String[] headers = new String[] {
"contestantNumber", "email", "firstName", "lastName", "gender", "occupation",
"age", "countryRegionCity", "phoneNumber", "designTitle", "designDescription",
"pdfPath", "videoPath", "videoDuration", "videoSizeMB", "pdfSizeMB", "createdAt", "updatedAt"
};
for (int i = 0; i < headers.length; i++) {
Cell c = header.createCell(i);
c.setCellValue(headers[i]);
}
for (Contestant cst : list) {
Row r = sheet.createRow(rowIdx++);
int ci = 0;
r.createCell(ci++).setCellValue(cst.getContestantNumber() == null ? "" : cst.getContestantNumber().toString());
r.createCell(ci++).setCellValue(cst.getEmail() == null ? "" : cst.getEmail());
r.createCell(ci++).setCellValue(cst.getFirstName() == null ? "" : cst.getFirstName());
r.createCell(ci++).setCellValue(cst.getLastName() == null ? "" : cst.getLastName());
r.createCell(ci++).setCellValue(cst.getGender() == null ? "" : cst.getGender());
r.createCell(ci++).setCellValue(cst.getOccupation() == null ? "" : cst.getOccupation());
r.createCell(ci++).setCellValue(cst.getAge() == null ? "" : cst.getAge().toString());
r.createCell(ci++).setCellValue(cst.getCountryRegionCity() == null ? "" : cst.getCountryRegionCity());
r.createCell(ci++).setCellValue(cst.getPhoneNumber() == null ? "" : cst.getPhoneNumber());
r.createCell(ci++).setCellValue(cst.getDesignTitle() == null ? "" : cst.getDesignTitle());
r.createCell(ci++).setCellValue(cst.getDesignDescription() == null ? "" : cst.getDesignDescription());
// r.createCell(ci++).setCellValue(cst.getPdfPath() == null ? "" : cst.getPdfPath());
// r.createCell(ci++).setCellValue(cst.getVideoPath() == null ? "" : cst.getVideoPath());
// 视频时长(秒)
r.createCell(ci++).setCellValue(cst.getVideoDuration() == null ? "" : cst.getVideoDuration().toString());
// 视频大小、PDF 大小:以 MB 导出,保留两位小数
if (cst.getVideoSize() == null) {
r.createCell(ci++).setCellValue("");
} else {
double vMb = cst.getVideoSize() / 1024.0 / 1024.0;
r.createCell(ci++).setCellValue(String.format("%.2f", vMb));
}
if (cst.getPdfSize() == null) {
r.createCell(ci++).setCellValue("");
} else {
double pMb = cst.getPdfSize() / 1024.0 / 1024.0;
r.createCell(ci++).setCellValue(String.format("%.2f", pMb));
}
r.createCell(ci++).setCellValue(cst.getCreatedAt() == null ? "" : cst.getCreatedAt().toString());
r.createCell(ci++).setCellValue(cst.getUpdatedAt() == null ? "" : cst.getUpdatedAt().toString());
}
workbook.write(out);
out.flush();
return out.toByteArray();
} catch (IOException e) {
log.error("export contestants failed", e);
throw e;
}
}
@Override
public void saveContestantsToLocal() throws Exception {
List<Contestant> list = contestantMapper.selectList(new QueryWrapper<>());
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
String ts = LocalDateTime.now().format(fmt);
Path exportDir = Paths.get(uploadDir == null ? "uploads" : uploadDir, "exports");
Files.createDirectories(exportDir);
Path outPath = exportDir.resolve("contestants_" + ts + ".xlsx");
try (XSSFWorkbook workbook = new XSSFWorkbook(); FileOutputStream fos = new FileOutputStream(outPath.toFile())) {
Sheet sheet = workbook.createSheet("contestants");
int rowIdx = 0;
Row header = sheet.createRow(rowIdx++);
String[] headers = new String[] {
"contestantNumber", "email", "firstName", "lastName", "gender", "occupation",
"age", "countryRegionCity", "phoneNumber", "designTitle", "designDescription",
"pdfPath", "videoPath", "videoDuration", "videoSizeMB", "pdfSizeMB", "createdAt", "updatedAt"
};
for (int i = 0; i < headers.length; i++) {
Cell c = header.createCell(i);
c.setCellValue(headers[i]);
}
for (Contestant cst : list) {
Row r = sheet.createRow(rowIdx++);
int ci = 0;
r.createCell(ci++).setCellValue(cst.getContestantNumber() == null ? "" : cst.getContestantNumber().toString());
r.createCell(ci++).setCellValue(cst.getEmail() == null ? "" : cst.getEmail());
r.createCell(ci++).setCellValue(cst.getFirstName() == null ? "" : cst.getFirstName());
r.createCell(ci++).setCellValue(cst.getLastName() == null ? "" : cst.getLastName());
r.createCell(ci++).setCellValue(cst.getGender() == null ? "" : cst.getGender());
r.createCell(ci++).setCellValue(cst.getOccupation() == null ? "" : cst.getOccupation());
r.createCell(ci++).setCellValue(cst.getAge() == null ? "" : cst.getAge().toString());
r.createCell(ci++).setCellValue(cst.getCountryRegionCity() == null ? "" : cst.getCountryRegionCity());
r.createCell(ci++).setCellValue(cst.getPhoneNumber() == null ? "" : cst.getPhoneNumber());
r.createCell(ci++).setCellValue(cst.getDesignTitle() == null ? "" : cst.getDesignTitle());
r.createCell(ci++).setCellValue(cst.getDesignDescription() == null ? "" : cst.getDesignDescription());
// r.createCell(ci++).setCellValue(cst.getPdfPath() == null ? "" : cst.getPdfPath());
// r.createCell(ci++).setCellValue(cst.getVideoPath() == null ? "" : cst.getVideoPath());
// 视频时长(秒)
r.createCell(ci++).setCellValue(cst.getVideoDuration() == null ? "" : cst.getVideoDuration().toString());
// 视频大小、PDF 大小:以 MB 导出,保留两位小数
if (cst.getVideoSize() == null) {
r.createCell(ci++).setCellValue("");
} else {
double vMb = cst.getVideoSize() / 1024.0 / 1024.0;
r.createCell(ci++).setCellValue(String.format("%.2f", vMb));
}
if (cst.getPdfSize() == null) {
r.createCell(ci++).setCellValue("");
} else {
double pMb = cst.getPdfSize() / 1024.0 / 1024.0;
r.createCell(ci++).setCellValue(String.format("%.2f", pMb));
}
r.createCell(ci++).setCellValue(cst.getCreatedAt() == null ? "" : cst.getCreatedAt().toString());
r.createCell(ci++).setCellValue(cst.getUpdatedAt() == null ? "" : cst.getUpdatedAt().toString());
}
workbook.write(fos);
fos.flush();
log.info("Exported contestants to local file: {}", outPath.toString());
} catch (IOException e) {
log.error("save contestants to local failed", e);
throw e;
}
}
@Override @Override
public ContestantDTO getContestantByID(String id) { public ContestantDTO getContestantByID(String id) {
if (id == null) { if (id == null) {
@@ -204,6 +384,9 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
dto.setDesignDescription(existing.getDesignDescription()); dto.setDesignDescription(existing.getDesignDescription());
dto.setPdfPath(existing.getPdfPath()); dto.setPdfPath(existing.getPdfPath());
dto.setVideoPath(existing.getVideoPath()); dto.setVideoPath(existing.getVideoPath());
dto.setVideoDuration(existing.getVideoDuration());
dto.setPdfSize(existing.getPdfSize());
dto.setVideoSize(existing.getVideoSize());
return dto; return dto;
} }
@@ -295,6 +478,111 @@ public class GlobalAwardServiceImpl implements GlobalAwardService {
// 这里推送消息是在接受到视频生成结束后发生的所以UserContext中没有用户信息 // 这里推送消息是在接受到视频生成结束后发生的所以UserContext中没有用户信息
messageCenterService.pushMessage("system", userId); messageCenterService.pushMessage("system", userId);
} }
@Override
public int exportContestantFiles(Integer minContestantNumber, Integer maxContestantNumber) throws Exception {
if (minContestantNumber == null || maxContestantNumber == null) {
throw new BusinessException("minContestantNumber and maxContestantNumber are required.");
}
if (minContestantNumber > maxContestantNumber) {
throw new BusinessException("minContestantNumber cannot be greater than maxContestantNumber.");
}
// 1. 根据contestantNumber范围查询参赛者
QueryWrapper<Contestant> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
.ge(Contestant::getContestantNumber, minContestantNumber)
.le(Contestant::getContestantNumber, maxContestantNumber)
.orderByAsc(Contestant::getContestantNumber);
List<Contestant> contestants = contestantMapper.selectList(queryWrapper);
if (contestants.isEmpty()) {
log.info("No contestants found in range [{}, {}]", minContestantNumber, maxContestantNumber);
return 0;
}
// 2. 创建基础目录
String baseDir = uploadDir + "/contestants";
Path basePath = Paths.get(baseDir).toAbsolutePath();
Files.createDirectories(basePath);
log.info("Base directory created: {}", basePath);
int exportedCount = 0;
// 3. 遍历每个参赛者,下载文件
for (Contestant contestant : contestants) {
Integer contestantNumber = contestant.getContestantNumber();
if (contestantNumber == null) {
log.warn("Contestant {} has no contestantNumber, skipping", contestant.getId());
continue;
}
// 创建参赛者文件夹
String contestantDir = baseDir + "/" + contestantNumber;
Path contestantPath = Paths.get(contestantDir);
Files.createDirectories(contestantPath);
// 下载PDF文件
String pdfPath = contestant.getPdfPath();
if (StringUtils.isNotBlank(pdfPath)) {
try {
String fileName = pdfPath.contains("/") ?
pdfPath.substring(pdfPath.lastIndexOf("/") + 1) : "design.pdf";
downloadFileFromMinio(pdfPath, contestantPath.toString(), "design.pdf");
log.info("Downloaded PDF for contestant {}", fileName);
} catch (Exception e) {
log.error("Failed to download PDF for contestant {}: {}", contestantNumber, e.getMessage());
}
}
// 下载视频文件
String videoPath = contestant.getVideoPath();
if (StringUtils.isNotBlank(videoPath)) {
try {
// 根据路径判断视频格式
String fileName = videoPath.contains("/") ?
videoPath.substring(videoPath.lastIndexOf("/") + 1) : "video.mp4";
downloadFileFromMinio(videoPath, contestantPath.toString(), fileName);
log.info("Downloaded video for contestant {}", contestantNumber);
} catch (Exception e) {
log.error("Failed to download video for contestant {}: {}", contestantNumber, e.getMessage());
}
}
exportedCount++;
}
log.info("Exported {} contestants' files to {}", exportedCount, basePath);
return exportedCount;
}
/**
* 从MinIO下载文件到本地
* @param minioPath MinIO路径 (格式: bucketName/objectPath)
* @param localDir 本地目录
* @param fileName 本地文件名
*/
private void downloadFileFromMinio(String minioPath, String localDir, String fileName) {
if (StringUtils.isBlank(minioPath)) {
return;
}
// 从路径中提取bucket名称和对象名称
int index = minioPath.indexOf("/");
if (index == -1) {
log.warn("Invalid MinIO path: {}", minioPath);
return;
}
String bucketName = minioPath.substring(0, index);
String objectName = minioPath.substring(index + 1);
// 构建本地文件完整路径
Path localFilePath = Paths.get(localDir, fileName);
// 下载文件
minioUtil.downloadMinioObjectToLocal(bucketName, objectName, localFilePath.toString());
}
} }

View File

@@ -28,6 +28,7 @@ import io.netty.util.internal.StringUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -53,7 +54,11 @@ public class LibraryModelPointServiceImpl extends ServiceImpl<LibraryModelPointM
private final PythonTAllInfoService pythonTAllInfoService; private final PythonTAllInfoService pythonTAllInfoService;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public LibraryModelPointVO saveOrEditTemplatePoint(LibraryModelPointDTO libraryModelPointDTO) { public LibraryModelPointVO saveOrEditTemplatePoint(LibraryModelPointDTO libraryModelPointDTO) {
// 参数校验
validateInputParams(libraryModelPointDTO);
LibraryModelPointVO libraryModelPointVO = CopyUtil.copyObject(libraryModelPointDTO, LibraryModelPointVO.class); LibraryModelPointVO libraryModelPointVO = CopyUtil.copyObject(libraryModelPointDTO, LibraryModelPointVO.class);
// 不管是保存还是另存为都需要传模特的libraryId // 不管是保存还是另存为都需要传模特的libraryId
@@ -71,7 +76,8 @@ public class LibraryModelPointServiceImpl extends ServiceImpl<LibraryModelPointM
// 更新模特图片 // 更新模特图片
if (flag) { if (flag) {
libModel.setUrl(url); libModel.setUrl(url);
libModel.setMd5(MD5Utils.encryptFile(minioUtil.getPreSignedUrl(url, CommonConstant.MINIO_IMAGE_EXPIRE_TIME), false)); String preSignedUrl = minioUtil.getPreSignedUrl(url, CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
libModel.setMd5(MD5Utils.encryptFile(preSignedUrl, false));
List<Integer> imagesWidthAndHeight = minioUtil.getImagesWidthAndHeight(url); List<Integer> imagesWidthAndHeight = minioUtil.getImagesWidthAndHeight(url);
libModel.setWidth(imagesWidthAndHeight.get(0)); libModel.setWidth(imagesWidthAndHeight.get(0));
libModel.setHigh(imagesWidthAndHeight.get(1)); libModel.setHigh(imagesWidthAndHeight.get(1));
@@ -104,25 +110,10 @@ public class LibraryModelPointServiceImpl extends ServiceImpl<LibraryModelPointM
} else { } else {
// 不覆盖,即另存为 // 不覆盖,即另存为
// 新增模特library信息 Library saveAsModel = createNewLibraryCopy(libModel, libraryModelPointDTO);
Library saveAsModel = new Library();
saveAsModel.setAccountId(libModel.getAccountId());
saveAsModel.setLevel1Type(libModel.getLevel1Type());
saveAsModel.setLevel2Type(libModel.getLevel2Type());
String ageGroup = StringUtil.isNullOrEmpty(libModel.getLevel3Type()) ? "Adult" : libModel.getLevel3Type();
saveAsModel.setLevel3Type(ageGroup);
saveAsModel.setName(DateUtil.dateToStr(new Date(), DateUtil.YYYY_MM_DD));
saveAsModel.setUrl(url);
saveAsModel.setMd5(MD5Utils.encryptFile(minioUtil.getPreSignedUrl(url, CommonConstant.MINIO_IMAGE_EXPIRE_TIME), false));
List<Integer> imagesWidthAndHeight = minioUtil.getImagesWidthAndHeight(url);
saveAsModel.setWidth(imagesWidthAndHeight.get(0));
saveAsModel.setHigh(imagesWidthAndHeight.get(1));
saveAsModel.setCreateDate(DateUtil.getByTimeZone(libraryModelPointDTO.getTimeZone()));
libraryService.save(saveAsModel);
// 更新新的模特在library中的id,用于后面新建模特点位信息用
libraryModelPointDTO.setLibraryId(saveAsModel.getId());
// 新增模特点位信息 // 新增模特点位信息
libraryModelPointDTO.setLibraryId(saveAsModel.getId()); // 更新libraryId为新创建的模型ID
LibraryModelPoint libraryModelPoint = resolvePoint(libraryModelPointDTO); LibraryModelPoint libraryModelPoint = resolvePoint(libraryModelPointDTO);
libraryModelPoint.setModelType("Library"); libraryModelPoint.setModelType("Library");
libraryModelPoint.setCreateDate(DateUtil.getByTimeZone(libraryModelPointDTO.getTimeZone())); libraryModelPoint.setCreateDate(DateUtil.getByTimeZone(libraryModelPointDTO.getTimeZone()));
@@ -130,22 +121,50 @@ public class LibraryModelPointServiceImpl extends ServiceImpl<LibraryModelPointM
libraryModelPointVO.setTemplateId(libraryModelPoint.getId()); libraryModelPointVO.setTemplateId(libraryModelPoint.getId());
libraryModelPointVO.setRelationId(libraryModelPoint.getRelationId()); libraryModelPointVO.setRelationId(libraryModelPoint.getRelationId());
} }
//编辑
/*if (!StringUtils.isEmpty(libraryModelPointDTO.getModelSex())) {
Library byId = libraryService.getById(libraryModelPointDTO.getLibraryId());
if (!byId.getLevel2Type().equals(libraryModelPointDTO.getModelSex())) {
if (byId.getLevel2Type().equals(Sex.FEMALE.getValue())) {
libraryService.checkModel(Sex.FEMALE.getValue(), Collections.singletonList(byId.getId()), 1);
}else {
libraryService.checkModel(Sex.MALE.getValue(), Collections.singletonList(byId.getId()), 1);
}
byId.setLevel2Type(libraryModelPointDTO.getModelSex());
libraryService.updateById(byId);
}
}*/
return libraryModelPointVO; return libraryModelPointVO;
} }
/**
* 验证输入参数
*/
private void validateInputParams(LibraryModelPointDTO libraryModelPointDTO) {
if (libraryModelPointDTO == null) {
throw new BusinessException("libraryModelPointDTO cannot be null");
}
if (libraryModelPointDTO.getLibraryId() == null || libraryModelPointDTO.getLibraryId() <= 0) {
throw new BusinessException("libraryId is required");
}
if (StringUtils.isEmpty(libraryModelPointDTO.getModelPath())) {
throw new BusinessException("modelPath is required");
}
if (StringUtils.isEmpty(libraryModelPointDTO.getTimeZone())) {
throw new BusinessException("timeZone is required");
}
}
/**
* 创建新的库模型副本
*/
private Library createNewLibraryCopy(Library originalModel, LibraryModelPointDTO libraryModelPointDTO) {
// 新增模特library信息
Library saveAsModel = new Library();
saveAsModel.setAccountId(originalModel.getAccountId());
saveAsModel.setLevel1Type(originalModel.getLevel1Type());
saveAsModel.setLevel2Type(originalModel.getLevel2Type());
String ageGroup = StringUtil.isNullOrEmpty(originalModel.getLevel3Type()) ? "Adult" : originalModel.getLevel3Type();
saveAsModel.setLevel3Type(ageGroup);
saveAsModel.setName(DateUtil.dateToStr(new Date(), DateUtil.YYYY_MM_DD));
saveAsModel.setUrl(libraryModelPointDTO.getModelPath());
String preSignedUrl = minioUtil.getPreSignedUrl(libraryModelPointDTO.getModelPath(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
saveAsModel.setMd5(MD5Utils.encryptFile(preSignedUrl, false));
List<Integer> imagesWidthAndHeight = minioUtil.getImagesWidthAndHeight(libraryModelPointDTO.getModelPath());
saveAsModel.setWidth(imagesWidthAndHeight.get(0));
saveAsModel.setHigh(imagesWidthAndHeight.get(1));
saveAsModel.setCreateDate(DateUtil.getByTimeZone(libraryModelPointDTO.getTimeZone()));
libraryService.save(saveAsModel);
return saveAsModel;
}
@Override @Override
public LibraryModelPointVO saveOrEditTemplatePointOld(LibraryModelPointDTO libraryModelPointDTO) { public LibraryModelPointVO saveOrEditTemplatePointOld(LibraryModelPointDTO libraryModelPointDTO) {
// Library library = libraryService.getById(libraryModelPointDTO.getLibraryId()); // Library library = libraryService.getById(libraryModelPointDTO.getLibraryId());

View File

@@ -31,6 +31,11 @@ public class RabbitMQServiceImpl implements RabbitMQService {
mqPublisher.sendGenerateMessage(message); mqPublisher.sendGenerateMessage(message);
} }
@Override
public void publishMessageToGenerateResult(String message) {
mqPublisher.sendGenerateResultMessage(message);
}
@Override @Override
public void publishMessageToSR(String message) { public void publishMessageToSR(String message) {
mqPublisher.sendSRMessage(message); mqPublisher.sendSRMessage(message);

View File

@@ -1060,11 +1060,12 @@ public class StripeServiceImpl implements StripeService {
String periodEnd = DateUtil.changeTimeStampFormat(subscriptionInfo.getCurrentPeriodEnd(), "seconds", CommonConstant.TIME_FORMAT_yyyy_MM_dd_HH_mm_ss); String periodEnd = DateUtil.changeTimeStampFormat(subscriptionInfo.getCurrentPeriodEnd(), "seconds", CommonConstant.TIME_FORMAT_yyyy_MM_dd_HH_mm_ss);
qwPI.lambda().eq(PaymentInfo::getOrderNo, subscriptionInfo.getOrderNo()) qwPI.lambda().eq(PaymentInfo::getOrderNo, subscriptionInfo.getOrderNo())
.eq(PaymentInfo::getTradeState, "paid")
.between(PaymentInfo::getCreateTime, periodStart, periodEnd) .between(PaymentInfo::getCreateTime, periodStart, periodEnd)
.orderByDesc(PaymentInfo::getId); .orderByDesc(PaymentInfo::getId);
List<PaymentInfo> paymentInfos = paymentInfoMapper.selectList(qwPI); List<PaymentInfo> paymentInfos = paymentInfoMapper.selectList(qwPI);
if (paymentInfos.isEmpty()) { if (paymentInfos.isEmpty()) {
log.info("不发送邮件原因【根据order_no:{},查询到的paymentInfos为空】", orderNo); log.info("不发送邮件原因【根据order_no:{},查询到的成功的paymentInfos为空】", orderNo);
return false; return false;
} }
PaymentInfo paymentInfo = paymentInfos.get(0); PaymentInfo paymentInfo = paymentInfos.get(0);

View File

@@ -1461,12 +1461,16 @@ public class UserLikeGroupServiceImpl extends ServiceImpl<UserLikeGroupMapper, U
if (StringUtil.isNullOrEmpty(fluxResult)) { if (StringUtil.isNullOrEmpty(fluxResult)) {
toProductImageResult.setStatus("Fail"); toProductImageResult.setStatus("Fail");
toProductImageResultMapper.updateById(toProductImageResult); toProductImageResultMapper.updateById(toProductImageResult);
sortRank(toProductImageResult); if (toProductImageResult.getIsLike() != null && toProductImageResult.getIsLike() == 1) {
sortRank(toProductImageResult);
}
results.add(new MagicToolResultVO(taskId, "Fail")); results.add(new MagicToolResultVO(taskId, "Fail"));
} else if (fluxResult.equals("Fail") || fluxResult.equals("Pending")) { } else if (fluxResult.equals("Fail") || fluxResult.equals("Pending")) {
toProductImageResult.setStatus(fluxResult); toProductImageResult.setStatus(fluxResult);
toProductImageResultMapper.updateById(toProductImageResult); toProductImageResultMapper.updateById(toProductImageResult);
sortRank(toProductImageResult); if (fluxResult.equals("Fail") && toProductImageResult.getIsLike() != null && toProductImageResult.getIsLike() == 1) {
sortRank(toProductImageResult);
}
results.add(new MagicToolResultVO(taskId, fluxResult)); results.add(new MagicToolResultVO(taskId, fluxResult));
} else { } else {
results.add(processFluxResult(fluxResult, toProductImageResult, taskId, toProductImageRecord.getPrompt())); results.add(processFluxResult(fluxResult, toProductImageResult, taskId, toProductImageRecord.getPrompt()));

View File

@@ -125,9 +125,9 @@ orderList.link=https://develop.aida.com.hk/home/homePage?order=
# 0 不发送邮件通知 1 发送邮件通知 # 0 不发送邮件通知 1 发送邮件通知
stripe.webhook.fail.reminder=0 stripe.webhook.fail.reminder=0
# kim test # kim test
stripe.paymentMethodConfiguration=pmc_1LywTWH7nPZ8bkrN6FvdCUWG #stripe.paymentMethodConfiguration=pmc_1LywTWH7nPZ8bkrN6FvdCUWG
# developer test # developer test
#stripe.paymentMethodConfiguration=pmc_1QIKyq02n1TEydyNKVEYvhW7 stripe.paymentMethodConfiguration=pmc_1QIKyq02n1TEydyNKVEYvhW7
#thymelea模板配置 #thymelea模板配置
#控制 Thymeleaf 是否启用模板缓存 生产环境用true,以提高性能 #控制 Thymeleaf 是否启用模板缓存 生产环境用true,以提高性能
spring.thymeleaf.cache=false spring.thymeleaf.cache=false
@@ -181,4 +181,4 @@ file.upload.max.size.video=104857600
# 上传任务过期时间(小时) # 上传任务过期时间(小时)
file.upload.task.expiry.hours=24 file.upload.task.expiry.hours=24
global.award.link=https://develop.aida.com.hk/award/contestants?id= global.award.link=https://aida-global-design-awards.com.hk/contestants?id=

View File

@@ -179,4 +179,4 @@ file.upload.max.size.video=104857600
# 上传任务过期时间(小时) # 上传任务过期时间(小时)
file.upload.task.expiry.hours=24 file.upload.task.expiry.hours=24
global.award.link=https://www.aida.com.hk/award/contestants?id= global.award.link=https://aida-global-design-awards.com.hk/contestants?id=

View File

@@ -2,7 +2,7 @@
#spring.profiles.active=test #spring.profiles.active=test
#<23><><EFBFBD><EFBFBD>application-prod<6F>ļ<EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) #<23><><EFBFBD><EFBFBD>application-prod<6F>ļ<EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
#spring.profiles.active=prod spring.profiles.active=prod
#<23><><EFBFBD><EFBFBD>application-dev<65>ļ<EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) #<23><><EFBFBD><EFBFBD>application-dev<65>ļ<EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
spring.profiles.active=dev #spring.profiles.active=dev

View File

@@ -61,10 +61,10 @@
</if> </if>
<!-- 添加时间区间查询条件 --> <!-- 添加时间区间查询条件 -->
<if test="startTime != null and startTime != ''"> <if test="startTime != null and startTime != ''">
AND cd.create_time &gt;= #{startTime} AND create_time &gt;= #{startTime}
</if> </if>
<if test="endTime != null and endTime != ''"> <if test="endTime != null and endTime != ''">
AND cd.create_time &lt;= #{endTime} AND create_time &lt;= #{endTime}
</if> </if>
GROUP BY GROUP BY
account_id account_id

View File

@@ -52,8 +52,10 @@
AND b.create_date between #{startTime} and #{endTime} AND b.create_date between #{startTime} and #{endTime}
</if> </if>
</where> </where>
and b.create_date not like '%:01' <if test="filterBySecond">
and b.create_date not like '%:02' and b.create_date not like '%:01'
and b.create_date not like '%:02'
</if>
<if test="ids != null and ids.size() > 0"> <if test="ids != null and ids.size() > 0">
and a.id in and a.id in
<foreach item="id" collection="ids" open="(" separator="," close=")"> <foreach item="id" collection="ids" open="(" separator="," close=")">

View File

@@ -17,3 +17,5 @@
</mapper> </mapper>

View File

@@ -27,9 +27,9 @@ paypal.webhook_id=1D107312EX592781K
##### Stripe ##### Stripe
# developer # developer
stripe.private-key=sk_test_51P4ZZL02n1TEydyN8qQHjOA9imsFU7Oxs2HMHGy2urHnnQgSHnZuu5vVP6pKhEACwUpsKNyrbZpdcg5TJWJLRHcY008dEO1fn2 #stripe.private-key=sk_test_51P4ZZL02n1TEydyN8qQHjOA9imsFU7Oxs2HMHGy2urHnnQgSHnZuu5vVP6pKhEACwUpsKNyrbZpdcg5TJWJLRHcY008dEO1fn2
# dev 端点 # dev 端点
stripe.webhook-sign-secret=whsec_e0dBiJngx6qqgJj6yPyJ2A9ouh1Cjv5w #stripe.webhook-sign-secret=whsec_e0dBiJngx6qqgJj6yPyJ2A9ouh1Cjv5w
# local 端点 # local 端点
#stripe.webhook-sign-secret=whsec_TJcMSnAkh4uktrNY1M6Iy8XaVze4Rzqm #stripe.webhook-sign-secret=whsec_TJcMSnAkh4uktrNY1M6Iy8XaVze4Rzqm
@@ -43,8 +43,8 @@ stripe.webhook-sign-secret=whsec_e0dBiJngx6qqgJj6yPyJ2A9ouh1Cjv5w
#stripe.webhook-sign-secret=whsec_pX0pPMQm85PaUSWnFMEzoccb3MGNkjoL #stripe.webhook-sign-secret=whsec_pX0pPMQm85PaUSWnFMEzoccb3MGNkjoL
# kim - live # kim - live
#stripe.private-key=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 stripe.private-key=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
# prod 端点 # prod 端点
#stripe.webhook-sign-secret=whsec_hhGDgdelQRHSg4LmChtQe41crj41eb11 stripe.webhook-sign-secret=whsec_hhGDgdelQRHSg4LmChtQe41crj41eb11
# dev 端点 # dev 端点
#stripe.webhook-sign-secret=whsec_cFUtjUOo8wnrIKZmt4GNvt7ZY1bOfrYr #stripe.webhook-sign-secret=whsec_cFUtjUOo8wnrIKZmt4GNvt7ZY1bOfrYr