Compare commits
28 Commits
23716984cc
...
dev/3.1_re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
921d2d956e | ||
|
|
d700f94f9d | ||
|
|
b277479e73 | ||
|
|
83cbd57dea | ||
|
|
4d3b22de82 | ||
|
|
6b5c2cfec0 | ||
|
|
b676de054a | ||
|
|
4c169ef67e | ||
|
|
f2bce066b6 | ||
|
|
6af442eb15 | ||
|
|
768df55309 | ||
|
|
f351277b73 | ||
|
|
a799162ea4 | ||
|
|
c035eb9d7d | ||
|
|
906a54b3c8 | ||
|
|
643799546b | ||
|
|
f582464cd3 | ||
|
|
b864b393bc | ||
|
|
c03a8762e7 | ||
|
|
cb87ad1099 | ||
|
|
fb229764f8 | ||
|
|
8bec1f842d | ||
|
|
b54bd04cff | ||
|
|
b4ccad6242 | ||
|
|
6068bf7d7d | ||
|
|
d36baf747f | ||
| 7c8f1bee6a | |||
|
|
62bd145e2c |
111
.gitea/workflows/develop_3.1_MS_build_manual.yaml
Normal file
111
.gitea/workflows/develop_3.1_MS_build_manual.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
name: 手动 AiDA back-java 开发分支构建部署
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_and_deploy:
|
||||
runs-on: java21
|
||||
|
||||
outputs:
|
||||
build_status: ${{ job.status }}
|
||||
build_url: ${{ gitea.server_url }}/${{ gitea.repository.owner.name }}/${{ gitea.repository.name }}/actions/runs/${{ gitea.run_id }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
REMOTE_DEPLOY_PATH: /workspace/workspace_aida/DevelopVersion/develop-MS-version-aida-back
|
||||
|
||||
steps:
|
||||
- name: 0.记录开始时间
|
||||
id: build_start_time
|
||||
run: echo "current_time=$(TZ='Asia/Hong_Kong' date '+%Y-%m-%d %H:%M:%S %Z')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 1.检出代码
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: dev/3.1_release_merge_MS
|
||||
|
||||
|
||||
- name: 3.缓存 Maven 依赖
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
|
||||
- name: 4.构建项目
|
||||
run: |
|
||||
java -version
|
||||
mvn -v
|
||||
mvn clean package -DskipTests
|
||||
|
||||
- name: 5.生成Dockerfile
|
||||
run: |
|
||||
echo "===== 生成Dockerfile ====="
|
||||
cat > Dockerfile << 'EOF'
|
||||
FROM openjdk:21-ea-21-jdk-slim
|
||||
VOLUME /tmp
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' > /etc/timezone
|
||||
ADD ./target/aida-0.0.1-SNAPSHOT.jar /app.jar
|
||||
ENTRYPOINT ["java","-jar","/app.jar"]
|
||||
EOF
|
||||
echo "Dockerfile内容:"
|
||||
cat Dockerfile
|
||||
|
||||
- name: 6.生成docker-compose.yml
|
||||
run: |
|
||||
echo "===== 生成docker-compose.yml ====="
|
||||
cat > docker-compose.yml << 'EOF'
|
||||
version: '3'
|
||||
services:
|
||||
aida_back:
|
||||
container_name: develop-aida-ms
|
||||
build: .
|
||||
volumes:
|
||||
# 数据挂载
|
||||
- ./log:/log
|
||||
- ./temp:/temp
|
||||
- ./uploads:/temp/uploads
|
||||
ports:
|
||||
- '10092:10092'
|
||||
restart: always
|
||||
EOF
|
||||
# 验证docker-compose.yml生成
|
||||
echo "docker-compose.yml内容:"
|
||||
cat docker-compose.yml
|
||||
|
||||
- name: 7.上传jar到远程服务器
|
||||
uses: appleboy/scp-action@master
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
port: 22
|
||||
username: ${{ secrets.SERVER_USER }}
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
source: "target/*.jar,Dockerfile,docker-compose.yml"
|
||||
target: ${{ env.REMOTE_DEPLOY_PATH }}
|
||||
preserve_host_directory_structure: false
|
||||
|
||||
- name: 8. 重启 Docker 服务
|
||||
uses: appleboy/ssh-action@master # 👈 专门执行命令的 action
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
username: ${{ secrets.SERVER_USER }}
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
key_base64: true
|
||||
script: |
|
||||
echo "========= 进入部署目录 ========="
|
||||
cd ${{ env.REMOTE_DEPLOY_PATH }}
|
||||
ls -l
|
||||
|
||||
echo "========= 停止旧服务 ========="
|
||||
docker compose down
|
||||
|
||||
echo "========= 启动新服务 ========="
|
||||
docker compose up -d --build
|
||||
|
||||
echo "========= 查看运行状态 ========="
|
||||
docker compose ps
|
||||
@@ -103,7 +103,13 @@ jobs:
|
||||
- ./uploads:/temp/uploads
|
||||
ports:
|
||||
- '10090:5567'
|
||||
networks:
|
||||
- aida_java_net
|
||||
restart: always
|
||||
networks:
|
||||
aida_java_net:
|
||||
external: true
|
||||
name: aida_java_net
|
||||
EOF
|
||||
# 验证docker-compose.yml生成
|
||||
echo "docker-compose.yml内容:"
|
||||
|
||||
6
pom.xml
6
pom.xml
@@ -263,6 +263,12 @@
|
||||
<version>2.15.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.13.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.stripe</groupId>
|
||||
<artifactId>stripe-java</artifactId>
|
||||
|
||||
@@ -559,83 +559,83 @@ public class GenerateConsumer {
|
||||
log.info("============ProcessPoseTransformResult End listening==========");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer1(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 1");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer2(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 2");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer3(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 3");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer4(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 4");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer5(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 5");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer6(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 6");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer7(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 7");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer8(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 8");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
@RabbitHandler
|
||||
public void generateConsumer9(Message msg, Channel channel) {
|
||||
generate(msg, channel, "consumer 9");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generateResult}")
|
||||
@RabbitHandler
|
||||
public void getGenerateResult(Message msg, Channel channel) {
|
||||
processGenerateResult(msg, channel);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageResult}")
|
||||
@RabbitHandler
|
||||
public void getToProductImageResult(Message msg, Channel channel) {
|
||||
processToProductImageResult(msg, channel);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.relightResult}")
|
||||
@RabbitHandler
|
||||
public void getRelightResult(Message msg, Channel channel) {
|
||||
processRelightResult(msg, channel);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransform}")
|
||||
@RabbitHandler
|
||||
public void getPoseTransformationResult(Message msg, Channel channel) {
|
||||
processPoseTransformResult(msg, channel);
|
||||
}
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer1(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 1");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer2(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 2");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer3(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 3");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer4(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 4");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer5(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 5");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer6(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 6");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer7(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 7");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer8(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 8");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||
// @RabbitHandler
|
||||
// public void generateConsumer9(Message msg, Channel channel) {
|
||||
// generate(msg, channel, "consumer 9");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generateResult}")
|
||||
// @RabbitHandler
|
||||
// public void getGenerateResult(Message msg, Channel channel) {
|
||||
// processGenerateResult(msg, channel);
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageResult}")
|
||||
// @RabbitHandler
|
||||
// public void getToProductImageResult(Message msg, Channel channel) {
|
||||
// processToProductImageResult(msg, channel);
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.relightResult}")
|
||||
// @RabbitHandler
|
||||
// public void getRelightResult(Message msg, Channel channel) {
|
||||
// processRelightResult(msg, channel);
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransform}")
|
||||
// @RabbitHandler
|
||||
// public void getPoseTransformationResult(Message msg, Channel channel) {
|
||||
// processPoseTransformResult(msg, channel);
|
||||
// }
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.designBatch}")
|
||||
// @RabbitHandler
|
||||
// public void getDesignBatchResult(Message msg, Channel channel) {
|
||||
|
||||
@@ -222,16 +222,16 @@ public class SRConsumer {
|
||||
taskListService.updateTaskStatusOrOutputRedis(uniqueId, "fail", null);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.sr}")
|
||||
@RabbitHandler
|
||||
public void SRConsumer1(Message msg, Channel channel) {
|
||||
superResolution(msg, channel, "consumer 1");
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.srResult}")
|
||||
@RabbitHandler
|
||||
public void SRResultConsumer1(Message msg, Channel channel) {
|
||||
getSRResult(msg, channel, "consumer 1");
|
||||
}
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.sr}")
|
||||
// @RabbitHandler
|
||||
// public void SRConsumer1(Message msg, Channel channel) {
|
||||
// superResolution(msg, channel, "consumer 1");
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = "#{rabbitMQProperties.queues.srResult}")
|
||||
// @RabbitHandler
|
||||
// public void SRResultConsumer1(Message msg, Channel channel) {
|
||||
// getSRResult(msg, channel, "consumer 1");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@ import com.ai.da.common.response.Response;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author: dangweijian
|
||||
@@ -36,6 +38,14 @@ public class ExceptionCatch {
|
||||
return Response.error(e.getCode(), e.getMsg());
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||
@ExceptionHandler(UnauthorizedException.class)
|
||||
public Response<String> unauthorizedExceptionCatch(UnauthorizedException e) {
|
||||
log.error("Unauthorized: {}", e.getMessage());
|
||||
return Response.error(401, e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Response<String> exceptionCatch(Exception e) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ai.da.common.config.exception;
|
||||
|
||||
public class UnauthorizedException extends RuntimeException {
|
||||
|
||||
public UnauthorizedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnauthorizedException() {
|
||||
super("Gateway token verification failed");
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ public class CommonConstant {
|
||||
// 单位 秒 两天过期
|
||||
public static final Long CREDITS_EXPIRE_TIME = 2 * 24 * 60 * 60L;
|
||||
// 单位 分钟
|
||||
public static final Integer MINIO_IMAGE_EXPIRE_TIME = 24 * 60;
|
||||
public static final Integer MINIO_IMAGE_EXPIRE_TIME = 24 * 60 * 7;
|
||||
// 单位 秒 一天过期 in redis
|
||||
public static final Long GENERATE_RESULT_EXPIRE_TIME = 24 * 60 * 60L;
|
||||
// 单位 秒 7天过期
|
||||
|
||||
@@ -18,8 +18,8 @@ public class ModelConstants {
|
||||
|
||||
// 模型名称常量
|
||||
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 PRINTBOARD_HIGH_T2I = "doubao-seedream-3-0-t2i-250415";
|
||||
public static final String MOODBOARD_ADVANCED = "doubao-seedream-4-5-251128";
|
||||
public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-4-0-250828-high";
|
||||
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 IMAGEN_MODEL = "imagen-4.0-generate-001";
|
||||
|
||||
@@ -3,17 +3,39 @@ package com.ai.da.common.context;
|
||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||
|
||||
public class UserContext {
|
||||
private static ThreadLocal<AuthPrincipalVo> userHolder = new ThreadLocal<AuthPrincipalVo>();
|
||||
private static final ThreadLocal<AuthPrincipalVo> userHolder = new ThreadLocal<>();
|
||||
|
||||
public static void setUserHolder(AuthPrincipalVo authPrincipalVo) {
|
||||
userHolder.set(authPrincipalVo);
|
||||
}
|
||||
|
||||
public static AuthPrincipalVo getUserHolder() {
|
||||
return userHolder.get();
|
||||
AuthPrincipalVo holder = userHolder.get();
|
||||
if (holder == null) {
|
||||
throw new RuntimeException("User not authenticated");
|
||||
}
|
||||
if (!"AIDA".equals(holder.getSource())) {
|
||||
throw new RuntimeException("Access denied: source must be AIDA");
|
||||
}
|
||||
return holder;
|
||||
}
|
||||
|
||||
public static void delete() {
|
||||
userHolder.remove();
|
||||
}
|
||||
|
||||
public static void setUserHolder(AuthPrincipalVo authPrincipalVo) {
|
||||
userHolder.set(authPrincipalVo);
|
||||
public static Long getUserId() {
|
||||
return getUserHolder().getId();
|
||||
}
|
||||
|
||||
public static Long getBuyerId() {
|
||||
AuthPrincipalVo holder = userHolder.get();
|
||||
if (holder == null) {
|
||||
throw new RuntimeException("User not authenticated");
|
||||
}
|
||||
if (!"BUYER".equals(holder.getSource())) {
|
||||
throw new RuntimeException("Access denied: source must be BUYER");
|
||||
}
|
||||
return holder.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class AccountTask {
|
||||
* 每个月月初只刷新教育子账号的积分
|
||||
*/
|
||||
// @Scheduled(cron = "0 25 14 * * ?")
|
||||
@Scheduled(cron = "0 0 0 1 * ?")
|
||||
// @Scheduled(cron = "0 0 0 1 * ?")
|
||||
public void refreshCreditsMonthly() {
|
||||
log.info("每月1号0点 重置教育版子账号为默认积分");
|
||||
accountService.refreshCreditsMonthly();
|
||||
@@ -54,7 +54,7 @@ public class AccountTask {
|
||||
}*/
|
||||
|
||||
// 每天检测正式用户到期情况,每天凌晨0点执行
|
||||
@Scheduled(cron = "0 0 0 * * ?")
|
||||
// @Scheduled(cron = "0 0 0 * * ?")
|
||||
public void paidUserToVisitor() {
|
||||
// 1、查询当前已过期正式用户或试用用户
|
||||
List<Account> accountList = accountService.getExpiredUserBySystemUser(1);
|
||||
@@ -77,7 +77,7 @@ public class AccountTask {
|
||||
accountService.registerUserToVisitor();
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 0 0 1 * ?")
|
||||
// @Scheduled(cron = "0 0 0 1 * ?")
|
||||
// 每月初刷新所有用户用户名剩余修改次数
|
||||
public void resetUsernameModifyTimes(){
|
||||
log.info("重置所有用户的用户名修改次数");
|
||||
@@ -85,17 +85,17 @@ public class AccountTask {
|
||||
}
|
||||
|
||||
// @Scheduled(cron = "0 35 14 * * ?")
|
||||
@Scheduled(cron = "0 5 0 * * ?")
|
||||
// @Scheduled(cron = "0 5 0 * * ?")
|
||||
public void checkEduAdminExpireStatus() {
|
||||
accountService.checkEduAdminExpireStatus();
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 5 0 * * ?")
|
||||
// @Scheduled(cron = "0 5 0 * * ?")
|
||||
public void activeSubscriptionPlan() {
|
||||
subscriptionPlanService.activeSubscriptionPlan(null);
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||
public void expireSubscription() {
|
||||
subscriptionPlanService.expireSubscription();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class GenerateTask {
|
||||
* 故这里通过定时任务做补偿
|
||||
* flux五分钟查询一次,万相1小时查询一次
|
||||
*/
|
||||
@Scheduled(cron = "0 */4 * * * ?")
|
||||
// @Scheduled(cron = "0 */4 * * * ?")
|
||||
public void fluxCompensationMechanism(){
|
||||
// 1、查所有 任务还没成功、还没失败,正在等待或者执行中的任务id有哪些
|
||||
// (由于获取结果的polling_url在redis中只存一天,大部分结果超过一天之后就无法再找到任务,小部分可以通过公共路径查到结果)
|
||||
@@ -98,7 +98,7 @@ public class GenerateTask {
|
||||
}
|
||||
|
||||
// 万相 -> pose transformation 补偿 当前任务执行完后,5分钟再执行一次(不会出现任务重叠的情况)
|
||||
@Scheduled(fixedDelay = 5 * 60 * 1000)
|
||||
// @Scheduled(fixedDelay = 5 * 60 * 1000)
|
||||
public void wxCompensationMechanism(){
|
||||
List<APIGenerate> apiGenerates = apiGenerateService.getPendingTaskByStatus("wx");
|
||||
if (apiGenerates != null && !apiGenerates.isEmpty()){
|
||||
|
||||
@@ -104,7 +104,7 @@ public class PaymentTask {
|
||||
}
|
||||
|
||||
// 定时同步(每分钟一次)
|
||||
@Scheduled(fixedRate = 60000)
|
||||
// @Scheduled(fixedRate = 60000)
|
||||
public void syncLinkViewCountToDB(){
|
||||
affiliateService.syncLinkViewCountToDB();
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public class PaymentTask {
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||
public void calcCouponsCommission(){
|
||||
// log.info("优惠券佣金计算定时器");
|
||||
affiliateService.calcCouponsCommission();
|
||||
|
||||
@@ -14,6 +14,7 @@ import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -41,6 +42,9 @@ public class MinioUtil {
|
||||
@Autowired
|
||||
private MinioClient minioClient;
|
||||
|
||||
@Value("${minio.endpoint}")
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 获取MinIO客户端实例
|
||||
*/
|
||||
@@ -48,6 +52,18 @@ public class MinioUtil {
|
||||
return minioClient;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
/**
|
||||
* Redis缓存key前缀,用于Minio签名URL缓存
|
||||
*/
|
||||
private static final String REDIS_MINIO_URL_PREFIX = "minio:url:";
|
||||
|
||||
/**
|
||||
* 签名URL缓存过期时间(秒),默认1天
|
||||
*/
|
||||
private static final long URL_CACHE_EXPIRE_SECONDS = 24 * 60 * 60;
|
||||
/**
|
||||
* description: 判断bucket是否存在,不存在则创建
|
||||
*
|
||||
@@ -388,6 +404,11 @@ public class MinioUtil {
|
||||
* @return 文件的临时URL,如果出现异常则返回null
|
||||
*/
|
||||
public String getPreSignedUrl(String bucketName, String fileName, int expiry) {
|
||||
String cacheKey = REDIS_MINIO_URL_PREFIX + bucketName + "/" + fileName;
|
||||
Object cachedUrl = redisUtil.getFromString(cacheKey);
|
||||
if (cachedUrl != null) {
|
||||
return cachedUrl.toString();
|
||||
}
|
||||
try {
|
||||
|
||||
String lowerName = fileName.toLowerCase();
|
||||
@@ -415,8 +436,9 @@ public class MinioUtil {
|
||||
|
||||
builder.extraQueryParams(queryParams);
|
||||
}
|
||||
|
||||
return minioClient.getPresignedObjectUrl(builder.build());
|
||||
String presignedObjectUrl = minioClient.getPresignedObjectUrl(builder.build());
|
||||
redisUtil.addToString(cacheKey, presignedObjectUrl, URL_CACHE_EXPIRE_SECONDS);
|
||||
return presignedObjectUrl;
|
||||
} catch (MinioException | InvalidKeyException
|
||||
| IOException | NoSuchAlgorithmException | IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
@@ -958,6 +980,166 @@ public class MinioUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测字符串是否为预签名URL
|
||||
* 通过检查URL中是否包含minio endpoint来判断
|
||||
*
|
||||
* @param str 待检测的字符串
|
||||
* @return true表示是预签名URL,false表示不是
|
||||
*/
|
||||
public boolean isPresignedUrl(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// 检查字符串是否是一个有效的URL
|
||||
URL url = new URL(str);
|
||||
String host = url.getHost();
|
||||
// 获取endpoint中的主机部分(去掉http://或https://)
|
||||
String endpointHost = endpoint;
|
||||
if (endpointHost.startsWith("http://")) {
|
||||
endpointHost = endpointHost.substring(7);
|
||||
} else if (endpointHost.startsWith("https://")) {
|
||||
endpointHost = endpointHost.substring(8);
|
||||
}
|
||||
// 去掉端口号
|
||||
if (endpointHost.contains(":")) {
|
||||
endpointHost = endpointHost.substring(0, endpointHost.indexOf(":"));
|
||||
}
|
||||
// 检查URL的host是否与endpoint的host匹配
|
||||
return host.equals(endpointHost);
|
||||
} catch (Exception e) {
|
||||
// 不是有效的URL
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测字符串是否为MinIO逻辑路径(bucketName/objectName格式)
|
||||
* 逻辑路径特点:
|
||||
* 1. 包含 "/"(桶名和对象名之间的分隔符)
|
||||
* 2. 不是完整的URL(不以http://或https://开头)
|
||||
* 3. 路径中没有查询参数
|
||||
*
|
||||
* @param str 待检测的字符串
|
||||
* @return true表示是MinIO逻辑路径,false表示不是
|
||||
*/
|
||||
public boolean isMinioLogicalPath(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
// 必须是字符串
|
||||
if (!(str instanceof String)) {
|
||||
return false;
|
||||
}
|
||||
String trimStr = str.trim();
|
||||
// 不应该以http://或https://开头
|
||||
if (trimStr.startsWith("http://") || trimStr.startsWith("https://")) {
|
||||
return false;
|
||||
}
|
||||
// 应该包含 "/"(bucket/object格式)
|
||||
if (!trimStr.contains("/")) {
|
||||
return false;
|
||||
}
|
||||
// 不应该包含空格或特殊字符
|
||||
if (trimStr.contains(" ") || trimStr.contains("\n") || trimStr.contains("\t")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将预签名URL转换为逻辑路径
|
||||
*
|
||||
* @param presignedUrl 预签名URL
|
||||
* @return 逻辑路径(格式:bucketName/objectName)
|
||||
*/
|
||||
public String getLogicalPathFromPresignedUrl(String presignedUrl) {
|
||||
try {
|
||||
// 解析URL
|
||||
URL url = new URL(presignedUrl);
|
||||
|
||||
// 获取路径部分(去掉开头的/)
|
||||
String path = url.getPath();
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
// 路径格式为 bucketName/objectName
|
||||
// Minio路径中可能包含多个/,需要正确分割
|
||||
int firstSlashIndex = path.indexOf("/");
|
||||
if (firstSlashIndex <= 0) {
|
||||
throw new MinioException("预签名URL路径格式无效,应包含桶名和对象名: " + presignedUrl);
|
||||
}
|
||||
|
||||
String bucketName = path.substring(0, firstSlashIndex);
|
||||
String objectName = path.substring(firstSlashIndex + 1);
|
||||
|
||||
// log.info("预签名URL转换成功,桶名: {}, 对象名: {}", bucketName, objectName);
|
||||
return bucketName + "/" + objectName;
|
||||
} catch (Exception e) {
|
||||
log.error("预签名URL解析失败: {}", e.getMessage(), e);
|
||||
throw new BusinessException("system.error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理MinIO资源(预签名URL或逻辑路径),统一生成预签名URL
|
||||
*
|
||||
* @param resource 预签名URL或逻辑路径
|
||||
* @param expires 过期时间(秒)
|
||||
* @return 新的预签名URL
|
||||
*/
|
||||
public String processMinioResource(String resource, int expires) {
|
||||
try {
|
||||
String logicalPath;
|
||||
if (isPresignedUrl(resource)) {
|
||||
// 是预签名URL,解析为逻辑路径
|
||||
logicalPath = getLogicalPathFromPresignedUrl(resource);
|
||||
} else if (isMinioLogicalPath(resource)) {
|
||||
// 本身就是逻辑路径
|
||||
logicalPath = resource.trim();
|
||||
} else {
|
||||
// 不认识的内容,直接返回原始值
|
||||
log.warn("未识别的MinIO资源格式: {}", resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
// 统一生成预签名URL
|
||||
return getPreSignedUrl(logicalPath, expires);
|
||||
} catch (Exception e) {
|
||||
log.error("处理MinIO资源失败: {}, error: {}", resource, e.getMessage(), e);
|
||||
// 如果失败,返回原始内容
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任意MinIO URL转换为逻辑路径
|
||||
* 检测URL类型并转换为逻辑路径返回
|
||||
*
|
||||
* @param url 预签名URL或逻辑路径
|
||||
* @return 逻辑路径(格式:bucketName/objectName)
|
||||
* @throws MinioException 如果不是有效的MinIO资源
|
||||
*/
|
||||
public String convertToLogicalPath(String url) {
|
||||
if (url == null || url.isEmpty()) {
|
||||
throw new BusinessException("url.cannot.be.empty");
|
||||
}
|
||||
if (isMinioLogicalPath(url)) {
|
||||
// 本身就是逻辑路径,直接返回
|
||||
return url.trim();
|
||||
} else if (isPresignedUrl(url)) {
|
||||
// 是预签名URL,转换为逻辑路径
|
||||
return getLogicalPathFromPresignedUrl(url);
|
||||
} else {
|
||||
// 不认识的内容,抛出异常
|
||||
throw new BusinessException("无法识别的MinIO资源格式: " + url + ",请提供有效的预签名URL或逻辑路径");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public class PythonService {
|
||||
@Value("${access.python.generate_sr_port}")
|
||||
private String srServicePort;
|
||||
|
||||
@Value("${design.callback.url}")
|
||||
@Value("${design.callback.url.aida}")
|
||||
private String callbackUrl;
|
||||
|
||||
@Resource
|
||||
|
||||
37
src/main/java/com/ai/da/seller/DesignUrlsDTO.java
Normal file
37
src/main/java/com/ai/da/seller/DesignUrlsDTO.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.ai.da.seller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 设计URLs DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "设计URLs数据传输对象")
|
||||
public class DesignUrlsDTO {
|
||||
|
||||
/**
|
||||
* 设计项ID
|
||||
*/
|
||||
@Schema(description = "设计项ID", example = "1")
|
||||
private Long designItemId;
|
||||
|
||||
/**
|
||||
* TO_PRODUCT_IMAGE类型的URL列表
|
||||
*/
|
||||
@Schema(description = "TO_PRODUCT_IMAGE类型的URL列表")
|
||||
private List<String> toProductImageUrls;
|
||||
|
||||
/**
|
||||
* DesignItemDetail的path列表
|
||||
*/
|
||||
@Schema(description = "DesignItemDetail的path列表")
|
||||
private List<String> clothes;
|
||||
|
||||
/**
|
||||
* 姿势转换视频信息列表
|
||||
*/
|
||||
@Schema(description = "姿势转换视频信息列表")
|
||||
private List<PoseTransformationVideoDTO> videos;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ai.da.seller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 姿势转换视频信息DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "姿势转换视频信息数据传输对象")
|
||||
public class PoseTransformationVideoDTO {
|
||||
|
||||
/**
|
||||
* GIF第一帧截图URL
|
||||
*/
|
||||
@Schema(description = "GIF第一帧截图URL")
|
||||
private String firstFrameUrl;
|
||||
|
||||
/**
|
||||
* GIF视频URL
|
||||
*/
|
||||
@Schema(description = "GIF视频URL")
|
||||
private String gifUrl;
|
||||
|
||||
/**
|
||||
* 视频URL
|
||||
*/
|
||||
@Schema(description = "视频URL")
|
||||
private String videoUrl;
|
||||
}
|
||||
44
src/main/java/com/ai/da/seller/SellerController.java
Normal file
44
src/main/java/com/ai/da/seller/SellerController.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.ai.da.seller;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.service.UserLikeGroupService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Seller Controller
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/seller")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "Seller", description = "Seller相关接口")
|
||||
public class SellerController {
|
||||
|
||||
private final UserLikeGroupService userLikeGroupService;
|
||||
|
||||
/**
|
||||
* 根据designItemId列表获取设计相关的URL列表
|
||||
* @param designItemIds designItemId列表
|
||||
* @return 设计URLs DTO列表
|
||||
*/
|
||||
@GetMapping("/sketchDetail")
|
||||
@Operation(summary = "获取设计相关URL列表", description = "根据designItemId列表获取设计相关的URL列表,包括TO_PRODUCT_IMAGE类型的URL和DesignItemDetail的path列表")
|
||||
public Response<List<DesignUrlsDTO>> getDesignUrlsByDesignItemIds(
|
||||
@Parameter(description = "设计项ID列表", required = true, example = "1,2,3")
|
||||
@RequestParam List<Long> designItemIds) {
|
||||
List<DesignUrlsDTO> designUrlsDTOList = new ArrayList<>();
|
||||
for (Long designItemId : designItemIds) {
|
||||
DesignUrlsDTO designUrlsDTO = userLikeGroupService.getToProductImageUrlsByDesignItemId(designItemId);
|
||||
designUrlsDTOList.add(designUrlsDTO);
|
||||
}
|
||||
return Response.success(designUrlsDTOList);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.mapper.primary.entity.*;
|
||||
import com.ai.da.model.dto.*;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.ai.da.seller.DesignUrlsDTO;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
@@ -121,4 +122,11 @@ public interface UserLikeGroupService extends IService<UserLikeGroup> {
|
||||
Boolean toProductImageElementDelete(Long id);
|
||||
|
||||
ToProductElementVO convertRelightElement(Long id);
|
||||
|
||||
/**
|
||||
* 根据designItemId获取TO_PRODUCT_IMAGE类型的URL列表和DesignItemDetail的path列表
|
||||
* @param designItemId designItemId
|
||||
* @return 包含TO_PRODUCT_IMAGE类型的URL列表和DesignItemDetail的path列表的对象
|
||||
*/
|
||||
DesignUrlsDTO getToProductImageUrlsByDesignItemId(Long designItemId);
|
||||
}
|
||||
|
||||
@@ -358,6 +358,8 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
principal.setUsername(account.getUserName());
|
||||
principal.setLanguage(account.getLanguage());
|
||||
principal.setCountry(account.getCountry());
|
||||
//区分买家端登录
|
||||
principal.setSource("AIDA");
|
||||
String token2 = tokenGenerateUtils.createToken(principal);
|
||||
// 本地 JVM 缓存(适配旧逻辑)
|
||||
LocalCacheUtils.setTokenCache(String.valueOf(account.getId()), token2);
|
||||
|
||||
@@ -1553,11 +1553,11 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
if (imagePath != null) {
|
||||
requestBuilder.image(finalImagePath1);
|
||||
}
|
||||
if (useModel.equals(ModelConstants.PRINTBOARD_HIGH_I2I)) {
|
||||
if (useModel.equals(ModelConstants.PRINTBOARD_HIGH_I2I)|| useModel.equals(ModelConstants.PRINTBOARD_HIGH_T2I)) {
|
||||
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的常量做替代
|
||||
//由于PRINTBOARD_HIGH_T2I,PRINTBOARD_HIGH_I2I与PRINTBOARD_ADVANCED_I2I使用模型一致,为了区别积分扣除,PRINTBOARD_HIGH_I2I加入了-fast或者-high,但传入模型时需要去掉-fast或者-high,用PRINTBOARD_ADVANCED_I2I的常量做替代
|
||||
requestBuilder.model(ModelConstants.PRINTBOARD_ADVANCED_I2I);
|
||||
}
|
||||
|
||||
@@ -4225,8 +4225,11 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
||||
}
|
||||
|
||||
// 发送POST请求到Flux API
|
||||
long start = System.currentTimeMillis();
|
||||
String resp = sendRequestUtil.sendFluxPost(fluxRequestUrl, requestBody.toString());
|
||||
JSONObject respObj = JSONUtil.parseObj(resp);
|
||||
long end = System.currentTimeMillis();
|
||||
log.info("flux 耗时:{}ms", end - start);
|
||||
log.info("flux 发起生成请求返回结果: {}", respObj);
|
||||
|
||||
// 从响应中提取任务ID
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.ai.da.model.enums.Module;
|
||||
import com.ai.da.model.vo.*;
|
||||
import com.ai.da.python.PythonService;
|
||||
import com.ai.da.service.*;
|
||||
import com.ai.da.seller.DesignUrlsDTO;
|
||||
import com.ai.da.seller.PoseTransformationVideoDTO;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@@ -31,6 +33,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@@ -61,6 +64,8 @@ import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ai.da.common.enums.LayersPriorityEnum.BODY;
|
||||
|
||||
/**
|
||||
* 服务实现类
|
||||
*
|
||||
@@ -71,6 +76,89 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserLikeGroupServiceImpl extends ServiceImpl<UserLikeGroupMapper, UserLikeGroup> implements UserLikeGroupService {
|
||||
|
||||
/**
|
||||
* 根据CollectionSort ID查询子记录,将TO_PRODUCT_IMAGE类型的URL和姿势转换视频信息写入DesignUrlsDTO
|
||||
* @param collectionSortId CollectionSort ID
|
||||
* @param designUrlsDTO DesignUrlsDTO,用于收集图片URL和视频信息
|
||||
*/
|
||||
private void getToProductImageUrlsByCollectionSortId(Long collectionSortId, DesignUrlsDTO designUrlsDTO) {
|
||||
// 查询子记录中的TO_PRODUCT_IMAGE类型
|
||||
QueryWrapper<CollectionSort> childCollectionQw = new QueryWrapper<>();
|
||||
childCollectionQw.lambda().eq(CollectionSort::getParentId, collectionSortId);
|
||||
childCollectionQw.lambda().in(CollectionSort::getRelationType, CollectionType.TO_PRODUCT_IMAGE.getValue(), CollectionType.RELIGHT.getValue(), CollectionType.POSE_TRANSFORM.getValue());
|
||||
childCollectionQw.lambda().orderByAsc(CollectionSort::getSort);
|
||||
List<CollectionSort> childSortList = collectionSortMapper.selectList(childCollectionQw);
|
||||
|
||||
for (CollectionSort userLikeSort : childSortList) {
|
||||
if (userLikeSort.getRelationType().equals(CollectionType.POSE_TRANSFORM.getValue())){
|
||||
PoseTransformation poseTransformation = poseTransformationMapper.selectById(userLikeSort.getRelationId());
|
||||
if (poseTransformation != null) {
|
||||
PoseTransformationVideoDTO videoDTO = new PoseTransformationVideoDTO();
|
||||
videoDTO.setFirstFrameUrl(minioUtil.processMinioResource(poseTransformation.getFirstFrameUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
videoDTO.setGifUrl(minioUtil.processMinioResource(poseTransformation.getGifUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
videoDTO.setVideoUrl(minioUtil.processMinioResource(poseTransformation.getVideoUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
designUrlsDTO.getVideos().add(videoDTO);
|
||||
}
|
||||
}else {
|
||||
ToProductImageResult toProductImageResult = toProductImageResultMapper.selectById(userLikeSort.getRelationId());
|
||||
if (toProductImageResult != null && !isGenerateTaskFailed(toProductImageResult.getStatus(), toProductImageResult.getCreateTime())) {
|
||||
String url = toProductImageResult.getUrl();
|
||||
designUrlsDTO.getToProductImageUrls().add(minioUtil.processMinioResource(url, CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据designItemId获取TO_PRODUCT_IMAGE类型的URL列表和DesignItemDetail的path列表
|
||||
* @param designItemId designItemId
|
||||
* @return 包含TO_PRODUCT_IMAGE类型的URL列表和DesignItemDetail的path列表的对象
|
||||
*/
|
||||
public DesignUrlsDTO getToProductImageUrlsByDesignItemId(Long designItemId) {
|
||||
DesignUrlsDTO designUrlsDTO = new DesignUrlsDTO();
|
||||
designUrlsDTO.setDesignItemId(designItemId);
|
||||
designUrlsDTO.setVideos(new ArrayList<>());
|
||||
designUrlsDTO.setToProductImageUrls(new ArrayList<>());
|
||||
designUrlsDTO.setClothes(new ArrayList<>());
|
||||
|
||||
// 根据designItemId查询UserLike
|
||||
QueryWrapper<UserLike> userLikeQueryWrapper = new QueryWrapper<>();
|
||||
userLikeQueryWrapper.lambda().eq(UserLike::getDesignItemId, designItemId);
|
||||
UserLike userLike = userLikeMapper.selectOne(userLikeQueryWrapper);
|
||||
|
||||
if (userLike != null) {
|
||||
// 根据UserLike的ID查询CollectionSort
|
||||
QueryWrapper<CollectionSort> collectionSortQueryWrapper = new QueryWrapper<>();
|
||||
collectionSortQueryWrapper.lambda().eq(CollectionSort::getRelationId, userLike.getId());
|
||||
collectionSortQueryWrapper.lambda().eq(CollectionSort::getRelationType, CollectionType.DESIGN.getValue());
|
||||
CollectionSort collectionSort = collectionSortMapper.selectOne(collectionSortQueryWrapper);
|
||||
|
||||
if (collectionSort != null) {
|
||||
// 获取TO_PRODUCT_IMAGE类型的URL列表
|
||||
getToProductImageUrlsByCollectionSortId(collectionSort.getId(), designUrlsDTO);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询DesignItemDetail表,排除type为"Body"的数据
|
||||
QueryWrapper<DesignItemDetail> designItemDetailQueryWrapper = new QueryWrapper<>();
|
||||
designItemDetailQueryWrapper.lambda().eq(DesignItemDetail::getDesignItemId, designItemId);
|
||||
designItemDetailQueryWrapper.lambda().ne(DesignItemDetail::getType, BODY.getType());
|
||||
List<DesignItemDetail> designItemDetails = designItemDetailMapper.selectList(designItemDetailQueryWrapper);
|
||||
|
||||
for (DesignItemDetail designItemDetail : designItemDetails) {
|
||||
// 判断当前用户是否是DesignItemDetail的创建者
|
||||
if (!Objects.equals(designItemDetail.getAccountId(), UserContext.getUserHolder().getId())){
|
||||
throw new BusinessException("unknown.authentication.operation.type");
|
||||
}
|
||||
if (designItemDetail.getPath() != null) {
|
||||
designUrlsDTO.getClothes().add(minioUtil.processMinioResource(designItemDetail.getPath(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
|
||||
}
|
||||
}
|
||||
|
||||
return designUrlsDTO;
|
||||
}
|
||||
|
||||
private final UserLikeGroupMapper userLikeGroupMapper;
|
||||
private final AccountMapper accountMapper;
|
||||
private final CollectionService collectionService;
|
||||
@@ -87,6 +175,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl<UserLikeGroupMapper, U
|
||||
private final PortfolioMapper portfolioMapper;
|
||||
private final TagsMapper tagsMapper;
|
||||
private final DesignItemDetailService designItemDetailService;
|
||||
private final DesignItemDetailMapper designItemDetailMapper;
|
||||
private final CollectionElementMapper collectionElementMapper;
|
||||
private final AttributeRetrievalMapper attributeRetrievalMapper;
|
||||
private final ProductImageAttributeMapper productImageAttributeMapper;
|
||||
|
||||
@@ -547,7 +547,7 @@ public class UploadServiceImpl implements UploadService {
|
||||
/**
|
||||
* 清理过期上传任务(每小时执行一次)
|
||||
*/
|
||||
@Scheduled(fixedDelay = 3600000) // 1小时
|
||||
// @Scheduled(fixedDelay = 3600000) // 1小时
|
||||
public void cleanupExpiredUploads() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
uploadTasks.entrySet().removeIf(entry -> {
|
||||
|
||||
@@ -5,28 +5,12 @@
|
||||
# ============================================================
|
||||
|
||||
server:
|
||||
port: 5567
|
||||
port: 10092
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: aida-back
|
||||
|
||||
# ---------- 副数据源(back 私有,由 Nacos 统一管理) ----------
|
||||
|
||||
# ---------- Token 生成参数(由 TokenGenerateUtils 使用) ----------
|
||||
security:
|
||||
jwtSecret: JWTSECRET
|
||||
jwtTokenHeader: Authorization
|
||||
jwtTokenPrefix: Bearer-
|
||||
jwtExpiration: 8640000000
|
||||
|
||||
# ---------- Python 服务 ----------
|
||||
access:
|
||||
python:
|
||||
ip: http://18.167.251.121
|
||||
port: 9994
|
||||
generate_sr_port: 9994
|
||||
address: http://18.167.251.121:9994
|
||||
|
||||
# ---------- MinIO Buckets ----------
|
||||
minio:
|
||||
@@ -101,10 +85,6 @@ google:
|
||||
redirect:
|
||||
uri: https://develop.api.aida.com.hk/api/third/party/auth/google_callback
|
||||
|
||||
design:
|
||||
callback:
|
||||
url: https://darkish-copied-sprinkler.ngrok-free.dev/api/third/party/receiveDesignResults
|
||||
|
||||
redirect:
|
||||
url: http://18.167.251.121:7788
|
||||
|
||||
|
||||
@@ -4,18 +4,31 @@
|
||||
# 示例:docker run -e NACOS_NAMESPACE=prod ...
|
||||
# ============================================================
|
||||
|
||||
nacos:
|
||||
namespace: dev
|
||||
host: 18.167.251.121:28848
|
||||
username: nacos
|
||||
password: Aidlab123123!
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: aida-back
|
||||
config:
|
||||
import: optional:nacos:aida-public-${NACOS_NAMESPACE:test}.yml
|
||||
import: optional:nacos:aida-public-${nacos.namespace}.yml
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: ${NACOS_HOST:127.0.0.1:8848}
|
||||
namespace: ${NACOS_NAMESPACE:test}
|
||||
server-addr: ${nacos.host}
|
||||
namespace: ${nacos.namespace}
|
||||
username: ${nacos.username}
|
||||
password: ${nacos.password}
|
||||
# ip: 18.167.251.121
|
||||
port: 10092
|
||||
# ip-type: ipv4
|
||||
# prefer-ip-address: true
|
||||
config:
|
||||
server-addr: ${NACOS_HOST:127.0.0.1:8848}
|
||||
namespace: ${NACOS_NAMESPACE:test}
|
||||
group: ${NACOS_GROUP:DEFAULT_GROUP}
|
||||
server-addr: ${nacos.host}
|
||||
namespace: ${nacos.namespace}
|
||||
file-extension: yaml
|
||||
username: ${nacos.username}
|
||||
password: ${nacos.password}
|
||||
|
||||
@@ -111,6 +111,7 @@ waistbandRight.cannot.be.empty=waistbandRight cannot be empty.
|
||||
handLeft.cannot.be.empty=handLeft cannot be empty.
|
||||
handRight.cannot.be.empty=handRight cannot be empty.
|
||||
id.cannot.be.empty=id cannot be empty.
|
||||
url.cannot.be.empty=url cannot be empty.
|
||||
type.cannot.be.empty=type cannot be empty.
|
||||
color.cannot.be.empty=color cannot be empty.
|
||||
generateDetailId.cannot.be.empty=generateDetailId cannot be empty.
|
||||
|
||||
@@ -110,6 +110,7 @@ waistbandRight.cannot.be.empty=waistbandRight不能为空。
|
||||
handLeft.cannot.be.empty=handLeft不能为空。
|
||||
handRight.cannot.be.empty=handRight不能为空。
|
||||
id.cannot.be.empty=id不能为空。
|
||||
url.cannot.be.empty=url不能为空。
|
||||
type.cannot.be.empty=type不能为空。
|
||||
color.cannot.be.empty=color不能为空。
|
||||
generateDetailId.cannot.be.empty=generateDetailId不能为空。
|
||||
|
||||
Reference in New Issue
Block a user