104 Commits

Author SHA1 Message Date
ef60e00a05 删除 .gitea/workflows/test.yaml 2026-05-06 14:34:35 +08:00
7e7e6114a3 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 14:27:53 +08:00
b9be107fb3 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 14:14:15 +08:00
08af386876 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 14:10:47 +08:00
5f13d554d5 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 14:10:26 +08:00
f3fe41d334 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 14:03:19 +08:00
7858fb1f15 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 13:53:25 +08:00
3e4ccf47ba 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 13:50:48 +08:00
d1c50cb92a 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 12:12:13 +08:00
26280f30c2 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 12:09:00 +08:00
19a803578f 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 12:04:12 +08:00
934c212633 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 12:03:20 +08:00
281d0423cc 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 12:02:38 +08:00
0a3081b3c9 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 12:00:49 +08:00
b4097162d8 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 11:41:59 +08:00
7f7e3cc1ab 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 11:37:24 +08:00
7d7e214d11 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 11:31:07 +08:00
bbfc88d189 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-05-06 11:28:01 +08:00
ad35f22d79 更新 .gitea/workflows/test.yaml 2026-05-06 11:23:17 +08:00
93c34b3d2f 更新 .gitea/workflows/test.yaml 2026-05-06 11:23:05 +08:00
a112dc247f 更新 .gitea/workflows/test.yaml 2026-05-06 11:21:10 +08:00
ccd6446fe2 更新 .gitea/workflows/test.yaml 2026-05-06 11:13:53 +08:00
f66e723b97 更新 .gitea/workflows/test.yaml
Some checks failed
Java21 Maven Build / build (push) Failing after 11s
2026-05-06 11:10:26 +08:00
0778e51783 更新 .gitea/workflows/test.yaml 2026-05-06 11:10:02 +08:00
1fc3467828 更新 .gitea/workflows/test.yaml 2026-05-06 11:09:46 +08:00
af2883edff 更新 .gitea/workflows/test.yaml 2026-05-05 18:06:12 +08:00
000b20b066 更新 .gitea/workflows/test.yaml 2026-05-05 18:02:43 +08:00
56e430607d 更新 .gitea/workflows/test.yaml 2026-05-05 17:55:18 +08:00
258d91de51 更新 .gitea/workflows/test.yaml 2026-05-05 17:54:05 +08:00
71ab0a9102 更新 .gitea/workflows/test.yaml 2026-05-05 17:44:38 +08:00
4884ac9ade 更新 .gitea/workflows/test.yaml 2026-05-05 17:18:26 +08:00
f1381dbda8 更新 .gitea/workflows/test.yaml 2026-05-05 17:15:05 +08:00
63ef05ac15 更新 .gitea/workflows/test.yaml 2026-05-05 16:52:26 +08:00
f817517ab3 更新 .gitea/workflows/test.yaml 2026-05-05 16:51:25 +08:00
130768031b 更新 .gitea/workflows/test.yaml 2026-05-05 16:45:18 +08:00
cc14ee142c 更新 .gitea/workflows/test.yaml 2026-05-05 16:35:03 +08:00
9fdc72c9ab 添加 .gitea/workflows/test.yaml 2026-05-05 16:34:21 +08:00
ltx
e6f94e595f 更新 .gitea/workflows/prod_build_manual.yaml 2026-04-28 16:38:14 +08:00
6b43996f3f 更新 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-04-24 13:46:56 +08:00
995dda476f 上传文件至「.gitea/workflows」 2026-04-24 13:41:12 +08:00
d0efd00e5e 删除 .gitea/workflows/develop_3.1_release_merge_MS_build_manual.yaml 2026-04-24 13:36:04 +08:00
d3dcb32139 上传文件至「.gitea/workflows」 2026-04-24 13:29:21 +08:00
litianxiang
8126eb7568 数据映射 2026-04-12 23:35:36 +08:00
litianxiang
2aa6875385 2026.3.13生产部署 2026-03-13 17:11:09 +08:00
litianxiang
e4e7875940 2026.3.12生产部署 2026-03-12 19:19:21 +08:00
c1b43dec32 2026.3.5 生产部署 2026-03-05 18:30:14 +08:00
2779d5f10e 更新 .gitea/workflows/prod_build_schedule.yaml
All checks were successful
定时 AiDA back-java 生产分支构建部署 / build_and_deploy (push) Successful in 2m33s
2026-02-04 17:15:50 +08:00
a9485978b6 更新 .gitea/workflows/research_build_manual.yaml 2026-02-02 09:59:47 +08:00
1212c21f9d 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:34:33 +08:00
9d43343cf2 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:33:14 +08:00
dbbf9631be 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:23:47 +08:00
df1a3f47d9 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:20:17 +08:00
7bc2b43ebe 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:15:35 +08:00
7e440afeaa 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:08:13 +08:00
c90a727d80 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 17:04:43 +08:00
2acfad086c 更新 .gitea/workflows/develop_build_manual.yaml 2026-01-30 17:00:43 +08:00
8ab2413315 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 16:47:24 +08:00
366a82f112 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 15:09:08 +08:00
46744e3a29 更新 .gitea/workflows/research_build_manual.yaml 2026-01-30 15:06:12 +08:00
bea48f1aa9 添加 .gitea/workflows/research_build_manual.yaml 2026-01-30 15:00:45 +08:00
3c79593ab0 删除 .gitea/workflows/develop_build_commit.yaml 2026-01-30 14:59:33 +08:00
278a09366b 更新 .gitea/workflows/prod_build_manual.yaml 2026-01-30 14:58:49 +08:00
d722d9c81d 更新 .gitea/workflows/prod_build_schedule.yaml 2026-01-30 14:58:35 +08:00
b7e61cd9c8 2026.1.27 10:00 生产部署
All checks were successful
定时 AiDA back-java 生产分支构建部署 / build_and_deploy (push) Successful in 1m30s
2026-01-27 16:44:46 +08:00
c07cbc958d 2025.12.19 生产部署 2025-12-19 21:43:08 +08:00
70042e0fde 2025.12.19 生产部署 2025-12-19 21:41:56 +08:00
da790b3d11 2025.12.19 生产部署
Some checks failed
定时 AiDA back-java 生产分支构建部署 / build_and_deploy (push) Has been cancelled
2025-12-19 17:51:53 +08:00
d01d476414 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 14:12:03 +08:00
2a97d5fc79 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 12:29:59 +08:00
cc4a08feb3 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 12:21:43 +08:00
a51ee29fa0 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 12:21:09 +08:00
f172050162 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 12:15:43 +08:00
4f410837d9 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 12:08:35 +08:00
150929f721 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 12:00:13 +08:00
2fd96d871c 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 11:59:49 +08:00
356b9fdfc6 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 11:51:51 +08:00
b1510a48ab 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 11:48:48 +08:00
188bf63104 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 11:47:44 +08:00
1b8ab3a578 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 11:47:22 +08:00
204105f525 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 11:05:35 +08:00
069f0b894f 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 10:59:36 +08:00
0c15c7de69 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 10:55:08 +08:00
69c9b23a95 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-02 10:31:13 +08:00
5a84f3f1d4 删除 .gitea/workflows/develop_build_test.yaml 2025-12-01 16:35:36 +08:00
7994e7d082 上传文件至「.gitea/workflows」 2025-12-01 16:35:29 +08:00
fc7020c1d7 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-01 16:25:30 +08:00
5d5dcff55a 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-01 16:24:22 +08:00
4eb5be2ba7 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-01 16:23:13 +08:00
72a0171bfb 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-01 16:22:29 +08:00
1b9bcb2a27 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-01 16:19:02 +08:00
291c83d596 更新 .gitea/workflows/develop_build_manual.yaml 2025-12-01 16:18:09 +08:00
b45eed6191 更新 .gitea/workflows/develop_build_test.yaml 2025-12-01 10:33:06 +08:00
2f84d3d765 [run build] 2025-12-01 10:32:15 +08:00
3837546e7d 更新 .gitea/workflows/prod_build_schedule.yaml
All checks were successful
定时 AiDA back-java Develop 分支构建部署 / build_and_deploy (push) Successful in 2m33s
2025-11-28 17:36:36 +08:00
4615792fce 更新 .gitea/workflows/develop_build_commit.yaml 2025-11-28 16:06:42 +08:00
89843939b0 更新 .gitea/workflows/prod_build_schedule.yaml 2025-11-28 15:24:43 +08:00
f34f50db20 更新 .gitea/workflows/prod_build_manual.yaml 2025-11-28 15:24:11 +08:00
6496d88945 添加 .gitea/workflows/prod_build_manual.yaml 2025-11-28 15:22:47 +08:00
65703881da 更新 .gitea/workflows/prod_build_schedule.yaml
Some checks are pending
定时 AiDA back-java Develop 分支构建部署 / build_and_deploy (push) Has started running
2025-11-28 15:17:11 +08:00
4ee5269b6f 添加 .gitea/workflows/prod_build_schedule.yaml 2025-11-28 15:16:04 +08:00
c6a8375f67 更新 .gitea/workflows/develop_build.yaml 2025-11-28 15:14:45 +08:00
598231f7c0 添加 .gitea/workflows/develop_build.yaml 2025-11-28 15:13:31 +08:00
638d974932 更新 .gitea/workflows/develop_build_manual.yaml 2025-11-28 15:08:08 +08:00
ec162bba0b 添加 .gitea/workflows/develop_build_manual.yaml 2025-11-28 14:52:44 +08:00
1115 changed files with 10045 additions and 79749 deletions

View File

@@ -71,7 +71,7 @@ jobs:
- ./temp:/temp - ./temp:/temp
- ./uploads:/temp/uploads - ./uploads:/temp/uploads
ports: ports:
- '10092:10092' - '10092:5567'
restart: always restart: always
EOF EOF
# 验证docker-compose.yml生成 # 验证docker-compose.yml生成

View File

@@ -14,7 +14,7 @@ jobs:
packages: write packages: write
env: env:
REMOTE_DEPLOY_PATH: /workspace/workspace_aida/DevelopVersion/develop-version-aida-back REMOTE_DEPLOY_PATH: /mnt/process/A6000_Server/AiDA_Workspace/Java_Server_workspace/Dev/
steps: steps:
- name: 0.记录开始时间 - name: 0.记录开始时间
@@ -99,17 +99,9 @@ jobs:
volumes: volumes:
# 数据挂载 # 数据挂载
- ./log:/log - ./log:/log
- ./temp:/temp
- ./uploads:/temp/uploads
ports: ports:
- '10090:5567' - '10090:5567'
networks:
- aida_java_net
restart: always restart: always
networks:
aida_java_net:
external: true
name: aida_java_net
EOF EOF
# 验证docker-compose.yml生成 # 验证docker-compose.yml生成
echo "docker-compose.yml内容:" echo "docker-compose.yml内容:"

View File

@@ -0,0 +1,174 @@
name: 手动 AiDA back-java 生产分支构建部署
on:
workflow_dispatch:
jobs:
build_and_deploy:
runs-on: ubuntu-latest
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/ProdVersion/prod-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: release/3.1
- name: 2.Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: 3.设置JAVA Maven 环境
run: |
# 适配root/普通用户
SUDO=""
[ "$(id -u)" != "0" ] && SUDO="sudo"
# 安装依赖
$SUDO apt update && $SUDO apt install -y wget tar --no-install-recommends
# 下载Maven
MAVEN_VERSION="3.9.11"
MAVEN_TAR="apache-maven-${MAVEN_VERSION}-bin.tar.gz"
MAVEN_URL="https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/${MAVEN_TAR}"
wget --no-verbose -O /tmp/${MAVEN_TAR} ${MAVEN_URL}
# 解压+软链接
$SUDO tar -xzf /tmp/${MAVEN_TAR} -C /usr/local/
$SUDO ln -sf /usr/local/apache-maven-${MAVEN_VERSION} /usr/local/maven
# 配置PATH
echo "/usr/local/maven/bin" >> $GITHUB_PATH
export PATH="/usr/local/maven/bin:$PATH"
# 验证
mvn -v
- name: 4.构建jar包
run: |
echo "===== 开始构建JAR包 ====="
# 新增:打印当前构建分支(两种方式双重确认)
echo "当前工作目录分支:$(git branch --show-current)"
echo "Gitea检出分支:${{ github.ref_name }}"
echo "预期构建分支:dev/3.1_release_merge"
echo "========================"
mvn -B clean install -DskipTests -Pdev 2>&1
# 检查构建是否成功
if [ $? -ne 0 ]; then
echo "JAR包构建失败!"
exit 1
fi
- 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 ./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: prod-version-aida-back
build: .
volumes:
# 数据挂载
- ./log:/log
- ./temp:/temp
- ./uploads:/temp/uploads
ports:
- '10010:5567'
restart: always
EOF
# 验证docker-compose.yml生成
echo "docker-compose.yml内容:"
cat docker-compose.yml
- name: 7.安装SSH工具
run: |
$SUDO apt install -y sshpass openssh-client --no-install-recommends
# 配置SSH免密
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: 8.同步文件到远程服务器
run: |
echo "===== 同步文件到远程服务器 ====="
# 使用scp同步文件
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
./target/*.jar ./Dockerfile ./docker-compose.yml \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ env.REMOTE_DEPLOY_PATH }} 2>&1
- name: 9.部署和运行服务
run: |
echo "===== 开始部署服务 ====="
# SSH执行部署命令
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'EOF_SSH'
cd ${{ env.REMOTE_DEPLOY_PATH }}
echo "停止旧容器..."
docker compose down || true
echo "构建镜像..."
docker compose build --no-cache
echo "启动服务..."
docker compose up -d
echo "验证容器状态..."
docker compose ps
echo "部署完成!"
EOF_SSH
- name: 10.发送构建结果邮件
if: always() # 无论上一步是否失败,都执行此步骤
uses: dawidd6/action-send-mail@v3
with:
from: ${{ secrets.MAIL_USERNAME }}
# --- 邮件配置 ---
server_address: smtp.gmail.com # 替换为你的SMTP服务器地址
server_port: 465 # 替换为你的SMTP端口 (通常是465或587)
username: ${{ secrets.MAIL_USERNAME }} # 存储在Secrets中的邮箱用户名
password: ${{ secrets.MAIL_PASSWORD }} # 存储在Secrets中的邮箱密码
subject: 'Gitea Actions 构建通知: ${{ job.status }} - AiDA back-java Develop'
# 收件人列表,可以根据需要更改
to: 'xupei3360@163.com,txli@aidlab.hk,cgzhou@aidlab.hk,zchengrong@yeah.net' # 替换为实际收件人邮箱
# --- 邮件正文内容 ---
body: |
项目: AiDA back-java Prod
分支: release/3.1
🎉 构建结果: ${{ job.status }}
📅 构建时间: ${{ steps.build_start_time.outputs.current_time }}
🔗 构建链接: ${{ gitea.server_url }}/${{ gitea.repository.owner.name }}/${{ gitea.repository.name }}/actions/runs/${{ gitea.run_id }}
# 确保邮件内容为纯文本,或者你可以设置为 html: true 并调整 body
content_type: text/plain

View File

@@ -0,0 +1,177 @@
name: 定时 AiDA back-java 生产分支构建部署
on:
schedule:
# cron为UTC时区构建时间=部署时间-8小时 {*分 (-8)时 *日 *月 *周} ---
# 示例: 1月1日22点22分触发构建 cron写作 - '22 14 1 1 *'
- cron: '00 14 13 3 *'
jobs:
build_and_deploy:
runs-on: ubuntu-latest
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/ProdVersion/prod-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: release/3.1
- name: 2.Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: 3.设置JAVA Maven 环境
run: |
# 适配root/普通用户
SUDO=""
[ "$(id -u)" != "0" ] && SUDO="sudo"
# 安装依赖
$SUDO apt update && $SUDO apt install -y wget tar --no-install-recommends
# 下载Maven
MAVEN_VERSION="3.9.11"
MAVEN_TAR="apache-maven-${MAVEN_VERSION}-bin.tar.gz"
MAVEN_URL="https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/${MAVEN_TAR}"
wget --no-verbose -O /tmp/${MAVEN_TAR} ${MAVEN_URL}
# 解压+软链接
$SUDO tar -xzf /tmp/${MAVEN_TAR} -C /usr/local/
$SUDO ln -sf /usr/local/apache-maven-${MAVEN_VERSION} /usr/local/maven
# 配置PATH
echo "/usr/local/maven/bin" >> $GITHUB_PATH
export PATH="/usr/local/maven/bin:$PATH"
# 验证
mvn -v
- name: 4.构建jar包
run: |
echo "===== 开始构建JAR包 ====="
# 新增:打印当前构建分支(两种方式双重确认)
echo "当前工作目录分支:$(git branch --show-current)"
echo "Gitea检出分支:${{ github.ref_name }}"
echo "预期构建分支:dev/3.1_release_merge"
echo "========================"
mvn -B clean install -DskipTests -Pdev 2>&1
# 检查构建是否成功
if [ $? -ne 0 ]; then
echo "JAR包构建失败!"
exit 1
fi
- 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 ./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: prod-version-aida-back
build: .
volumes:
# 数据挂载
- ./log:/log
ports:
- '10010:5567'
restart: always
EOF
# 验证docker-compose.yml生成
echo "docker-compose.yml内容:"
cat docker-compose.yml
- name: 7.安装SSH工具
run: |
$SUDO apt install -y sshpass openssh-client --no-install-recommends
# 配置SSH免密
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: 8.同步文件到远程服务器
run: |
echo "===== 同步文件到远程服务器 ====="
# 使用scp同步文件
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
./target/*.jar ./Dockerfile ./docker-compose.yml \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ env.REMOTE_DEPLOY_PATH }} 2>&1
- name: 9.部署和运行服务
run: |
echo "===== 开始部署服务 ====="
# SSH执行部署命令
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'EOF_SSH'
cd ${{ env.REMOTE_DEPLOY_PATH }}
echo "停止旧容器..."
docker compose down || true
echo "清理Docker资源..."
docker system prune -f
echo "构建镜像..."
docker compose build --no-cache
echo "启动服务..."
docker compose up -d
echo "验证容器状态..."
docker compose ps
echo "部署完成!"
EOF_SSH
- name: 10.发送构建结果邮件
if: always() # 无论上一步是否失败,都执行此步骤
uses: dawidd6/action-send-mail@v3
with:
from: ${{ secrets.MAIL_USERNAME }}
# --- 邮件配置 ---
server_address: smtp.gmail.com # 替换为你的SMTP服务器地址
server_port: 465 # 替换为你的SMTP端口 (通常是465或587)
username: ${{ secrets.MAIL_USERNAME }} # 存储在Secrets中的邮箱用户名
password: ${{ secrets.MAIL_PASSWORD }} # 存储在Secrets中的邮箱密码
subject: 'Gitea Actions 构建通知: ${{ job.status }} - AiDA back-java Develop'
# 收件人列表,可以根据需要更改
to: 'xupei3360@163.com,txli@aidlab.hk,cgzhou@aidlab.hk,zchengrong@yeah.net' # 替换为实际收件人邮箱
# --- 邮件正文内容 ---
body: |
项目: AiDA back-java Prod
分支: release/3.1
🎉 构建结果: ${{ job.status }}
📅 构建时间: ${{ steps.build_start_time.outputs.current_time }}
🔗 构建链接: ${{ gitea.server_url }}/${{ gitea.repository.owner.name }}/${{ gitea.repository.name }}/actions/runs/${{ gitea.run_id }}
# 确保邮件内容为纯文本,或者你可以设置为 html: true 并调整 body
content_type: text/plain

View File

@@ -0,0 +1,176 @@
name: 手动 AiDA back-java 开发分支构建部署
on:
workflow_dispatch:
jobs:
build_and_deploy:
runs-on: ubuntu-latest
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: /mnt/process/A6000_Server/AiDA_Workspace/Java_Server_workspace/Dev/
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
- name: 2.Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: 3.设置JAVA Maven 环境
run: |
# 适配root/普通用户
SUDO=""
[ "$(id -u)" != "0" ] && SUDO="sudo"
# 安装依赖
$SUDO apt update && $SUDO apt install -y wget tar --no-install-recommends
# 下载Maven
MAVEN_VERSION="3.9.11"
MAVEN_TAR="apache-maven-${MAVEN_VERSION}-bin.tar.gz"
MAVEN_URL="https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/${MAVEN_TAR}"
wget --no-verbose -O /tmp/${MAVEN_TAR} ${MAVEN_URL}
# 解压+软链接
$SUDO tar -xzf /tmp/${MAVEN_TAR} -C /usr/local/
$SUDO ln -sf /usr/local/apache-maven-${MAVEN_VERSION} /usr/local/maven
# 配置PATH
echo "/usr/local/maven/bin" >> $GITHUB_PATH
export PATH="/usr/local/maven/bin:$PATH"
# 验证
mvn -v
- name: 4.构建jar包
run: |
echo "===== 开始构建JAR包 ====="
# 新增:打印当前构建分支(两种方式双重确认)
echo "当前工作目录分支:$(git branch --show-current)"
echo "Gitea检出分支:${{ github.ref_name }}"
echo "预期构建分支:dev/3.1_release_merge"
echo "========================"
mvn -B clean install -DskipTests -Pdev 2>&1
# 检查构建是否成功
if [ $? -ne 0 ]; then
echo "JAR包构建失败!"
exit 1
fi
- 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 ./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-version-aida-back
build: .
volumes:
# 数据挂载
- ./log:/log
ports:
- '1608:5567'
restart: always
EOF
# 验证docker-compose.yml生成
echo "docker-compose.yml内容:"
cat docker-compose.yml
- name: 7.安装SSH工具
run: |
$SUDO apt install -y sshpass openssh-client --no-install-recommends
# 配置SSH免密
mkdir -p ~/.ssh
echo "${{ secrets.SEARCH_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SEARCH_SERVER_HOST }} >> ~/.ssh/known_hosts
- name: 8.同步文件到远程服务器
run: |
echo "===== 同步文件到远程服务器 ====="
# 使用scp同步文件
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
./target/*.jar ./Dockerfile ./docker-compose.yml \
${{ secrets.SEARCH_SERVER_USER }}@${{ secrets.SEARCH_SERVER_HOST }}:${{ env.REMOTE_DEPLOY_PATH }} 2>&1
- name: 9.部署和运行服务
run: |
echo "===== 开始部署服务 ====="
# SSH执行部署命令
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
${{ secrets.SEARCH_SERVER_USER }}@${{ secrets.SEARCH_SERVER_HOST }} << 'EOF_SSH'
cd ${{ env.REMOTE_DEPLOY_PATH }}
echo "停止旧容器..."
docker compose down || true
echo "清理Docker资源..."
docker system prune -f
echo "构建镜像..."
docker compose build --no-cache
echo "启动服务..."
docker compose up -d
echo "验证容器状态..."
docker compose ps
echo "部署完成!"
EOF_SSH
- name: 10.发送构建结果邮件
if: always() # 无论上一步是否失败,都执行此步骤
uses: dawidd6/action-send-mail@v3
with:
from: ${{ secrets.MAIL_USERNAME }}
# --- 邮件配置 ---
server_address: smtp.gmail.com # 替换为你的SMTP服务器地址
server_port: 465 # 替换为你的SMTP端口 (通常是465或587)
username: ${{ secrets.MAIL_USERNAME }} # 存储在Secrets中的邮箱用户名
password: ${{ secrets.MAIL_PASSWORD }} # 存储在Secrets中的邮箱密码
subject: 'Gitea Actions 构建通知: ${{ job.status }} - AiDA back-java Develop'
# 收件人列表,可以根据需要更改
to: 'cgzhou@aidlab.hk,zchengrong@yeah.net' # 替换为实际收件人邮箱
# --- 邮件正文内容 ---
body: |
项目: AiDA back-java Develop
分支: dev/3.1_release_merge
🎉 构建结果: ${{ job.status }}
📅 构建时间: ${{ steps.build_start_time.outputs.current_time }}
🔗 构建链接: ${{ gitea.server_url }}/${{ gitea.repository.owner.name }}/${{ gitea.repository.name }}/actions/runs/${{ gitea.run_id }}
# 确保邮件内容为纯文本,或者你可以设置为 html: true 并调整 body
content_type: text/plain

49
.gitignore vendored
View File

@@ -1,51 +1,2 @@
sql/*.sql sql/*.sql
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
.log
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
.mvn
mvnw*
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
### generated files ###
bin/
gen/
### MAC ###
.DS_Store
### Other ###
logs/
log
temp/
docker-compose.yml
/src/main/resources/application-local.properties

View File

@@ -1,3 +1,2 @@
# Aida 1.2 # Aida 1.2
Version of aida 1.3 Version of aida 1.2
修改预先登录接口、逻辑

192
aida.iml Normal file
View File

@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.29" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.25" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.29" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.29" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.2.2.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.2.2.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.2.2.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.29" level="project" />
<orderEntry type="library" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.2" level="project" />
<orderEntry type="library" name="Maven: jakarta.activation:jakarta.activation-api:1.2.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.vintage:junit-vintage-engine:5.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:3.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.13.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:3.1.0" level="project" />
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.10.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.2.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.2.2.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.6.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.2.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.2.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.2.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.lettuce:lettuce-core:5.2.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.43.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.43.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.43.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.43.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.43.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.43.Final" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.3.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:5.2.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.2.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:5.2.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.1.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.64" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.64" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.18" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:4.4" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.10" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.7" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.3.61" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.61" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.29" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.18.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
<orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.8.2" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:fastjson:2.0.6.graal" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.fastjson2:fastjson2-extension:2.0.6.graal" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.fastjson2:fastjson2:2.0.6.graal" level="project" />
<orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.14.2" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okio:okio:1.17.2" level="project" />
<orderEntry type="library" name="Maven: javax.xml.bind:jaxb-api:2.4.0-b180830.0359" level="project" />
<orderEntry type="library" name="Maven: javax.activation:javax.activation-api:1.2.0" level="project" />
<orderEntry type="library" name="Maven: com.sun.xml.bind:jaxb-impl:4.0.0" level="project" />
<orderEntry type="library" name="Maven: com.sun.xml.bind:jaxb-core:4.0.0" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.eclipse.angus:angus-activation:1.0.0" level="project" />
<orderEntry type="library" name="Maven: javax.activation:activation:1.1.1" level="project" />
<orderEntry type="library" name="Maven: com.github.whvcse:easy-captcha:1.6.2" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:31.1-jre" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:3.12.0" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.11.0" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring-boot-starter:3.0.3" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring-boot-autoconfigure:3.0.3" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring:3.0.3" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-annotations:3.0.3" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-annotations:1.5.22" level="project" />
<orderEntry type="library" name="Maven: io.swagger.core.v3:swagger-annotations:2.1.2" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-core:3.0.3" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.25.0-GA" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger2:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spi:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-schema:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger-common:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-web:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.github.classgraph:classgraph:4.8.83" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-webflux:3.0.0" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.mapstruct:mapstruct:1.3.1.Final" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-webmvc:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-core:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-oas:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.swagger.core.v3:swagger-models:2.1.2" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-bean-validators:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-models:1.5.22" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-core:1.5.22" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.1" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-boot-starter:3.0.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-data-rest:3.0.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-core:2.0.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-metadata:2.0.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring-ui:3.0.3" level="project" />
<orderEntry type="library" name="Maven: com.tencentcloudapi:tencentcloud-sdk-java-ses:3.1.572" level="project" />
<orderEntry type="library" name="Maven: com.tencentcloudapi:tencentcloud-sdk-java-common:3.1.572" level="project" />
<orderEntry type="library" name="Maven: commons-logging:commons-logging:1.2" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okhttp:okhttp:2.7.5" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okhttp:logging-interceptor:2.7.5" level="project" />
<orderEntry type="library" name="Maven: org.ini4j:ini4j:0.5.4" level="project" />
</component>
</module>

View File

@@ -1,9 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAymkBAWixxUi9IAeMWgsq
K92AzFbe0qzzYPdkoh15ymL2A5MkYH7asnhFwclgdiFmd9a0TbZP+t/SzWW8UUzN
1pXoEp48R+eguGTt5xkJwb10+H6quVXF/Ezzid5yzVW3dcYRp8qUlFr0XBpvkK9l
FpPzh2+mwVEAsgBMXq/K50ZiX2dlkPZ7ffkVPWaK2ESIo3YgfM6dmiiza0hPWJ35
UgTH5rwJ7vN3IdOJTlkQOvrIrj2ocPcrudeEwqybIbCGhgRBwQSBsXQOO4U//rE4
VU+0LF/3uQgXkvVY1+a1JLiTncZYKGEQ/NtxM+dGtYWV2gPhQRyJ7Z77OX0XCbcn
zwIDAQAB
-----END PUBLIC KEY-----

View File

@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDD+NUduhLJcb2Z
ryLwtIHdmjfh6Wn73E9umHmdPf6yF7IbDoTDBmIAfaPU/oiLgrka3fKGCkn/yHvW
QcL+Ry96/Uu+iIN9SbG5vPVvLtLfx+5++IE8p3RxcSDQggqFuJ+osebXeVIrOcTZ
s7nXCqGenTcagv2eJESiq712fcBvY1wVgilT6ERVQy+zdvwAOiS6wXF/51AueP+E
rNDHuPLkGH6JhLtO4LffeYgM/Th7eCl/WWLkiVMSoeJt7vWFe4bYV/IYW1qI2aQX
H1DYmvwgDfDv8jRORD9D191YBqq1l3Tw7VSjFrpydFvSK46dbXKBj3oA5ZiJ+Ttj
ZCtBRiOdAgMBAAECggEAUKl4Fs9C8lV1o+85Y3f4yBy1CbCIZhltPGlYDUe6MNWe
ApL8REW5Sthr+bx2uW2qAQv/yfosMTL0/eB9gSoNugLODXOlI4mUtI25O/U66M8j
NHHWx/9o51SYHBqaeCXg2Y+4I1KVZqNVigH26TNACMhPKQNnnpLxCT/FMSNbdLzo
wfFMyjN7R3Hc8ZB1C2zx+fLJm1DNZeOJOHAkW1LprlotRv6eq3lOwZaDDUTB5xhT
0Erev3djC/R08Fne1y09ukar8z0tX3Fm9SzHJDFVoh1HOYPWayCiAxOhip+JnFct
rtK5jjuB8DAP4Q1k12yOWUFwb6NOG9Hf/G6XExRPBQKBgQD1P2SnKD1IlNSrvVJn
2HzKnBVllVo50fbv7SpnP8H1B5vt2Qo/mgOGtzbeXyK4mcLFaWg9++BrsjTXwZFi
wmKeJgNI822DPhF5qQhK7Cc+WMwesufGrTnmRUOEFYehz9ffZBvMa1s/ObIEyLcr
tYitT74+nFdRPtr+8PN06QMEcwKBgQDMkGFWhSO7p7VMuV0H0uC1fj3GGtVvM+Ps
a9ASs0HBhQaOpberkKY9vgry6HoJ8CGvbrxlmc3JoYPRwKN3oQRYLvGSF96HAg9i
643FmVAWiVzHpjYX9fMJyCzXiOw6Qet8Zp3Ewaw9BBG0200Fj6/zGc8XEqNjIv5Q
DQ9MosRDrwKBgQCU5i5IRugeXy5YLxQPNKNfqDBdgrZLEK2qsgXithUencYQPIw6
XVnyut43WO+NwN0+WmcN6xUwjfwDWuTYX0jc2Bt6eUFuQ4r8oKIGSybwdZ1IrjqG
p7nVkwwQ77lvhu98FB3EmRHHa1IoEW0Uvp0DDL1m6ikhjNYNn2FRA//u/QKBgGbY
a+eo1ldBMPha9Te6wLjeuEYCNa5L41p4tcrBDt0xeSN8k4QRHFNMWYrYcIrQjM77
mIJoOjsWFgT9mfHKJToEl/VAROORmJS+Iq/mrYo3E0tY+DdBsygG2Oyf7Uw42iDY
IpfKW0Lt6c0IuIeEPwy0vBY4i6aK8Frkxf1ck9oHAoGBAKFQg/c36J6tjnttpmes
R/zijp1ROE+z+dMmm3icDhCDvvR6MnHa2Y9ittNWdEUosZk9FsFn62YNtJJV2SIN
DDn0ASLtBkeCd8yad5uzUb7Umci9V7TP5c0NE3DK95FmciLGOuRbFyq1Z8edHnaS
zgLnf4yb25eCMLEG0Z2ugN3C
-----END PRIVATE KEY-----

View File

@@ -1,9 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw/jVHboSyXG9ma8i8LSB
3Zo34elp+9xPbph5nT3+sheyGw6EwwZiAH2j1P6Ii4K5Gt3yhgpJ/8h71kHC/kcv
ev1LvoiDfUmxubz1by7S38fufviBPKd0cXEg0IIKhbifqLHm13lSKznE2bO51wqh
np03GoL9niREoqu9dn3Ab2NcFYIpU+hEVUMvs3b8ADokusFxf+dQLnj/hKzQx7jy
5Bh+iYS7TuC333mIDP04e3gpf1li5IlTEqHibe71hXuG2FfyGFtaiNmkFx9Q2Jr8
IA3w7/I0TkQ/Q9fdWAaqtZd08O1Uoxa6cnRb0iuOnW1ygY96AOWYifk7Y2QrQUYj
nQIDAQAB
-----END PUBLIC KEY-----

465
pom.xml
View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version> <version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>com.aida</groupId> <groupId>com.aida</groupId>
@@ -14,53 +14,21 @@
<name>aida</name> <name>aida</name>
<description>ai da</description> <description>ai da</description>
<properties> <properties>
<java.version>21</java.version> <java.version>8</java.version>
<mybatis.plus.version>3.5.7</mybatis.plus.version> <mybatis.plus.version>3.5.2</mybatis.plus.version>
<hutool.version>5.8.23</hutool.version> <hutool.version>5.8.2</hutool.version>
<wx.java.version>4.2.7.B</wx.java.version> <wx.java.version>4.2.7.B</wx.java.version>
<fastjson.version>2.0.43</fastjson.version> <fastjson.version>2.0.6.graal</fastjson.version>
<jjwt.version>0.12.3</jjwt.version> <security.jwt.version>1.1.1.RELEASE</security.jwt.version>
<guava.version>32.1.3-jre</guava.version> <jjwt.version>0.9.1</jjwt.version>
<guava.version>31.1-jre</guava.version>
<jaxb-api>2.4.0-b180830.0359</jaxb-api>
<jaxb-impl>4.0.0</jaxb-impl>
<jaxb-core>4.0.0</jaxb-core>
<activation>1.1.1</activation>
<easy-captcha>1.6.2</easy-captcha> <easy-captcha>1.6.2</easy-captcha>
<aws.java.sdk.version>2.20.43</aws.java.sdk.version>
<javacv.version>1.5.5</javacv.version>
<system.windowsx64>windows-x86_64</system.windowsx64>
<javacpp.platform.linux-x86_64>linux-x86_64</javacpp.platform.linux-x86_64>
<!-- Spring Cloud Alibaba 版本 -->
<spring-cloud-alibaba.version>2023.0.3.4</spring-cloud-alibaba.version>
<!-- Spring Cloud 版本 -->
<spring-cloud.version>2023.0.4</spring-cloud.version>
</properties> </properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>${aws.java.sdk.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud 依赖版本管理 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba 依赖版本管理 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@@ -90,30 +58,24 @@
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>org.springframework.security</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>spring-security-jwt</artifactId>
<version>${security.jwt.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId> <artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version> <version>${mybatis.plus.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.4</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
@@ -126,28 +88,34 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId> <artifactId>jjwt</artifactId>
<version>${jjwt.version}</version> <version>${jjwt.version}</version>
</dependency> </dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
<version>3.14.2</version> <version>3.14.2</version>
</dependency> </dependency>
<!-- JAXB is included in Java 11+ but needs explicit dependency for Java 9-10 --> <dependency>
<!-- For Java 21, these are not needed as JAXB is part of JDK --> <groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb-impl}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>${jaxb-core}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation}</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.whvcse</groupId> <groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId> <artifactId>easy-captcha</artifactId>
@@ -161,336 +129,15 @@
<dependency> <dependency>
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <artifactId>knife4j-spring-boot-starter</artifactId>
<version>4.4.0</version> <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<!-- Swagger 2 annotations for backward compatibility -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.14</version>
</dependency> </dependency>
<!-- /**发送邮件**/--> <!-- /**发送邮件**/-->
<!-- <dependency>-->
<!-- <groupId>com.tencentcloudapi</groupId>-->
<!-- <artifactId>tencentcloud-sdk-java-ses</artifactId>-->
<!-- <version>3.1.572</version>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>com.tencentcloudapi</groupId> <groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-ses</artifactId> <artifactId>tencentcloud-sdk-java-ses</artifactId>
<version>3.1.572</version> <version>3.1.572</version>
</dependency> </dependency>
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.4.2.jre11</version>
</dependency>
<!-- RabbitMQ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- redis 连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--支付宝 SDK-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.57.ALL</version>
</dependency>
<!--PayPal SDK-->
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>checkout-sdk</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>rest-api-sdk</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<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>
<version>26.2.0</version>
</dependency>
<!-- aws s3 -->
<!-- S3 dependency -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-transfer-manager</artifactId>
<version>2.17.103-PREVIEW</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kms</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3control</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.32.1</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>1.32.1</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>1.41.5</version>
</dependency>
<!-- 邮件发送 -->
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.3</version>
</dependency>
<!-- JSON 转义恢复 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.10.0</version> <!-- 使用最新版本 -->
</dependency>
<!-- 最新版本号https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
<!-- 万象SDK -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>2.20.1</version>
</dependency>
<!-- FFmpeg封装JavaCV 视频转gif 全部依赖-->
<!--<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.9</version>
</dependency>-->
<!-- javacv+javacpp核心库-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${javacv.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<version>${javacv.version}</version>
</dependency>
<!-- 最小opencv依赖包 必须包含上面的javacv+javacpp -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.5.1-${javacv.version}</version>
<!--<classifier>${system.windowsx64}</classifier>-->
<classifier>${javacpp.platform.linux-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.13-${javacv.version}</version>
<!--<classifier>${system.windowsx64}</classifier>-->
<classifier>${javacpp.platform.linux-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
<version>2.13.3.31-${javacv.version}</version>
<!--<classifier>${system.windowsx64}</classifier>-->
<classifier>${javacpp.platform.linux-x86_64}</classifier>
</dependency>
<!-- FFmpeg视频处理解决你的报错 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.4-1.5.6</version>
<!--<classifier>${system.windowsx64}</classifier>-->
<classifier>${javacpp.platform.linux-x86_64}</classifier>
</dependency>
<dependency>
<groupId>com.volcengine</groupId>
<artifactId>volcengine-java-sdk-ark-runtime</artifactId>
<version>0.2.43</version>
</dependency>
<!-- Google 认证库 -->
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>1.38.0</version>
</dependency>
<!-- GIFEncoder 视频转gif-->
<dependency>
<groupId>com.madgag</groupId>
<artifactId>animated-gif-lib</artifactId>
<version>1.4</version>
</dependency>
<!-- Jakarta WebSocket API -->
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>2.1.1</version>
</dependency>
<!-- Spring MockMultipartFile 等测试工具,生产代码中也有引用 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- BouncyCastle 加密库 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- ==================== Spring Cloud Alibaba 微服务相关 ==================== -->
<!-- 启用 bootstrap.yml 加载 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- Nacos 服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Nacos 配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- OpenFeign 服务调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring Cloud LoadBalancer 负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@@ -510,30 +157,4 @@
</plugins> </plugins>
</build> </build>
<profiles>
<profile>
<!-- 本地开发环境 -->
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<profiles.active>test</profiles.active>
</properties>
</profile>
<profile>
<!-- 生产环境 -->
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
</profile>
</profiles>
</project> </project>

View File

View File

@@ -3,17 +3,9 @@ package com.ai.da;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@Slf4j @Slf4j
@SpringBootApplication @SpringBootApplication
@EnableScheduling
@EnableAsync
@EnableFeignClients
@EnableDiscoveryClient
public class AiDaApplication { public class AiDaApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@@ -1,95 +0,0 @@
package com.ai.da.common.RabbitMQ;
import com.ai.da.common.utils.MailUtil;
import com.ai.da.model.dto.BasicEmailParamDTO;
import com.ai.da.service.EmailService;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.core.exception.RetryableException;
import org.springframework.amqp.core.Message;
import jakarta.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class EmailRetryConsumer {
@Resource
private MailUtil mailUtil;
@Resource
private MQPublisher mqPublisher;
@Resource
private EmailService emailService;
// @RabbitListener(queues = "#{rabbitMQProperties.deadLetter.queue}")
public void handleRetry(Map<String, String> mailParams, Message message, Channel channel) throws IOException {
long tag = message.getMessageProperties().getDeliveryTag();
try {
log.info("死信队列收到消息:{}", message);
// 处理邮件发送参数
BasicEmailParamDTO basicEmailParamDTO = JSONObject.parseObject(mailParams.get("dto"), BasicEmailParamDTO.class);
String fileName = mailParams.get("filename");
InputStreamSource inputStreamSource = Objects.isNull(mailParams.get("source")) ?
null : JSONObject.parseObject(mailParams.get("source"), InputStreamSource.class);
JSONObject templateParams = JSONObject.parseObject(mailParams.get("templateParams"), JSONObject.class);
String templateName = mailParams.get("templatePath");
long logId = Long.parseLong(mailParams.get("logId"));
basicEmailParamDTO.setContent(mailUtil.setContent(templateParams, templateName));
// 发邮件
int lastReturnCode = mailUtil.sendMail(basicEmailParamDTO, fileName, inputStreamSource);
if (lastReturnCode == 250) {
log.info("邮件发送成功Subject : {}", basicEmailParamDTO.getSubject());
emailService.updateStatus(logId, EmailService.DELIVERED);
} else if (lastReturnCode == 450) {
log.info("目标邮箱 {} 暂时不可用,请稍后重试", (Object) basicEmailParamDTO.getMailTo());
// 重试
retry(mailParams, message, channel, tag, logId);
} else if (lastReturnCode == 550) {
log.info("目标邮箱 {} 不可用,邮件发送失败", (Object) basicEmailParamDTO.getMailTo());
emailService.updateStatus(logId, EmailService.FAILED);
} else {
log.info("邮件发送失败Subject : {}, 状态码: {}", basicEmailParamDTO.getSubject(), lastReturnCode);
retry(mailParams, message, channel, tag, logId);
emailService.updateStatus(logId, EmailService.FAILED);
}
channel.basicAck(tag, false);
} catch (RetryableException e) {
log.info("邮件重试发生异常:RetryableException -> {}", e.getMessage());
channel.basicAck(tag, false); // 确认原消息
} catch (Exception e) {
log.info("邮件重试发生异常:Exception -> {}", e.getMessage());
channel.basicAck(tag, false); // 确认原消息
}
}
private int getRetryAttempt(Message message) {
Integer attempt = message.getMessageProperties()
.getHeader("x-retry-attempt");
return attempt != null ? attempt : 1;
}
private void retry(Map<String, String> mailParams, Message message, Channel channel, long tag, long logId) throws IOException{
int attempt = getRetryAttempt(message);
if (attempt >= 3) { // 最大重试次数
channel.basicReject(tag, false);
emailService.updateStatus(logId, EmailService.FAILED);
log.error("重试结束,邮件最终发送失败: {}", mailParams);
} else {
log.info("重新将邮件信息发送到重试队列");
mqPublisher.sendEmailMsg(mailParams, attempt);
channel.basicAck(tag, false); // 确认原消息
// 更新数据库
emailService.updateRetryCount(logId, attempt + 1);
}
}
}

View File

@@ -1,661 +0,0 @@
package com.ai.da.common.RabbitMQ;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.constant.CommonConstant;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.model.dto.GenerateThroughImageTextDTO;
import com.ai.da.model.vo.GenerateResultVO;
import com.ai.da.model.vo.PoseTransformationVO;
import com.ai.da.service.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.rabbitmq.client.Channel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
@RequiredArgsConstructor
public class GenerateConsumer {
private final GenerateService generateService;
private final UserLikeGroupService userLikeGroupService;
private final DesignService designService;
private final CloudTaskService cloudTaskService;
private final RabbitMQProperties rabbitMQProperties;
private final RedisUtil redisUtil;
private final MessageCenterService messageCenterService;
@Value("${redis.key.orderForGenerate}")
private String consumptionOrderKey;
@Value("${redis.key.generateCancelSet}")
private String cancelSetKey;
@Value("${redis.key.generateExceptionMap}")
private String exceptionMapKey;
@Value("${redis.key.generateResult}")
private String generateResultKey;
@Value("${redis.key.toProductImageResultKey}")
private String toProductImageResultKey;
@Value("${redis.key.relightResultKey}")
private String relightResultKey;
public void generate(Message msg, Channel channel, String consumerName) {
log.info("============start listening==========");
long start = System.currentTimeMillis();
Map<String, String> resp = jsonBytesToMap(msg, channel);
String uniqueId = resp.get("tasks_id");
// String uniqueId = generateThroughImageTextDTO.getUniqueId();
log.info("From " + consumerName + " : " + uniqueId);
try {
// 2、判断当前消息是否在取消列表中
Boolean isMember = redisUtil.isElementExistsInSet(cancelSetKey, uniqueId);
if (isMember) {
try {
// 2.1 手动确认该消息
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException ex) {
log.error("手动确认,不返回队列重新消费");
}
} else {
GenerateThroughImageTextDTO generateThroughImageTextDTO = JSONObject.parseObject(msg.getBody(), GenerateThroughImageTextDTO.class);
generateService.generateThroughImageText(generateThroughImageTextDTO);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, uniqueId);
}
} catch (Exception e) {
log.error(e.getMessage());
// channel.basicNack() 为不确认deliveryTag对应的消息第二个参数是否应用于多消息第三个参数是否requeue
try {
// 第二个参数是否批量确认消息当传false时只确认当前 deliveryTag对应的消息;当传true时会确认当前及之前所有未确认的消息。
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, uniqueId);
String key = generateResultKey + ":" + uniqueId;
GenerateResultVO generateResultVO = new GenerateResultVO(uniqueId, null, null, "Fail");
redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(resp) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(uniqueId), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info(" task_id " + uniqueId + "----------" + consumerName + " 执行时长:" + (end - start) + "毫秒");
log.info("=============end listening===========");
}
public void processGenerateResult(Message msg, Channel channel) {
log.info("============ProcessGenerateResult listening==========");
long start = System.currentTimeMillis();
Map<String, String> generateResult = jsonBytesToMap(msg, channel);
log.info("generate response : {}", generateResult);
try {
log.info("tasks_id : {} start ", generateResult.get("tasks_id"));
if (generateResult.get("status").equals("SUCCESS")) {
String url = generateResult.get("image_url");
String taskId = generateResult.get("tasks_id");
String category = generateResult.get("category");
generateService.processGenerateResult(taskId, url, category);
} else {
// 修改redis中的数据状态为exception
String key = generateResultKey + ":" + generateResult.get("tasks_id");
redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(generateResult.get("tasks_id"), null, null, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.get("tasks_id"), generateResult.get("data"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.get("tasks_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(generateResult.get("tasks_id")), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start));
log.info("============ProcessGenerateResult End listening==========");
}
public void processToProductImageResult(Message msg, Channel channel) {
log.info("============processToProductImageResult listening==========");
long start = System.currentTimeMillis();
Map<String, String> generateResult = jsonBytesToMap(msg, channel);
log.info("toProductImage response : {}", generateResult);
try {
log.info("tasks_id : {} start ", generateResult.get("tasks_id"));
if (generateResult.get("status").equals("SUCCESS")) {
String url = generateResult.get("image_url");
String taskId = generateResult.get("tasks_id");
String category = generateResult.get("category");
generateService.processToProductImageResult(taskId, url, category);
} else if (generateResult.get("status").equals("NO_FACE")) {
String taskId = generateResult.get("tasks_id");
userLikeGroupService.toProduct(taskId);
} else {
// 修改redis中的数据状态为exception
String key = toProductImageResultKey + ":" + generateResult.get("tasks_id");
generateService.updateToProductTaskStatus(generateResult.get("tasks_id"), "Fail");
redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(generateResult.get("tasks_id"), null, null, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.get("tasks_id"), generateResult.get("data"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.get("tasks_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(generateResult.get("tasks_id")), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start));
log.info("============ProcessToProductImageResult End listening==========");
}
private void processRelightResult(Message msg, Channel channel) {
log.info("============processRelightResult listening==========");
long start = System.currentTimeMillis();
Map<String, String> generateResult = jsonBytesToMap(msg, channel);
log.info("toProductImage response : {}", generateResult);
try {
log.info("tasks_id : {} start ", generateResult.get("tasks_id"));
if (generateResult.get("status").equals("SUCCESS")) {
String url = generateResult.get("image_url");
String taskId = generateResult.get("tasks_id");
String category = generateResult.get("category");
generateService.processRelightResult(taskId, url, category);
} else if (generateResult.get("status").equals("NO_FACE")) {
String taskId = generateResult.get("tasks_id");
userLikeGroupService.relight(taskId);
} else {
// 修改redis中的数据状态为exception
String key = relightResultKey + ":" + generateResult.get("tasks_id");
generateService.updateToProductTaskStatus(generateResult.get("tasks_id"), "Fail");
redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(generateResult.get("tasks_id"), null, null, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.get("tasks_id"), generateResult.get("data"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.get("tasks_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(generateResult.get("tasks_id")), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start));
log.info("============ProcessRelightResult End listening==========");
}
public void processPoseTransformResult(Message msg, Channel channel) {
log.info("============ProcessPoseTransformResult listening==========");
long start = System.currentTimeMillis();
Map<String, String> generateResult = jsonBytesToMap(msg, channel);
log.info("PoseTransformation response : {}", generateResult);
try {
log.info("tasks_id : {} start ", generateResult.get("tasks_id"));
if (generateResult.get("status").equals("SUCCESS")) {
String gifUrl = generateResult.get("gif_url");
String taskId = generateResult.get("tasks_id");
String videoUrl = generateResult.get("video_url");
String imageUrl = generateResult.get("image_url");
generateService.processPoseTransformResult(taskId, gifUrl, videoUrl, imageUrl);
} else {
// 修改redis中的数据状态为exception
String key = generateResultKey + ":" + generateResult.get("tasks_id");
generateService.updatePoseTransferStatus(generateResult.get("tasks_id"), "Fail", null);
redisUtil.addToString(key, new Gson().toJson(new PoseTransformationVO(null, generateResult.get("tasks_id"),null, null, null, (byte)0, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.get("tasks_id"), generateResult.get("message"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
// 记录失败状态并向用户发送提示消息
generateService.processPTFailSituation(generateResult.get("tasks_id"));
}
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.get("tasks_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(generateResult.get("tasks_id")), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
// 记录失败状态并向用户发送提示消息
generateService.processPTFailSituation(generateResult.get("tasks_id"));
}
long end = System.currentTimeMillis();
log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start));
log.info("============ProcessPoseTransformResult End listening==========");
}
public static Map<String, String> jsonBytesToMap(Message msg, Channel channel) {
try {
// 1. byte[] -> String
String jsonString = new String(msg.getBody(), StandardCharsets.UTF_8).trim();
// 2. 处理可能的双重转义
if (jsonString.startsWith("\"") && jsonString.endsWith("\"")) {
jsonString = jsonString.substring(1, jsonString.length() - 1);
// 使用 Apache Commons Text 将 JSON 字符串中的转义字符还原为原始字符
jsonString = StringEscapeUtils.unescapeJson(jsonString);
}
// 3. 验证 JSON 格式
if (!isValidJson(jsonString)) {
throw new IllegalArgumentException("Invalid JSON format");
}
// 4. 解析为 Map
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(jsonString, new TypeReference<Map<String, String>>() {});
} catch (Exception e) {
log.error("消息解析失败: {}", e.getMessage(), e);
try {
// 仅对不可恢复错误(如非 JSON 数据)进行 ACK
if (e instanceof JsonParseException || e instanceof IllegalArgumentException) {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
log.warn("因消息格式错误,已确认并丢弃消息。原始消息为:{}", msg);
}
} catch (IOException ex) {
log.error("消息确认失败: {}", ex.getMessage(), ex);
}
throw new RuntimeException("Failed to parse JSON to Map", e);
}
}
// 辅助方法:验证字符串是否为合法 JSON
private static boolean isValidJson(String json) {
try {
new ObjectMapper().readTree(json);
return true;
} catch (Exception e) {
return false;
}
}
private void processDesignBatchResult(Message msg, Channel channel) {
log.info("============processDesignBatchResult listening==========");
long start = System.currentTimeMillis();
Map<String, Object> generateResult = JSONObject.parseObject(msg.getBody(), Map.class);
log.info("designBatch response : {}", generateResult);
designService.processDesignBatch(generateResult);
}
private void processToProductImageBatchResult(Message msg, Channel channel) {
log.info("============processToProductImageResultBatch listening==========");
long start = System.currentTimeMillis();
JSONObject generateResult = JSONObject.parseObject(msg.getBody(), JSONObject.class);
log.info("toProductImageBatch response : {}", generateResult);
try {
log.info("task_id : {} start ", generateResult.get("task_id"));
if (!StringUtils.isEmpty(generateResult.getString("progress"))) {
String progress = generateResult.getString("progress");
String url = null;
if (!progress.startsWith("0") && !progress.equals("OK")) {
JSONObject result = generateResult.getJSONObject("result");
if (Objects.nonNull(result)) {
url = result.getString("product_img");
String taskId = generateResult.getString("task_id");
userLikeGroupService.toProductBatch(taskId, url, progress);
}
} else if (progress.startsWith("0/")) {
String batchTaskId = generateResult.getString("task_id");
if (!StringUtils.isEmpty(batchTaskId)) {
cloudTaskService.startTask(batchTaskId);
}
} else if (progress.equals("OK")) {
String batchTaskId = generateResult.getString("task_id");
if (!StringUtils.isEmpty(batchTaskId)) {
cloudTaskService.completeTask(batchTaskId);
}
}
} else {
// 修改redis中的数据状态为exception
String key = toProductImageResultKey + ":" + generateResult.get("task_id");
generateService.updateToProductTaskStatus(generateResult.getString("task_id"), "Fail");
redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(generateResult.getString("tasks_id"), null, null, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.getString("task_id"), generateResult.getString("data"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.getString("task_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(generateResult.get("task_id")), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info("task_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("task_id"), generateResult.get("message"), (end - start));
log.info("============ProcessToProductImageBatchResult End listening==========");
}
private void processRelightBatchResult(Message msg, Channel channel) {
log.info("============processRelightResult listening==========");
long start = System.currentTimeMillis();
JSONObject generateResult = JSONObject.parseObject(msg.getBody(), JSONObject.class);
log.info("relightBatch response : {}", generateResult);
try {
log.info("task_id : {} start ", generateResult.get("task_id"));
if (!StringUtils.isEmpty(generateResult.getString("progress"))) {
String progress = generateResult.getString("progress");
String url = null;
if (!progress.startsWith("0") && !progress.equals("OK")) {
JSONObject result = generateResult.getJSONObject("result");
if (Objects.nonNull(result)) {
url = result.getString("relight_img");
String taskId = generateResult.getString("task_id");
userLikeGroupService.relightBatch(taskId, url, progress);
}
} else if (progress.startsWith("0/")) {
String batchTaskId = generateResult.getString("task_id");
if (!StringUtils.isEmpty(batchTaskId)) {
cloudTaskService.startTask(batchTaskId);
}
} else if (progress.equals("OK")) {
String batchTaskId = generateResult.getString("task_id");
if (!StringUtils.isEmpty(batchTaskId)) {
cloudTaskService.completeTask(batchTaskId);
}
}
} else {
// 修改redis中的数据状态为exception
String key = relightResultKey + ":" + generateResult.get("task_id");
generateService.updateToProductTaskStatus(generateResult.getString("task_id"), "Fail");
redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(generateResult.getString("tasks_id"), null, null, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.getString("task_id"), generateResult.getString("data"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.getString("task_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(String.valueOf(generateResult.get("task_id")), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info("task_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("task_id"), generateResult.get("message"), (end - start));
log.info("============ProcessRelightBatchResult End listening==========");
}
private void processPoseTransformBatchResult(Message msg, Channel channel) {
log.info("============ProcessPoseTransformBatchResult listening==========");
long start = System.currentTimeMillis();
JSONObject generateResult = JSONObject.parseObject(msg.getBody(), JSONObject.class);
log.info("PoseTransformationBatch response : {}", generateResult);
try {
log.info("task_id : {} start ", generateResult.get("task_id"));
if (!StringUtils.isEmpty(generateResult.getString("progress"))) {
String progress = generateResult.getString("progress");
String taskId = generateResult.getString("task_id");
generateService.processPoseTransformResultBatch(progress, taskId);
JSONArray result = generateResult.getJSONArray("result");
if (!StringUtils.isEmpty(result)) {
JSONObject jsonObject = result.getJSONObject(0);
String gifUrl = jsonObject.getString("gif_url");
String videoUrl = jsonObject.getString("video_url");
String imageUrl = jsonObject.getString("first_image_url");
generateService.processPoseTransformResultBatch(taskId, gifUrl, videoUrl, imageUrl, progress);
}
} else {
// 修改redis中的数据状态为exception
String key = generateResultKey + ":" + generateResult.getString("task_id");
generateService.updatePoseTransferStatus(generateResult.getString("task_id"), "Fail", null);
redisUtil.addToString(key, new Gson().toJson(new PoseTransformationVO(null, generateResult.getString("task_id"),null, null, null, (byte)0, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 将异常信息存到exception中
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.getString("task_id"), generateResult.getString("message"));
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
try {
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, generateResult.getString("task_id"));
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
// 将入参和错误信息存入数据库
String exceptionMessage = JSONObject.toJSONString(generateResult) +
" Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
exceptionInfo.put(generateResult.getString("task_id"), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
long end = System.currentTimeMillis();
log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start));
log.info("============ProcessPoseTransformResult End listening==========");
}
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
// @RabbitHandler
// public void generateConsumer1(Message msg, Channel channel) {
// 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) {
// processDesignBatchResult(msg, channel);
// }
// @RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageBatch}")
// @RabbitHandler
// public void getToProductImageBatchResult(Message msg, Channel channel) {
// processToProductImageBatchResult(msg, channel);
// }
//
// @RabbitListener(queues = "#{rabbitMQProperties.queues.relightBatch}")
// @RabbitHandler
// public void getRelightBatchResult(Message msg, Channel channel) {
// processRelightBatchResult(msg, channel);
// }
//
// @RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransformBatch}")
// @RabbitHandler
// public void getPoseTransformBatchResult(Message msg, Channel channel) {
// processPoseTransformBatchResult(msg, channel);
// }
}

View File

@@ -1,82 +0,0 @@
package com.ai.da.common.RabbitMQ;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MQConfig {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Bean
public Queue generateQueue() {
return new Queue(rabbitMQProperties.getQueues().getGenerate());
}
@Bean
public Queue SRQueue() {
return new Queue(rabbitMQProperties.getQueues().getSr());
}
@Bean
public Queue SRResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getSrResult());
}
@Bean
public Queue generateResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getGenerateResult());
}
@Bean
public Queue toProductImageResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getToProductImageResult());
}
@Bean
public Queue relightResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getRelightResult());
}
@Bean
public Queue poseTransformQueue() {
return new Queue(rabbitMQProperties.getQueues().getPoseTransform());
}
@Bean
public Queue mailRetryQueue() {
// 普通队列不绑定DLX首次失败后才进入MQ
// durable 持久化队列
return QueueBuilder.durable(rabbitMQProperties.getQueues().getEmailRetry())
// 关键参数:绑定死信交换机
.withArgument("x-dead-letter-exchange", rabbitMQProperties.getDeadLetter().getExchange())
// 可选:指定死信路由键(默认使用原消息的路由键)
.withArgument("x-dead-letter-routing-key", rabbitMQProperties.getDeadLetter().getRoutingKey())
.build();
}
// 新增死信交换机
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange(rabbitMQProperties.getDeadLetter().getExchange());
}
// 新增死信队列
@Bean
public Queue deadLetterQueue() {
return QueueBuilder.durable(rabbitMQProperties.getDeadLetter().getQueue()).build();
}
// 绑定死信队列
@Bean
public Binding deadLetterBinding() {
return BindingBuilder.bind(deadLetterQueue())
.to(deadLetterExchange())
.with(rabbitMQProperties.getDeadLetter().getRoutingKey());
}
}

View File

@@ -1,61 +0,0 @@
package com.ai.da.common.RabbitMQ;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Map;
@Slf4j
@Component
public class MQPublisher {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Autowired
private AmqpTemplate amqpTemplate;
public void sendGenerateMessage(String mm) {
log.info("send generate message: {}", mm);
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getGenerate(), mm);
}
public void sendSRMessage(String mm) {
log.info("send message: {}", 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 含有的字段
* {"dto": basicEmailParamDTO, "filename": fileName, "source": inputStreamSource,
* "templateParams": jsonObject, "templatePath": path}
* 邮件发送参数,附件文件名,附件数据
* @param retryTimes 重试次数初始为0
*/
public void sendEmailMsg(Map<String, String> mailParams, int retryTimes){
log.info("send email MQ message: {} ", mailParams);
// // 重新入队(指数退避) 时间单位:毫秒
long newDelay = (long) (5000 * Math.pow(2, retryTimes + 1));
log.info("send email MQ delay: {} ms, retry attempt: {}", newDelay, retryTimes + 1);
amqpTemplate.convertAndSend(
rabbitMQProperties.getQueues().getEmailRetry(),
mailParams,
m -> {
m.getMessageProperties().setExpiration(String.valueOf(newDelay));
m.getMessageProperties().setHeader("x-retry-attempt", retryTimes + 1);
return m;
}
);
}
}

View File

@@ -1,45 +0,0 @@
package com.ai.da.common.RabbitMQ;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "rabbitmq")
@Data
public class RabbitMQProperties {
private Queues queues;
private Exchange exchange;
private DeadLetter deadLetter; // 新增死信配置
@Data
public static class Queues {
private String generate;
private String sr;
private String srResult;
private String generateResult;
private String toProductImageResult;
private String relightResult;
private String poseTransform;
private String emailRetry;
private String designBatch;
private String relightBatch;
private String toProductImageBatch;
private String poseTransformBatch;
}
@Data
public static class Exchange {
private String generate;
}
// 新增死信配置内部类
@Data
public static class DeadLetter {
private String exchange;
private String queue;
private String routingKey;
}
}

View File

@@ -1,237 +0,0 @@
package com.ai.da.common.RabbitMQ;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.model.dto.SuperResolutionDTO;
import com.ai.da.model.dto.TaskDTO;
import com.ai.da.service.SuperResolutionService;
import com.ai.da.service.TaskListService;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
@Slf4j
@Component
public class SRConsumer {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Resource
private RedisUtil redisUtil;
@Resource
private TaskListService taskListService;
@Value("${redis.key.orderForSR}")
private String consumptionOrderKey;
@Value("${redis.key.SRCancelSet}")
private String cancelSetKey;
@Value("${redis.key.SRExceptionMap}")
private String exceptionMapKey;
@Value("${redis.key.taskList}")
private String taskListKey;
@Resource
private SuperResolutionService superResolutionService;
/**
* 请求超分处理
*/
public void superResolution(Message msg, Channel channel, String consumerName) {
log.info("============SR start listening==========");
long start = System.currentTimeMillis();
SuperResolutionDTO superResolutionDTO;
String uniqueId = null;
try {
superResolutionDTO = JSONObject.parseObject(msg.getBody(), SuperResolutionDTO.class);
uniqueId = superResolutionDTO.getUniqueId();
log.info("From " + consumerName + " : " + uniqueId);
superResolutionService.updateSROutput(uniqueId, "Executing", null);
taskListService.updateTaskStatusOrOutputRedis(uniqueId, "Executing", null);
/*try {
Thread.sleep(2 * 60 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}*/
// 2、判断当前消息是否在取消列表中
Boolean isMember = redisUtil.isElementExistsInSet(cancelSetKey, uniqueId);
if (isMember) {
try {
// 2.1 手动确认该消息
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException ex) {
log.error("手动确认,不返回队列重新消费");
}
} else {
// 请求python端进行超分
superResolutionService.SR(superResolutionDTO);
}
} catch (BusinessException e) {
log.error(e.getMsg());
superResolutionDTO = JSONObject.parseObject(msg.getBody(), SuperResolutionDTO.class);
// channel.basicNack() 为不确认deliveryTag对应的消息第二个参数是否应用于多消息第三个参数是否requeue
setErrorMessage(msg, channel, e.getMsg(), superResolutionDTO);
try {
// 2.1 手动确认该消息
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException ex) {
log.error("手动确认,不返回队列重新消费, error message : " + e.getMessage());
}
} catch (JSONException e) {
log.error(e.getMessage());
setErrorMessage(msg, channel, e.getMessage(), null);
try {
// 2.1 手动确认该消息
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException ex) {
log.error("手动确认,不返回队列重新消费, error message : " + e.getMessage());
}
} catch (Exception e) {
log.error(e.getMessage());
superResolutionDTO = JSONObject.parseObject(msg.getBody(), SuperResolutionDTO.class);
setErrorMessage(msg, channel, e.getMessage(), superResolutionDTO);
try {
// 2.1 手动确认该消息
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException ex) {
log.error("手动确认,不返回队列重新消费, error message : " + e.getMessage());
}
}
long end = System.currentTimeMillis();
log.info(" task_id " + uniqueId + "----------" + consumerName + " 执行时长:" + (end - start) + "毫秒");
log.info("=============SR end listening===========");
}
/**
* 获取超分结果
*/
public void getSRResult(Message msg, Channel channel, String consumerName) {
log.info("============SRResult start listening==========");
long start = System.currentTimeMillis();
JSONObject result = null;
String taskId = null;
try {
result = JSONObject.parseObject(msg.getBody(), JSONObject.class);
log.info("SR response : {}", result);
taskId = result.get("tasks_id").toString();
} catch (JSONException e) {
log.error("SRResult 返回数据格式不合规范");
log.error(e.getMessage());
setErrorMessage(msg, channel, e.getMessage(), null);
try {
// 第二个参数是否批量确认消息当传false时只确认当前 deliveryTag对应的消息;当传true时会确认当前及之前所有未确认的消息。
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
} catch (Exception e){
log.error(e.getMessage());
setErrorMessage(msg, channel, e.getMessage(), null);
try {
// 第二个参数是否批量确认消息当传false时只确认当前 deliveryTag对应的消息;当传true时会确认当前及之前所有未确认的消息。
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
}
try {
// 2、判断状态是否成功
if ("SUCCESS".equals(result.get("status").toString())) {
String output = result.get("data").toString();
superResolutionService.setSRResult(taskId, output, "success");
taskListService.updateTaskStatusOrOutputRedis(taskId, "success", output);
} else {
superResolutionService.setSRResult(taskId, null, "fail");
taskListService.updateTaskStatusOrOutputRedis(taskId, "fail", null);
HashMap<String, String> exceptionInfo = new HashMap<>();
// 获取输入信息
String task = redisUtil.getFromString(taskListKey + taskId + taskId.substring(taskId.lastIndexOf("-") + 1));
Gson gson = new Gson();
Type type = new TypeToken<TaskDTO<SuperResolutionDTO>>() {
}.getType();
TaskDTO<SuperResolutionDTO> taskDTO = gson.fromJson(task, type);
// 将输入信息和报错信息均存入redis todo 加判空
exceptionInfo.put(taskId, "Input ==> " + taskDTO.getInputParam() + "Fail Message ==> " + result.get("message").toString());
// 将报错信息存入redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
}
} catch (Exception e) {
log.error(e.getMessage());
// channel.basicNack() 为不确认deliveryTag对应的消息第二个参数是否应用于多消息第三个参数是否requeue
try {
// 第二个参数是否批量确认消息当传false时只确认当前 deliveryTag对应的消息;当传true时会确认当前及之前所有未确认的消息。
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (IOException exception) {
log.error("手动确认,取消返回队列,不再重新消费");
}
}
long end = System.currentTimeMillis();
log.info(" task_id " + taskId + "----------" + consumerName + " 执行时长:" + (end - start) + "毫秒");
log.info("=============SRResult end listening===========");
}
private void setErrorMessage(Message msg, Channel channel, String message, SuperResolutionDTO superResolutionDTO) {
String uniqueId;
try {
// 第二个参数是否批量确认消息当传false时只确认当前 deliveryTag对应的消息;当传true时会确认当前及之前所有未确认的消息。
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
uniqueId = superResolutionDTO.getUniqueId();
// 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除
redisUtil.removeFromZSet(consumptionOrderKey, uniqueId);
} catch (Exception exception) {
log.error("手动确认,取消返回队列,不再重新消费");
throw new BusinessException("message.confirm.fail");
}
// 将入参和错误信息存入redis
String exceptionMessage = JSONObject.toJSONString(superResolutionDTO) +
" Exception message " + message;
// " Exception message " + e.getMessage();
HashMap<String, String> exceptionInfo = new HashMap<>();
uniqueId = superResolutionDTO.getUniqueId();
exceptionInfo.put(String.valueOf(uniqueId), exceptionMessage);
// 存redis
redisUtil.addToMap(exceptionMapKey, exceptionInfo);
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");
// }
}

View File

@@ -1,170 +0,0 @@
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

@@ -1,43 +0,0 @@
package com.ai.da.common.config;
import com.alipay.api.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import jakarta.annotation.Resource;
@Configuration
//加载配置文件
@PropertySource("classpath:alipay-sandbox.properties")
public class AlipayClientConfig {
@Resource
private Environment config;
@Bean
public AlipayClient alipayClient() throws AlipayApiException {
AlipayConfig alipayConfig = new AlipayConfig();
//设置网关地址
alipayConfig.setServerUrl(config.getProperty("alipay.gateway-url"));
//设置应用Id
alipayConfig.setAppId(config.getProperty("alipay.app-id"));
//设置应用私钥
alipayConfig.setPrivateKey(config.getProperty("alipay.merchant-private-key"));
//设置请求格式固定值json
alipayConfig.setFormat(AlipayConstants.FORMAT_JSON);
//设置字符集
alipayConfig.setCharset(AlipayConstants.CHARSET_UTF8);
//设置支付宝公钥
alipayConfig.setAlipayPublicKey(config.getProperty("alipay.alipay-public-key"));
//设置签名类型
alipayConfig.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
//构造client
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
return alipayClient;
}
}

View File

@@ -1,21 +0,0 @@
package com.ai.da.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class AsyncConfig {
@Bean("asyncTaskExecutor")
public Executor asyncTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Async-ImageToSketch-");
executor.initialize();
return executor;
}
}

View File

@@ -1,393 +0,0 @@
package com.ai.da.common.config;
import com.ai.da.mapper.primary.entity.CustomerData;
import com.ai.da.mapper.primary.entity.TransactionData;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class CRMReportInterface {
// JDBC 驱动器名称以及数据库 URL
static final String JDBC_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
static final String DB_URL = "jdbc:sqlserver://118.142.0.178:1550;databaseName=Hayman_prod";
// 数据库凭据
static final String USER = "user01";
static final String PASS = "haySIS-2302";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 注册 JDBC 驱动器
Class.forName(JDBC_DRIVER);
// 打开一个连接
System.out.println("连接数据库...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// 执行查询步骤1: 生成 RW0095 报告以获取客户完整数据
System.out.println("执行步骤1生成 RW0095 报告...");
// 执行相应的查询并获取数据
// List<CustomerData> customerData = retrieveCustomerData();
// 执行查询步骤2: 使用 MZG013 报告检查客户的销售历史
System.out.println("执行步骤2使用 MZG013 报告检查客户的销售历史...");
// 执行相应的查询并获取数据
List<TransactionData> transactionData = retrieveTransactionData();
List<String> collect = transactionData.stream().map(TransactionData::getUserMember).collect(Collectors.toList());
List<CustomerData> customerData = retrieveCustomerData(collect);
for (TransactionData transactionDatum : transactionData) {
for (CustomerData customerDatum : customerData) {
if (customerDatum.getMbrCode().equals(transactionDatum.getUserMember())) {
customerDatum.setLastMonth(transactionDatum.getSumAmt());
break;
}
}
}
// 执行步骤3: 合并vlookupRW0095中的客户购买金额
System.out.println("执行步骤3合并客户购买金额...");
// 执行相应的操作如vlookup
// 执行步骤4: 按“发行店”筛选以分离不同文件并逐个发送给店铺
System.out.println("执行步骤4按发行店筛选并发送文件给店铺...");
// 执行相应的操作,如过滤和导出
String filePath = "C:\\Users\\10233\\Desktop\\CRM.csv";
exportToCSV(customerData, filePath);
// 关闭连接
conn.close();
} catch (SQLException se) {
// 处理 JDBC 错误
se.printStackTrace();
} catch (Exception e) {
// 处理 Class.forName 错误
e.printStackTrace();
} finally {
// 关闭资源
try {
if (stmt != null) stmt.close();
} catch (SQLException se2) {
} // 什么都不做
try {
if (conn != null) conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
System.out.println("接口执行完成!");
}
private static void exportToCSV(List<CustomerData> customerDataList, String filePath) throws IOException {
FileWriter writer = new FileWriter(filePath);
// // 写入 CSV 文件的第一行,即字段名
// writer.append("User Member,Mbr Name,Sh Code,Sum Amt\n");
//
// // 遍历数据列表,并将每一行数据写入 CSV 文件
// for (TransactionData transaction : transactionDataList) {
// writer.append(transaction.getUserMember()).append(",");
// writer.append(transaction.getMbrName()).append(",");
// writer.append(transaction.getShCode()).append(",");
// writer.append(String.valueOf(transaction.getSumAmt())).append("\n");
// }
writer.append("mbrCode,mbrName,mbrMobile,mbrGroup,mbrStatus,joinDate,mbrIssue,birthMonth,mbrSex,offBonus,effBonus,sumBonus,lastMonth\n");
// 遍历 customerDataList并将数据写入 CSV 文件
for (CustomerData customer : customerDataList) {
writer.append(customer.getMbrCode()).append(",");
writer.append(customer.getMbrName()).append(",");
writer.append(customer.getMbrMobile()).append(",");
writer.append(customer.getMbrGroup()).append(",");
writer.append(customer.getMbrStatus()).append(",");
writer.append(customer.getJoinDate().toString()).append(","); // 日期需要根据实际情况格式化
writer.append(customer.getMbrIssue()).append(",");
writer.append(Integer.toString(customer.getBirthMonth())).append(",");
writer.append(customer.getMbrSex()).append(",");
writer.append(Double.toString(customer.getOffBonus())).append(",");
writer.append(Double.toString(customer.getEffBonus())).append(",");
writer.append(Double.toString(customer.getSumBonus())).append(",");
writer.append(Double.toString(customer.getLastMonth())).append("\n");
}
writer.close();
}
public static List<CustomerData> retrieveCustomerData(List<String> collect) {
List<CustomerData> customerDataList = new ArrayList<>();
Connection conn = null;
Statement stmt = null;
try {
// 注册 JDBC 驱动器
Class.forName(JDBC_DRIVER);
// 打开一个连接
System.out.println("连接数据库...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// 执行查询
System.out.println("创建声明...");
stmt = conn.createStatement();
String sql;
// 构建 IN 子句的字符串,用于添加到 SQL 查询中
StringBuilder inClause = new StringBuilder("(");
for (String code : collect) {
inClause.append("'").append(code).append("',");
}
inClause.deleteCharAt(inClause.length() - 1); // 删除最后一个逗号
inClause.append(")");
// 构建完整的 SQL 查询语句
sql = "SELECT * FROM V_RW0095B WHERE mbr_code IN " + inClause.toString();
ResultSet rs = stmt.executeQuery(sql);
// 处理结果集
while (rs.next()) {
// 将每行数据转换为 CustomerData 对象并添加到列表中
CustomerData customer = new CustomerData();
customer.setMbrCode(rs.getString("mbr_code"));
customer.setMbrName(rs.getString("mbr_name"));
customer.setMbrMobile(rs.getString("mbr_mobile"));
customer.setMbrGroup(rs.getString("mbr_group"));
customer.setMbrStatus(rs.getString("mbr_status"));
customer.setJoinDate(rs.getDate("join_date"));
customer.setMbrIssue(rs.getString("mbr_issue"));
customer.setBirthMonth(rs.getInt("birth_m"));
customer.setMbrSex(rs.getString("mbr_sex"));
customer.setOffBonus(rs.getDouble("off_bonus"));
customer.setEffBonus(rs.getDouble("eff_bonus"));
customer.setSumBonus(rs.getDouble("sum_bonus"));
customerDataList.add(customer);
}
// 清理环境
rs.close();
stmt.close();
conn.close();
} catch (SQLException se) {
// 处理 JDBC 错误
se.printStackTrace();
} catch (Exception e) {
// 处理 Class.forName 错误
e.printStackTrace();
} finally {
// 关闭资源
try {
if (stmt != null) stmt.close();
} catch (SQLException se2) {
} // 什么都不做
try {
if (conn != null) conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
System.out.println("查询执行完成!");
return customerDataList;
}
public static List<TransactionData> retrieveTransactionData() {
List<TransactionData> transactionDataList = new ArrayList<>();
Connection conn = null;
Statement stmt = null;
try {
// 注册 JDBC 驱动器
Class.forName(JDBC_DRIVER);
// 打开一个连接
System.out.println("连接数据库...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// 执行查询
System.out.println("创建声明...");
stmt = conn.createStatement();
String sql;
sql = "SELECT user_member,mbr_name,sum(trx_bas_amt) sumAmtByMebBySh FROM V_MZG013\n" +
"WHERE trx_date >= DATEADD(day, -7, GETDATE())\n" +
"and user_member is not NULL\n" +
"GROUP BY user_member,mbr_name";
ResultSet rs = stmt.executeQuery(sql);
// 处理结果集
while (rs.next()) {
// 将每行数据转换为 TransactionData 对象并添加到列表中
TransactionData transaction = new TransactionData();
transaction.setUserMember(rs.getString("user_member"));
transaction.setMbrName(rs.getString("mbr_name"));
// transaction.setShCode(rs.getString("sh_code"));
transaction.setSumAmt(rs.getDouble("sumAmtByMebBySh"));
// transaction.setTrxNo(rs.getString("trx_no"));
// transaction.setTrxDate(rs.getTimestamp("trx_date"));
// transaction.setTrxType(rs.getString("trx_type"));
// transaction.setTrxStatus(rs.getString("trx_status"));
// transaction.setTrxTotQty(rs.getDouble("trx_tot_qty"));
// transaction.setCurrCode(rs.getString("curr_code"));
// transaction.setExchRate(rs.getDouble("exch_rate"));
// transaction.setDiscountPerc(rs.getDouble("discount_perc"));
// transaction.setTrxAccAmt(rs.getDouble("trx_acc_amt"));
// transaction.setTrxBasAmt(rs.getDouble("trx_bas_amt"));
// transaction.setOutstandAmt(rs.getDouble("outstand_amt"));
// transaction.setReceiveAmt(rs.getDouble("receive_amt"));
// transaction.setChangeAmt(rs.getDouble("change_amt"));
// transaction.setTrxTotBonus(rs.getDouble("trx_tot_bonus"));
// transaction.setDepositNo(rs.getString("deposit_no"));
// transaction.setDepositAmt(rs.getDouble("deposit_amt"));
// transaction.setDepositStatus(rs.getString("deposit_status"));
// transaction.setTrxAmtDesc(rs.getString("trx_amt_desc"));
// transaction.setRemark(rs.getString("remark"));
// transaction.setShCode(rs.getString("sh_code"));
// transaction.setWhCodeFrom(rs.getString("wh_code_from"));
// transaction.setWhCodeTo(rs.getString("wh_code_to"));
// transaction.setIssuedBy(rs.getString("issued_by"));
// transaction.setClientCode(rs.getString("client_code"));
// transaction.setClientName(rs.getString("client_name"));
// transaction.setSalesmanCode(rs.getString("salesman_code"));
// transaction.setCtypeCode(rs.getString("ctype_code"));
// transaction.setUpdatedOn(rs.getTimestamp("updated_on"));
// transaction.setDocType(rs.getString("doc_type"));
// transaction.setRefNo(rs.getString("ref_no"));
// transaction.setAdjType(rs.getString("adj_type"));
// transaction.setRefType(rs.getString("ref_type"));
// transaction.setOrderNo(rs.getString("order_no"));
// transaction.setRecoverF(rs.getString("recover_f"));
// transaction.setRecoverT(rs.getString("recover_t"));
// transaction.setRequestBy(rs.getString("request_by"));
// transaction.setError(rs.getString("error"));
// transaction.setAuthorizedDate(rs.getTimestamp("authorized_date"));
// transaction.setAuthorizedBy(rs.getString("authorized_by"));
// transaction.setChangeCurrCode(rs.getString("change_curr_code"));
// transaction.setChgRate(rs.getDouble("chg_rate"));
// transaction.setCashier(rs.getString("cashier"));
// transaction.setCashiNo(rs.getString("cashi_no"));
// transaction.setSalesmanCode2(rs.getString("salesman_code2"));
// transaction.setClassId(rs.getString("class_id"));
// transaction.setDisAmt(rs.getDouble("dis_amt"));
// transaction.setAcStatus(rs.getString("ac_status"));
// transaction.setReprint(rs.getString("reprint"));
// transaction.setAlt1(rs.getString("alt_1"));
// transaction.setAlt2(rs.getString("alt_2"));
// transaction.setAlt3(rs.getString("alt_3"));
// transaction.setAlt4(rs.getString("alt_4"));
// transaction.setAlt5(rs.getString("alt_5"));
// transaction.setAltD1(rs.getDate("alt_d1"));
// transaction.setAltD2(rs.getDate("alt_d2"));
// transaction.setAltD3(rs.getDate("alt_d3"));
// transaction.setAltD4(rs.getDate("alt_d4"));
// transaction.setAltD5(rs.getDate("alt_d5"));
// transaction.setSalesmanCode3(rs.getString("salesman_code3"));
// transaction.setContractNo(rs.getString("contract_no"));
// transaction.setExpireDate(rs.getTimestamp("expire_date"));
// transaction.setDepositNetAmt(rs.getDouble("deposit_netamt"));
// transaction.setClientRestriction(rs.getString("client_restriction"));
// transaction.setRefStatus(rs.getString("ref_status"));
// transaction.setMbrDis(rs.getDouble("mbr_dis"));
// transaction.setPmtDiscount(rs.getDouble("pmt_discount"));
// transaction.setPmtAmount(rs.getDouble("pmt_amount"));
// transaction.setPmtNo(rs.getString("pmt_no"));
// transaction.setRefCode(rs.getString("ref_code"));
// transaction.setDocApproved(rs.getString("doc_approved"));
// transaction.setRefractionNo(rs.getString("refraction_no"));
// transaction.setCcpTot(rs.getDouble("ccp_tot"));
// transaction.setCcpRed(rs.getDouble("ccp_red"));
// transaction.setCcpExpired(rs.getDouble("ccp_expired"));
// transaction.setPrintedTimes(rs.getInt("printed_times"));
// transaction.setPickupShop(rs.getString("pickup_shop"));
// transaction.setDeliveryDate(rs.getDate("delivery_date"));
// transaction.setDeliveryTime(rs.getString("delivery_time"));
// transaction.setWsCode(rs.getString("ws_code"));
// transaction.setClCode(rs.getString("cl_code"));
// transaction.setClDesc(rs.getString("cl_desc"));
// transaction.setRatio(rs.getString("ratio"));
// transaction.setUserMember(rs.getString("user_member"));
// transaction.setHflag(rs.getString("hflag"));
// transaction.setIssueShop(rs.getString("issue_shop"));
// transaction.setHoUpdBy(rs.getString("ho_upd_by"));
// transaction.setHoUpdOn(rs.getTimestamp("ho_upd_on"));
// transaction.setBonusExpired(rs.getDouble("bonus_expired"));
// transaction.setBonusRed(rs.getDouble("bonus_red"));
// transaction.setConfirmedOn(rs.getTimestamp("confirmed_on"));
// transaction.setConfirmedBy(rs.getString("confirmed_by"));
// transaction.setDocConfirmed(rs.getString("doc_confirmed"));
// transaction.setBrNo(rs.getString("br_no"));
// transaction.setChangeAmt2(rs.getDouble("change_amt2"));
// transaction.setSalesDate(rs.getDate("sales_date"));
// transaction.setMbrName(rs.getString("mbr_name"));
// transaction.setCanEntryDis(rs.getString("can_entry_dis"));
// transaction.setReactiveClient(rs.getString("reactive_client"));
// transaction.setReactiveMbr(rs.getString("reactive_mbr"));
// transaction.setShUpdBy(rs.getString("sh_upd_by"));
// transaction.setShUpdOn(rs.getTimestamp("sh_upd_on"));
// transaction.setTax1(rs.getDouble("tax1"));
// transaction.setTax2(rs.getDouble("tax2"));
// transaction.setTax3(rs.getDouble("tax3"));
// transaction.setTax4(rs.getDouble("tax4"));
// transaction.setTax5(rs.getDouble("tax5"));
// transaction.setAltChar1(rs.getString("alt_char1"));
// transaction.setAltChar2(rs.getString("alt_char2"));
// transaction.setAltChar3(rs.getString("alt_char3"));
// transaction.setAltChar4(rs.getString("alt_char4"));
// transaction.setAltChar5(rs.getString("alt_char5"));
// transaction.setAltNum1(rs.getDouble("alt_num1"));
// transaction.setAltNum2(rs.getDouble("alt_num2"));
// transaction.setAltNum3(rs.getDouble("alt_num3"));
// transaction.setAltNum4(rs.getDouble("alt_num4"));
// transaction.setAltNum5(rs.getDouble("alt_num5"));
// transaction.setNewClient(rs.getString("new_client"));
// transaction.setNewMbr(rs.getString("new_mbr"));
// transaction.setPmtExtraDiscount(rs.getDouble("pmt_extra_discount"));
// transaction.setPmtExtraAmount(rs.getDouble("pmt_extra_amount"));
// transaction.setManualDiscount(rs.getDouble("manual_discount"));
// transaction.setManualAmount(rs.getDouble("manual_amount"));
// transaction.setUsermbrDiscount(rs.getDouble("usermbr_discount"));
// transaction.setClientDiscount(rs.getDouble("client_discount"));
// transaction.setHoldVoid(rs.getString("hold_void"));
// transaction.setPayBasAmt(rs.getDouble("pay_bas_amt"));
// transaction.setPayDesc(rs.getString("pay_desc"));
// transaction.setPayCode(rs.getString("pay_code"));
// transaction.setCardNo(rs.getString("card_no"));
// transaction.setPayCurr(rs.getString("pay_curr"));
// transaction.setPayCurrAmt(rs.getDouble("pay_curr_amt"));
// transaction.setOnbehalfPaid(rs.getString("onbehalf_paid"));
// transaction.setOnbehalfLoc(rs.getString("onbehalf_loc"));
// transaction.setOldCardNo(rs.getString("old_card_no"));
// transaction.setTrxYear(rs.getInt("TRX_YEAR"));
// transaction.setTrxMonth(rs.getInt("TRX_MONTH"));
transactionDataList.add(transaction);
}
// 清理环境
rs.close();
stmt.close();
conn.close();
} catch (SQLException | ClassNotFoundException e) {
// 处理异常
e.printStackTrace();
}
System.out.println("查询执行完成!");
return transactionDataList;
}
// 示例导出数据到CSV文件
private static void exportToCSV(ResultSet resultSet, String filePath) throws SQLException, IOException {
FileWriter writer = new FileWriter(filePath);
while (resultSet.next()) {
// 将结果写入CSV文件
// 这里需要根据实际情况将数据写入CSV文件
}
writer.close();
}
}

View File

@@ -20,26 +20,25 @@ public class FileProperties {
private String linuxDomain; private String linuxDomain;
public ElPath getSys() { public ElPath getSys(){
String os = System.getProperty("os.name"); String os = System.getProperty("os.name");
if (os.toLowerCase().startsWith("win")) { if(os.toLowerCase().startsWith("win")) {
return windows; return windows;
} else if (os.toLowerCase().startsWith("mac")) { } else if(os.toLowerCase().startsWith("mac")){
return mac; return mac;
} }
return linux; return linux;
} }
public String getLinuxDomain(){
public String getLinuxDomain() {
String os = System.getProperty("os.name"); String os = System.getProperty("os.name");
if ((!os.toLowerCase().startsWith("win")) && (!os.toLowerCase().startsWith("mac"))) { if((!os.toLowerCase().startsWith("win") )&& (!os.toLowerCase().startsWith("mac"))) {
return linuxDomain; return linuxDomain;
} }
return null; return null;
} }
@Data @Data
public static class ElPath { public static class ElPath{
private String path; private String path;
} }
} }

View File

@@ -1,34 +0,0 @@
package com.ai.da.common.config;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Data
@Component
public class MinIoClientConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
/**
* 注入minio 客户端
*
* @return
*/
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +0,0 @@
package com.ai.da.common.config;
import com.paypal.core.PayPalEnvironment;
import com.paypal.core.PayPalHttpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@Slf4j
@PropertySource("classpath:payment.properties")
public class PayPalClient {
public PayPalHttpClient client(String mode, String clientId, String clientSecret) {
log.info("mode={}, clientId={}, clientSecret={}", mode, clientId, clientSecret);
PayPalEnvironment environment = mode.equals("live") ? new PayPalEnvironment.Live(clientId, clientSecret) : new PayPalEnvironment.Sandbox(clientId, clientSecret);
return new PayPalHttpClient(environment);
}
/**
* @param jo
* @param pre
* @return
*/
/*public String prettyPrint(JSONObject jo, String pre) {
Iterator<?> keys = jo.keys();
StringBuilder pretty = new StringBuilder();
while (keys.hasNext()) {
String key = (String) keys.next();
pretty.append(String.format("%s%s: ", pre, StringUtils.capitalize(key)));
if (jo.get(key) instanceof JSONObject) {
pretty.append(prettyPrint(jo.getJSONObject(key), pre + "\t"));
} else if (jo.get(key) instanceof JSONArray) {
int sno = 1;
for (Object jsonObject : jo.getJSONArray(key)) {
pretty.append(String.format("\n%s\t%d:\n", pre, sno++));
pretty.append(prettyPrint((JSONObject) jsonObject, pre + "\t\t"));
}
} else {
pretty.append(String.format("%s\n", jo.getString(key)));
}
}
return pretty.toString();
}*/
}

View File

@@ -1,63 +0,0 @@
package com.ai.da.common.config;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.ai.da.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
@Autowired
private MybatisPlusProperties mybatisPlusProperties;
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(
@Qualifier("primaryDataSource") DataSource dataSource,
ApplicationContext applicationContext,
@Qualifier("primaryMybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(applicationContext.getResources("classpath:mapper/primary/*.xml"));
// 设置 MyBatis Plus 全局配置
GlobalConfig globalConfig = this.mybatisPlusProperties.getGlobalConfig();
if (globalConfig != null) {
bean.setGlobalConfig(globalConfig);
}
bean.setPlugins(mybatisPlusInterceptor);
return bean.getObject();
}
@Primary
@Bean(name = "primarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

View File

@@ -1,42 +0,0 @@
package com.ai.da.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer); // key的序列化类型
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 方法过期,改为下面代码
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value的序列化类型
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

View File

@@ -1,49 +0,0 @@
package com.ai.da.common.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.ai.da.mapper.secondary", sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(
@Qualifier("secondaryDataSource") DataSource dataSource,
ApplicationContext applicationContext,
@Qualifier("secondaryMybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
// SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(applicationContext.getResources("classpath:mapper/secondary/*.xml"));
bean.setPlugins(mybatisPlusInterceptor);
return bean.getObject();
}
@Bean(name = "secondarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

View File

@@ -1,34 +0,0 @@
package com.ai.da.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
/**
* Spring Security 配置。
* 由于鉴权逻辑已迁移至 GatewayGlobalAuthWebFilter
* 后端服务 (aida-back) 默认放行所有请求,仅依赖网关传递的用户信息。
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 禁用 CSRF微服务通常不需要
.csrf(AbstractHttpConfigurer::disable)
// 允许所有请求,具体鉴权在网关层完成
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
)
// 禁用默认的表单登录和 HTTP Basic 认证,防止 302 重定向
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable);
return http.build();
}
}

View File

@@ -1,260 +0,0 @@
package com.ai.da.common.config;
import com.ai.da.common.utils.MinioUtil;
import com.ai.da.mapper.primary.ThreeDDetailMapper;
import com.ai.da.mapper.primary.ThreeDLayoutMapper;
import com.ai.da.mapper.primary.ThreeDPatternLayoutMapper;
import com.ai.da.mapper.primary.ThreeDSimpleMapper;
import com.ai.da.mapper.primary.entity.ThreeDDetail;
import com.ai.da.mapper.primary.entity.ThreeDLayout;
import com.ai.da.mapper.primary.entity.ThreeDPatternLayout;
import com.ai.da.mapper.primary.entity.ThreeDSimple;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Slf4j
@Component
public class ThreeDSave {
@Resource
private ThreeDDetailMapper threeDDetailMapper;
@Resource
private ThreeDSimpleMapper threeDSimpleMapper;
@Resource
private MinioUtil minioUtil;
@Resource
private ThreeDLayoutMapper threeDLayoutMapper;
@Resource
private ThreeDPatternLayoutMapper threeDPatternLayoutMapper;
@PostConstruct
public void test() {
// minioSave();
// frontBackDataCreate();
// patternDataCreate();
}
private void patternDataCreate() {
QueryWrapper<ThreeDSimple> qw = new QueryWrapper<>();
qw.lambda().eq(ThreeDSimple::getGender, "female");
qw.lambda().ne(ThreeDSimple::getId, 1);
List<ThreeDSimple> threeDSimpleList = threeDSimpleMapper.selectList(qw);
List<Integer> numbers = new ArrayList<>();
String patternPath = "C:\\workspace\\3D\\3D虚拟 1-7\\6.版文件、dxf文件\\女装系列(1)\\女装系列\\56款打版截图";
File directory = new File(patternPath);
if (directory.exists() && directory.isDirectory()) {
// 获取目录下的所有文件名,并建立编号 -> 文件名的映射
Map<Integer, String> fileMap = Arrays.stream(directory.listFiles())
.filter(File::isFile) // 只获取文件
.map(File::getName) // 获取文件名
.collect(Collectors.toMap(
name -> {
Matcher matcher = Pattern.compile("^\\d+").matcher(name);
return matcher.find() ? Integer.parseInt(matcher.group()) : -1;
},
name -> name,
(existing, replacement) -> existing // 处理重复情况,保留原有值
));
for (ThreeDSimple threeDSimple : threeDSimpleList) {
String name = threeDSimple.getName();
Pattern pattern = Pattern.compile("^\\d+"); // 匹配开头的数字
Matcher matcher = pattern.matcher(name);
if (matcher.find()) {
int number = Integer.parseInt(matcher.group());
numbers.add(number);
// 匹配对应文件夹,并获取文件
if (fileMap.containsKey(number)) {
String matchedFolder = fileMap.get(number);
File folder = new File(directory, matchedFolder);
ThreeDPatternLayout threeDPatternLayout = new ThreeDPatternLayout();
threeDPatternLayout.setThreeDSimpleId(threeDSimple.getId());
threeDPatternLayout.setName(matchedFolder);
String minioUrl = "aida-threed/female/pattern-layout/" + matchedFolder;
minioUtil.upload(minioUrl, folder);
threeDPatternLayout.setUrl(minioUrl);
// threeDPatternLayoutMapper.insert(threeDPatternLayout);
}
}
}
System.out.println("文件编号映射:" + fileMap);
}
}
private void frontBackDataCreate() {
QueryWrapper<ThreeDSimple> qw = new QueryWrapper<>();
qw.lambda().eq(ThreeDSimple::getGender, "female");
// qw.lambda().ne(ThreeDSimple::getId, 1);
List<ThreeDSimple> threeDSimpleList = threeDSimpleMapper.selectList(qw);
List<Integer> numbers = new ArrayList<>();
// 文件夹名列表
String path = "C:\\workspace\\3D\\3D虚拟 1-7\\3D服装真反面整理\\female"; // 目标路径
File directory = new File(path);
if (directory.exists() && directory.isDirectory()) {
// 获取文件夹名列表,并建立编号 -> 文件夹名的映射
Map<Integer, String> folderMap = Arrays.stream(directory.listFiles())
.filter(File::isDirectory)
.map(File::getName)
.collect(Collectors.toMap(
name -> {
Matcher matcher = Pattern.compile("^\\d+").matcher(name);
return matcher.find() ? Integer.parseInt(matcher.group()) : -1;
},
name -> name,
(existing, replacement) -> existing // 处理重复情况,保留原有值
));
System.out.println("文件夹编号映射:" + folderMap);
for (ThreeDSimple threeDSimple : threeDSimpleList) {
String name = threeDSimple.getName();
Pattern pattern = Pattern.compile("^\\d+"); // 匹配开头的数字
Matcher matcher = pattern.matcher(name);
if (matcher.find()) {
int number = Integer.parseInt(matcher.group());
numbers.add(number);
// 匹配对应文件夹,并获取文件
if (folderMap.containsKey(number)) {
String matchedFolder = folderMap.get(number);
File folder = new File(directory, matchedFolder);
if (folder.exists() && folder.isDirectory()) {
for (File file : folder.listFiles()) {
String fileName = file.getName(); // 去掉后缀
ThreeDLayout threeDLayout = new ThreeDLayout();
threeDLayout.setGender("female");
threeDLayout.setThreeDSimpleId(threeDSimple.getId());
threeDLayout.setName(file.getName());
if (fileName.startsWith("")) {
threeDLayout.setType("front");
}else if (fileName.startsWith("")) {
threeDLayout.setType("back");
}
String minioUrl = "aida-threed/female/layout/" + folderMap.get(number) + " " + file.getName();
minioUtil.upload(minioUrl, file);
threeDLayout.setUrl(minioUrl);
// threeDLayoutMapper.insert(threeDLayout);
}
}
}
}
}
System.out.println(numbers);
} else {
System.out.println("路径不存在或不是文件夹");
}
}
private void minioSave() {
// 指定目标文件夹路径
String folderPath = "C:\\workspace\\3D\\3D虚拟 1-7\\3D服装整理\\maleZip";
// 创建文件对象
File folder = new File(folderPath);
// 检查文件夹是否存在且是目录
if (folder.exists() && folder.isDirectory()) {
// 获取所有 .zip 文件
File[] zipFiles = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".zip"));
List<String> zipFileNameList = new ArrayList<>();
// 输出文件名
if (zipFiles != null) {
for (File file : zipFiles) {
String zipFileName = file.getName();
String[] split = zipFileName.split("_");
String zipName = split[0];
String sizeWithSuffix = split[1];
String[] sizeWithSuffixSplit = sizeWithSuffix.split("\\.");
String size = sizeWithSuffixSplit[0];
// 找到第一个字母的位置
int index = 0;
while (index < size.length() && Character.UnicodeBlock.of(size.charAt(index)) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) {
index++;
}
if (index > 0 && index < size.length()) {
String prefix = size.substring(0, index); // "亚码"
String suffix = size.substring(index); // "L"
ThreeDDetail threeDDetail = new ThreeDDetail();
threeDDetail.setName(zipFileName);
String url = "aida-threed/male/zip/" + zipFileName;
threeDDetail.setGender("male");
threeDDetail.setSizeType(prefix);
threeDDetail.setSize(suffix);
threeDDetail.setUrl(url);
// threeDDetailMapper.insert(threeDDetail);
minioUtil.upload(url, file);
QueryWrapper<ThreeDSimple> qw = new QueryWrapper<>();
qw.lambda().eq(ThreeDSimple::getName, zipName);
qw.lambda().eq(ThreeDSimple::getGender, "male");
List<ThreeDSimple> threeDSimples = threeDSimpleMapper.selectList(qw);
if (CollectionUtils.isEmpty(threeDSimples)) {
ThreeDSimple threeDSimple = new ThreeDSimple();
threeDSimple.setName(zipName);
threeDSimple.setGender("male");
String glbPath = "C:\\workspace\\3D\\3D虚拟 1-7\\3D服装整理\\male\\" + zipName + "\\" +"亚码L";
File glbFolder = new File(glbPath);
// 查找 .glb 文件
if (glbFolder.exists() && glbFolder.isDirectory()) {
File[] glbFiles = glbFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".glb"));
if (glbFiles != null && glbFiles.length > 0) {
for (File glbFile : glbFiles) {
String name = glbFile.getName();
String glbUrl = "aida-threed/male/glb/" + name;
threeDSimple.setUrl(glbUrl);
minioUtil.upload(glbUrl, glbFile);
}
} else {
System.out.println("未找到 GLB 文件。" + glbFolder);
}
} else {
System.out.println("GLB 文件夹不存在: " + glbPath);
}
// threeDSimpleMapper.insert(threeDSimple);
threeDDetail.setThreeDSimpleId(threeDSimple.getId());
threeDDetailMapper.updateById(threeDDetail);
}else {
Long id = threeDSimples.get(0).getId();
threeDDetail.setThreeDSimpleId(id);
threeDDetailMapper.updateById(threeDDetail);
}
} else {
}
}
} else {
System.out.println("未找到 ZIP 文件。");
}
log.info("aaa");
} else {
System.out.println("文件夹不存在或不是一个目录。");
}
}
}

View File

@@ -1,38 +1,17 @@
package com.ai.da.common.config; package com.ai.da.common.config;
import com.ai.da.common.interceptor.UserContextInterceptor;
import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import jakarta.annotation.Resource; import javax.validation.Validation;
import jakarta.validation.Validation; import javax.validation.Validator;
import jakarta.validation.Validator; import javax.validation.ValidatorFactory;
import jakarta.validation.ValidatorFactory;
@Configuration @Configuration
public class WebConfig implements WebMvcConfigurer { public class WebConfig {
static final String ORIGINS[] = new String[]{"GET", "POST", "PUT", "DELETE"};
@Resource
private UserContextInterceptor userContextInterceptor;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOriginPatterns("*").allowCredentials(true).allowedMethods(ORIGINS).maxAge(3600);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userContextInterceptor)
.addPathPatterns("/**");
}
@Bean @Bean
public Validator validator() { public Validator validator() {

View File

@@ -1,19 +1,7 @@
package com.ai.da.common.config.exception; package com.ai.da.common.config.exception;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.response.ResultEnum; import com.ai.da.common.response.ResultEnum;
import com.ai.da.model.enums.Language;
import com.ai.da.model.vo.AuthPrincipalVo;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Objects;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/** /**
* @author: dangweijian * @author: dangweijian
@@ -21,55 +9,20 @@ import java.util.ResourceBundle;
* @create: 2020-01-01 17:24 * @create: 2020-01-01 17:24
**/ **/
@Data @Data
@Slf4j
public class BusinessException extends RuntimeException { public class BusinessException extends RuntimeException {
private Integer code; private Integer code;
private String msg; private String msg;
public BusinessException(ResultEnum resultEnum) { public BusinessException(ResultEnum resultEnum){
super(resultEnum.getMsg());
this.code = resultEnum.getCode(); this.code = resultEnum.getCode();
this.msg = getMessageFromResource(resultEnum.getMsg(), getUserLocale()); this.msg = resultEnum.getMsg();
} }
public BusinessException(String msg) { public BusinessException(String msg) {
super(msg);
this.code = ResultEnum.FAIL.getCode(); this.code = ResultEnum.FAIL.getCode();
this.msg = getMessageFromResource(msg, getUserLocale()); this.msg = msg;
}
public BusinessException(String msg, Integer code) {
this.code = code;
this.msg = getMessageFromResource(msg, getUserLocale());
}
public BusinessException(Throwable cause) {
this.code = ResultEnum.FAIL.getCode();
this.msg = getMessageFromResource(cause.getMessage(), getUserLocale());
}
private static Locale getUserLocale() {
AuthPrincipalVo userInfo = UserContext.getUserHolder();
if (Objects.isNull(userInfo)) {
return new Locale("en");
}
return new Locale(Language.valueOf(userInfo.getLanguage()).getValue());
}
public static String getMessageFromResource(String msg) {
return getMessageFromResource(msg, getUserLocale());
}
public static String getMessageFromResource(String msg, Locale userLocale) {
try (InputStream inputStream = BusinessException.class.getClassLoader().getResourceAsStream("messages_" + userLocale.getLanguage() + ".properties")) {
if (inputStream != null) {
ResourceBundle bundle = new PropertyResourceBundle(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
if (bundle.containsKey(msg)) {
return bundle.getString(msg);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return msg; // 如果找不到对应的资源文件,返回原始的消息
} }
} }

View File

@@ -4,13 +4,11 @@ import com.ai.da.common.response.Response;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.ai.da.common.response.ResultEnum; import com.ai.da.common.response.ResultEnum;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/** /**
* @author: dangweijian * @author: dangweijian
@@ -38,14 +36,6 @@ public class ExceptionCatch {
return Response.error(e.getCode(), e.getMsg()); 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 @ResponseBody
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public Response<String> exceptionCatch(Exception e) { public Response<String> exceptionCatch(Exception e) {
@@ -61,12 +51,11 @@ public class ExceptionCatch {
return Response.error(resultEnum.getCode(), resultEnum.getMsg()); return Response.error(resultEnum.getCode(), resultEnum.getMsg());
} }
} }
return Response.error(ResultEnum.ERROR.getCode(), e.getMessage() == null ? ResultEnum.ERROR.getMsg() : e.getMessage()); return Response.error(ResultEnum.ERROR.getCode(), e.getMessage()==null?ResultEnum.ERROR.getMsg():e.getMessage());
} }
/** /**
* 处理参数校验异常 * 处理参数校验异常
*
* @param e * @param e
* @return ResponseData * @return ResponseData
*/ */
@@ -74,22 +63,19 @@ public class ExceptionCatch {
@ExceptionHandler(BindException.class) @ExceptionHandler(BindException.class)
public Response<String> bindExceptionHandler(BindException e) { public Response<String> bindExceptionHandler(BindException e) {
log.error("参数错误bind{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); log.error("参数错误bind{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
BusinessException businessException = new BusinessException(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); return Response.fail(ResultEnum.FAIL.getCode(), e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
return Response.error(businessException.getCode(), businessException.getMsg());
} }
/** /**
* 处理参数校验异常 * 处理参数校验异常
*
* @param e * @param e
* @return ResponseData * @return ResponseData
*/ */
@ResponseBody @ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class) @ExceptionHandler(MethodArgumentNotValidException.class)
public Response<String> handleValidationException(MethodArgumentNotValidException e) { public Response<String> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
log.error("参数错误bind{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); log.error("参数错误bind{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
BusinessException businessException = new BusinessException(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); return Response.fail(ResultEnum.FAIL.getCode(), e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
return Response.error(businessException.getCode(), businessException.getMsg());
} }
//初始化,不可预知异常自定义错误编码 //初始化,不可预知异常自定义错误编码

View File

@@ -1,12 +0,0 @@
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");
}
}

View File

@@ -1,4 +1,4 @@
package com.ai.da.common.config; package com.ai.da.common.config.mybatis.plus;
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
@@ -8,17 +8,11 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@MapperScan("com.ai.da.mapper")
public class MybatisPlusConfig { public class MybatisPlusConfig {
@Bean(name = "primaryMybatisPlusInterceptor") @Bean
public MybatisPlusInterceptor primaryMybatisPlusInterceptor() { public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean(name = "secondaryMybatisPlusInterceptor")
public MybatisPlusInterceptor secondaryMybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor; return interceptor;

View File

@@ -22,7 +22,7 @@ import java.util.function.Function;
**/ **/
@Data @Data
@Slf4j @Slf4j
public abstract class QueryCriteria<T, E> { public abstract class QueryCriteria<T,E> {
private long page = 1; private long page = 1;
private long limit = 10; private long limit = 10;
@@ -36,12 +36,12 @@ public abstract class QueryCriteria<T, E> {
this.mapper = mapper; this.mapper = mapper;
} }
public QueryWrapper<T> buildWrapper() { public QueryWrapper<T> buildWrapper(){
QueryWrapper<T> wrapper = new QueryWrapper<>(); QueryWrapper<T> wrapper = new QueryWrapper<>();
Field[] fields = this.getClass().getDeclaredFields(); Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) { for (Field field : fields) {
Condition condition = field.getAnnotation(Condition.class); Condition condition = field.getAnnotation(Condition.class);
if (condition != null) { if(condition != null){
field.setAccessible(true); field.setAccessible(true);
Object value = null; Object value = null;
try { try {
@@ -49,27 +49,27 @@ public abstract class QueryCriteria<T, E> {
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
log.warn("reflection anomaly!"); log.warn("reflection anomaly!");
} }
if (!StrUtil.isEmptyIfStr(value)) { if(!StrUtil.isEmptyIfStr(value)){
switch (condition.type()) { switch (condition.type()){
case EQ: case EQ:
wrapper.eq(ConvertUtil.humpToLine2(field.getName()), value); wrapper.eq(ConvertUtil.humpToLine2(field.getName()), value);
break; break;
case LIKE: case LIKE:
wrapper.like(ConvertUtil.humpToLine2(field.getName()), value); wrapper.like(ConvertUtil.humpToLine2(field.getName()), value);
case BETWEEN: case BETWEEN:
if (value instanceof Collection && ((List) value).size() >= 2) { if(value instanceof Collection && ((List) value).size() >= 2){
wrapper.between(ConvertUtil.humpToLine2(field.getName()), ((List) value).get(0), ((List) value).get(1)); wrapper.between(ConvertUtil.humpToLine2(field.getName()), ((List)value).get(0), ((List)value).get(1));
} }
default: default:
} }
} else if (condition.isNull()) { }else if(condition.isNull()){
wrapper.isNull(ConvertUtil.humpToLine2(field.getName())); wrapper.isNull(ConvertUtil.humpToLine2(field.getName()));
} }
} }
Order order = field.getAnnotation(Order.class); Order order = field.getAnnotation(Order.class);
if (order != null) { if(order != null){
if (!StrUtil.isEmptyIfStr(order.order())) { if(!StrUtil.isEmptyIfStr(order.order())){
switch (order.order()) { switch (order.order()){
case DESC: case DESC:
wrapper.orderByDesc(ConvertUtil.humpToLine2(field.getName())); wrapper.orderByDesc(ConvertUtil.humpToLine2(field.getName()));
break; break;

View File

@@ -0,0 +1,37 @@
package com.ai.da.common.config.swagger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class AidaConfiguration {
@Bean(value = "IntelligentCurtainApis")
public Docket gxyd5aThemeApis() {
Contact contact = new Contact("Mr.Y","","136");
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.description("aida接口文档")
.contact(contact)
.termsOfServiceUrl("暂无")
.version("1.0")
.build())
//分组名称
.groupName("1.0")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.ai.da.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}

View File

@@ -1,9 +0,0 @@
package com.ai.da.common.constant;
public class AffiliateConstants {
public static final String STATUS_ACTIVE = "Active";
public static final String STATUS_INACTIVE = "Inactive";
public static final String STATUS_DELETE = "Delete";
public static final Integer DELETED = 1;
public static final Integer NOT_DELETED = 0;
}

View File

@@ -1,20 +0,0 @@
package com.ai.da.common.constant;
public class AlipayHKConstant {
// 服务名
public static final String CREATE_ORDER = "create_order";
public static final String ORDER_DETAILS = "order_details";
public static final String TRANSACTION_DETAILS = "transaction_details";
public static final String GET_FILE = "get_file";
public static final String CREATE_AUTO_DEBIT = "create_auto_debit";
public static final String REFRESH_TRANSACTION_STATUS = "refresh_transaction_status";
public static final String REFUND_TRANSACTION = "refund_transaction";
// 订单状态
public static final String STATUS_NEW = "new";
public static final String STATUS_WAIT = "wait";
public static final String STATUS_PAID = "paid";
public static final String STATUS_EXPIRED = "expired";
public static final String STATUS_LIQUIDATED = "liquidated";
}

View File

@@ -1,98 +0,0 @@
package com.ai.da.common.constant;
import java.util.Arrays;
import java.util.List;
public class CommonConstant {
// 单位 秒 10分钟过期
// public static final Long TASK_EXPIRE_TIME = 24 * 60 * 60L;
public static final Long TASK_EXPIRE_TIME = 10 * 60L;
// 单位 秒 两天过期
public static final Long CREDITS_EXPIRE_TIME = 2 * 24 * 60 * 60L;
// 单位 分钟
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天过期
public static final Long REDIS_SET_EXPIRE_TIME = 24 * 60 * 60 * 7L;
public static class Numbers{
public static final Integer NUMBER_10 = 10;
public static final Integer NUMBER_1000 = 1000;
public static final Integer NUMBER_10080 = 10080;
}
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_SLOGAN = "/api/slogan";
public static final String GENERATE_CANCEL = "/api/generate_cancel/";
public static final String GENERATE_LOGO_SINGLE_CANCEL = "/api/generate_single_logo_cancel/";
// public static final String POSE_TRANSFORMATION_CANCEL = "/api/pose_transform_cancel/";
public static final String POSE_TRANSFORMATION_CANCEL = "/api/comfyui_i_2_video_cancel/";
public static final String PYTHON_PORT_9996 = "9996";
public static final String PYTHON_PORT_9997 = "9997";
public static final List<String> AGES_EN = Arrays.asList("Below 20", "20-30", "30-40", "40+");
public static final List<String> AGES_CN = Arrays.asList("20岁以下", "20-30岁", "30-40岁", "40+岁");
public static final List<String> IF_HELPFUL_EN = Arrays.asList("Easy to learn and use", "Easy to get trend information",
"Lots of creative design proposals","The AIGC functions for moodboard is helpful","The AIGC functions for design sketches is helpful",
"Easy to select the right color","The Chatbot function is helpful","The print position function is helpful",
"The drawing function is helpful","The export function is useful","Easy to edit the design","Others");
public static final List<String> IF_HELPFUL_CN = Arrays.asList("易于学习和使用", "容易获取趋势信息",
"提供大量创意设计方案","AIGC功能对灵感板有帮助","AIGC功能对设计草图有帮助",
"容易选择合适的颜色","聊天机器人功能有帮助","打印位置功能有帮助",
"绘图功能有帮助","导出功能有用","设计编辑简单","其他");
public static final List<String> IF_IMPROVE_EN = Arrays.asList("Proposed designs are boring, need more interesting designs",
"Difficult to make changes on design","Only 2D output, no 3D results","Difficult to apply keywords for AIGC generation",
"Clothing is not in the right proportion","Not compatible with pattern making solutions","Improved user interface for better navigation",
"Lack of responsive customer support","Insufficient tutorial or guidance for new users","Limited personalization options for designs","Others");
public static final List<String> IF_IMPROVE_CN = Arrays.asList("提供的设计很无聊,需要更多有趣的设计",
"设计修改困难","只有2D输出没有3D结果","难以选择合适的关键词应用于AIGC生成",
"服装比例不正确","与打版解决方案不兼容","改进用户界面以便更好导航",
"客户支持响应不及时","对新用户的教程或指导不足","设计个性化选项有限","其他");
public static final List<String> IS_SUBSCRIBE = Arrays.asList("yes", "no");
// public static final String DEFAULT_AVATAR = "aida-users/87/avatar/default.jpg";
public static final String DEFAULT_AVATAR = "aida-users/87/avatar/default.png";
/* 截止至2024/08/26在Code-Create DB中pmr_users表中最大的用户id */
public static final Long MAXIMUM_USER_ID = 704L;
// public static final Long MAXIMUM_USER_ID = 225L;
// 激活更改邮箱 链接有效期 毫秒 3天
public static final Long CHANGE_MAILBOX_LINK_VALIDITY = 259200000L;
public static final String RCA_WORKSHOP_TAG = "#RCAworkshop_2024";
public static final String PORTFOLIO_DELETED_EN = "Portfolio has been deleted";
public static final String PORTFOLIO_DELETED_CN = "作品已删除";
public static final String TIME_FORMAT_MMM_dd_yyyy_EEEE = "MMM. dd, yyyy, EEEE";
public static final String TIME_FORMAT_MMM_dd_yyyy = "MMM. dd, yyyy";
public static final String TIME_FORMAT_yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
public static final String AFFILIATE_LINK = "https://www.aida.com.hk?ref=";
public static final String PARTIAL_DESIGN_FILENAME = "PartialDesign";
public static final String PARTIAL_DESIGN_PREVIEW_FILENAME = "Preview";
public static final String senderEmail = "info@aida.com.hk";
}

View File

@@ -1,42 +0,0 @@
package com.ai.da.common.constant;
/**
* 模型相关常量类
* 用于存放 chooseModelAndPrompt 方法中的字符串常量
*/
public class ModelConstants {
// 类型常量
public static final String PRINTBOARD = "Printboard";
public static final String MOODBOARD = "Moodboard";
public static final String SKETCHBOARD = "Sketchboard";
// 模型级别常量
public static final String ADVANCED = "advanced";
public static final String HIGH = "high";
public static final String NORMAL = "normal";
// 模型名称常量
public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image";
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";
public static final String NANO_BANANA = "gemini-2.5-flash-image";
public static final String LOCAL_MODEL = "local";
// 风格常量
public static final String PAINTING_STYLE = "Painting Style";
public static final String ILLUSTRATION_STYLE = "Illustration Style";
public static final String REAL_STYLE = "Real Style";
// 映射键
public static final String PROMPT = "prompt";
public static final String USE_MODEL = "UseModel";
// 防止实例化
private ModelConstants() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}

View File

@@ -1,173 +0,0 @@
package com.ai.da.common.constant;
public class PayPalCheckoutConstant {
public static final String CAPTURE = "CAPTURE";
/**
* 该标签将覆盖PayPal网站上PayPal帐户中的公司名称
*/
public static final String BRANDNAME = "AIDA";
/**
* LOGIN。当客户单击PayPal Checkout时客户将被重定向到页面以登录PayPal并批准付款。
* BILLING。当客户单击PayPal Checkout时客户将被重定向到一个页面以输入信用卡或借记卡以及完成购买所需的其他相关账单信息
* NO_PREFERENCE。当客户单击“ PayPal Checkout”时将根据其先前的交互方式将其重定向到页面以登录PayPal并批准付款或重定向至页面以输入信用卡或借记卡以及完成购买所需的其他相关账单信息使用PayPal。
* 默认值NO_PREFERENCE
*/
public static final String LANDINGPAGE = "NO_PREFERENCE";
/**
* CONTINUE。将客户重定向到PayPal付款页面后将出现“ 继续”按钮。当结帐流程启动时最终金额未知时,请使用此选项,并且您想将客户重定向到商家页面而不处理付款。
* PAY_NOW。将客户重定向到PayPal付款页面后出现“ 立即付款”按钮。当启动结帐时知道最终金额并且您要在客户单击“ 立即付款”时立即处理付款时,请使用此选项。
*/
public static final String USERACTION = "PAY_NOW";
/**
* GET_FROM_FILE。使用贝宝网站上客户提供的送货地址。
* NO_SHIPPING。从PayPal网站编辑送货地址。推荐用于数字商品
* SET_PROVIDED_ADDRESS。使用商家提供的地址。客户无法在PayPal网站上更改此地址
*/
// public static final String SHIPPINGPREFERENCE = "SET_PROVIDED_ADDRESS";
public static final String SHIPPINGPREFERENCE = "NO_SHIPPING";
/**
* 交易异常
*/
public static final String FAILURE = "failure";
/**
* 交易成功
*/
public static final String SUCCESS = "success";
/**
* ipn回调。支付成功
*/
public static final String PAYMENT_STATUS_COMPLETED = "Completed";
/**
* ipn回调。退款成功
*/
public static final String PAYMENT_STATUS_REFUNDED = "Refunded";
/**
* ipn回调。待定
*/
public static final String PAYMENT_STATUS_PENDING = "Pending";
/**
* ipn回调付款因退款或其他类型的冲销而被冲销。资金已从您的帐户余额中删除并退还给买方
*/
public static final String PAYMENT_STATUS_REVERSED = "Reversed";
/**
* ipn回调, 撤销已被取消。例如,您赢得了与客户的纠纷,并且撤回的交易资金已退还给您
*/
public static final String PAYMENT_STATUS_CANCELED_REVERSAL = "Canceled_Reversal";
/**
* ipn回调付款被拒绝
*/
public static final String PAYMENT_STATUS_DENIED = "Denied";
/**
* ipn回调 此授权已过期,无法捕获
*/
public static final String PAYMENT_STATUS_EXPIRED = "Expired";
/**
* ipn回调 德国的ELV付款是通过Express Checkout进行的
*/
public static final String PAYMENT_STATUS_CREATED = "Created";
/**
* ipn回调 付款失败。仅当付款是通过您客户的银行帐户进行的。
*/
public static final String PAYMENT_STATUS_FAILED = "Failed";
/**
* ipn回调付款已被接受
*/
public static final String PAYMENT_STATUS_PROCESSED = "Processed";
/**
* ipn回调此授权已失效
*/
public static final String PAYMENT_STATUS_VOIDED = "Voided";
//订单状态
/**
* 1、支付完成;捕获的付款的资金已记入收款人的PayPal帐户
* 2、退款完成;该交易的资金已记入客户的帐户
*/
public static final String STATE_COMPLETED = "COMPLETED";
/**
* 部分退款;少于所捕获付款金额的金额已部分退还给付款人。
*/
public static final String STATE_PARTIALLY_REFUNDED = "PARTIALLY_REFUNDED";
/**
* 1、支付待定;捕获的付款资金尚未记入收款人的PayPal帐户。有关更多信息请参见status.details。
* 2、退款待定;有关更多信息请参见status_details.reason。
*/
/**
* 支付待定:
* capture_status_details
* reason 枚举
* 捕获的付款状态为PENDING或DENIED的原因。可能的值为
* BUYER_COMPLAINT。付款人与贝宝PayPal对此捕获的付款提出了争议。
* CHARGEBACK。响应于付款人与用于支付此已捕获付款的金融工具的发行人对此已捕获的付款提出异议已收回的资金被撤回。
* ECHECK。由尚未结清的电子支票支付的付款人。
* INTERNATIONAL_WITHDRAWAL。访问您的在线帐户。在您的“帐户概览”中接受并拒绝此笔付款。
* OTHER。无法提供其他特定原因。有关此笔付款的更多信息请在线访问您的帐户或联系PayPal。
* PENDING_REVIEW。捕获的付款正在等待人工审核。
*手动收取RECEIVING_PREFERENCE_MANDATES_MANUAL_ACTION。收款人尚未为其帐户设置适当的接收首选项。有关如何接受或拒绝此付款的更多信息请在线访问您的帐户。通常在某些情况下提供此原因例如当所捕获付款的货币与收款人的主要持有货币不同时。
* REFUNDED。收回的资金已退还。
* TRANSACTION_APPROVED_AWAITING_FUNDING。付款人必须将这笔付款的资金汇出。通常此代码适用于手动EFT。
* UNILATERAL。收款人没有PayPal帐户。
* VERIFICATION_REQUIRED。收款人的PayPal帐户未通过验证。
*/
/**
* 退款待定
* 退款具有“PENDING”或“FAILED”状态的原因。 可能的值为:
* ECHECK。客户的帐户通过尚未结清的eCheck进行注资。
*/
public static final String STATE_PENDING = "PENDING";
/**
* 退款;大于或等于此捕获的付款金额的金额已退还给付款人
*/
public static final String STATE_REFUNDED = "REFUNDED";
/**
* 支付拒绝
*/
public static final String STATE_DENIED = "DENIED";
/**
* 退款失败
*/
public static final String STATE_FAILED = "FAILED";
/**
* 争议状态
*/
public static final String BUYER_COMPLAINT = "BUYER_COMPLAINT";
/**
* 沙箱环境请求网关地址
*/
public static final String SANDBOX = "https://api.sandbox.paypal.com";
/**
* 生产环境请求网关地址
*/
public static final String LIVE = "https://api.paypal.com";
/**
* 添加物流信息请求路径
*/
public static final String ADD_TRACK_URL = "/v1/shipping/trackers-batch";
/**
* 修改物流信息请求路径
*/
public static final String UPDATE_TRACK_URL = "/v1/shipping/trackers/";
public final static String CMD_NOTIFY_VALIDATE = "_notify-validate";
public final static String PAYPAL_TOKEN_KEY = "PayPalAccessToken";
}

View File

@@ -0,0 +1,14 @@
package com.ai.da.common.constant;
/**
* @author yanglei
* 异常类常量
*/
public class TokenConstant {
/**
* 固定session
*/
public static final String FIX_SESSION = "qrLS_003af9d8c1363fc4_6c97e932665c4460a1fdbfbf47ce3490";
public static final String PERMISSIONS = "9672233956";
}

View File

@@ -3,39 +3,16 @@ package com.ai.da.common.context;
import com.ai.da.model.vo.AuthPrincipalVo; import com.ai.da.model.vo.AuthPrincipalVo;
public class UserContext { public class UserContext {
private static final ThreadLocal<AuthPrincipalVo> userHolder = new ThreadLocal<>(); private static ThreadLocal<AuthPrincipalVo> userHolder= new ThreadLocal<AuthPrincipalVo>();
public static void setUserHolder(AuthPrincipalVo authPrincipalVo) {
userHolder.set(authPrincipalVo);
}
public static AuthPrincipalVo getUserHolder() { public static AuthPrincipalVo getUserHolder() {
AuthPrincipalVo holder = userHolder.get(); return 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() { public static void delete() {
userHolder.remove(); userHolder.remove();
} }
public static Long getUserId() { public static void setUserHolder(AuthPrincipalVo authPrincipalVo) {
return getUserHolder().getId(); userHolder.set(authPrincipalVo);
}
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();
} }
} }

View File

@@ -1,39 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum AliPayTradeStateEnum {
/**
* 支付成功
*/
SUCCESS("TRADE_SUCCESS"),
/**
* 未支付
*/
NOTPAY("WAIT_BUYER_PAY"),
/**
* 已关闭
*/
CLOSED("TRADE_CLOSED"),
/**
* 退款成功
*/
REFUND_SUCCESS("REFUND_SUCCESS"),
/**
* 退款失败
*/
REFUND_ERROR("REFUND_ERROR");
/**
* 类型
*/
private final String type;
}

View File

@@ -1,45 +0,0 @@
package com.ai.da.common.enums;
import java.util.stream.Stream;
/**
* @author: yanglei
* @description: 操作类型 登入 忘记密码
* @create: 2022-8-10 17:33
**/
public enum AuthenticationOperationTypeEnum {
/**
* 登入
*/
LOGIN,
/**
* 异常ip
*/
EXCEPTION_IP,
/**
* 绑定邮箱
*/
BIND_MAILBOX,
/**
* 忘记密码
*/
FORGET_PWD,
/**
* 更改邮箱
*/
CHANGE_MAILBOX,
/**
* 填写用户国家和职业
*/
UPDATE_USERINFO,
REGISTER,
/**
* Global_Award 活动验证
*/
GLOBAL_AWARD;
public static AuthenticationOperationTypeEnum of(String name) {
return Stream.of(AuthenticationOperationTypeEnum.values()).filter(v -> v.name().equals(name)).findFirst().orElse(null);
}
}

View File

@@ -27,9 +27,7 @@ public enum CollectionLevel1TypeEnum {
/** /**
* 市场 * 市场
*/ */
MARKETING_SKETCH("MarketingSketch"), MARKETING_SKETCH("MarketingSketch");
MODEL("Models");
private String realName; private String realName;
@@ -41,8 +39,8 @@ public enum CollectionLevel1TypeEnum {
return realName; return realName;
} }
public static CollectionLevel1TypeEnum uploadOf(String realName) { public static CollectionLevel1TypeEnum uploadOf(String realName){
return Stream.of(CollectionLevel1TypeEnum.values()) return Stream.of(CollectionLevel1TypeEnum.values())
.filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); .filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
} }

View File

@@ -1,7 +1,5 @@
package com.ai.da.common.enums; package com.ai.da.common.enums;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
@@ -29,27 +27,7 @@ public enum CollectionLevel2TypeEnum {
/** /**
* 裤子 * 裤子
*/ */
TROUSERS("Trousers"), TROUSERS("Trousers");
/**
* 男装上装
*/
TOPS("Tops"),
/**
* 男装下装
*/
BOTTOMS("Bottoms"),
/**
* 印花-logo
*/
LOGO("Logo"),
/**
* 印花-slogan
*/
SLOGAN("Slogan"),
/**
* 印花-图案
*/
Pattern("Pattern");
private String realName; private String realName;
@@ -64,11 +42,4 @@ public enum CollectionLevel2TypeEnum {
public static CollectionLevel2TypeEnum of(String realName) { public static CollectionLevel2TypeEnum of(String realName) {
return Stream.of(CollectionLevel2TypeEnum.values()).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); return Stream.of(CollectionLevel2TypeEnum.values()).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null);
} }
public static List<String> printType() {
return Arrays.asList(LOGO.getRealName(), SLOGAN.getRealName(), Pattern.getRealName());
}
public static CollectionLevel2TypeEnum ofWithLoweCase(String realName) {
return Stream.of(CollectionLevel2TypeEnum.values()).filter(v -> v.getRealName().toLowerCase().equals(realName)).findFirst().orElse(null);
}
} }

View File

@@ -6,5 +6,5 @@ package com.ai.da.common.enums;
* @create: 2020-01-14 17:33 * @create: 2020-01-14 17:33
**/ **/
public enum ConditionType { public enum ConditionType {
EQ, LIKE, BETWEEN; EQ,LIKE,BETWEEN;
} }

View File

@@ -1,91 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@AllArgsConstructor
@Getter
public enum CreditsEventsEnum {
PRICE("price","10"),
// PRICE("price","1"),// for test
// PRICE("price","0.1"),
BUY_CREDITS("Buy Credits","50"),
// BUY_CREDITS("Buy Credits","10"),// for test
REFUND("Refund","50"),
// BUY_CREDITS("Buy Credits","10"),
// 每月更新
INIT_YEARLY("init_yearly", "50000"),
INIT_MONTHLY("init_monthly", "3500"),
INIT_MONTHLY_ECO("init_monthly_eco", "500"),
INIT_QUARTERLY("init_quarterly", "12000"),
INIT_MONTHLY_EDU("init_monthly_edu", "3500"),
INIT_TRIAL("init_trial", "100"),
INIT_WEEKLY("init_weekly","6000"),
RESET_YEAR_CREDITS("reset_year_credits","6000"),
// SUPER_RESOLUTION("Super Resolution","30"),
SUPER_RESOLUTION("Super Resolution","10"),
SLOGAN("Slogan","10"),
LOGO("Logo","5"),
PATTERN("Pattern","5"),
MOOD_BOARD("MoodBoard","5"),
SKETCH_BOARD("SketchBoard","5"),
TO_PRODUCT_IMAGE("ToProductImage","5"),
TO_PRODUCT_IMAGE_ADVANCED("ToProductImageAdvanced","15"),
RELIGHT("Relight","5"),
RELIGHT_FLUX("RelightFlux","10"),
QUESTIONNAIRE("Questionnaire","100"),
IMAGE_TO_SKETCH("ImageToSketch","5"),
IMAGE_TO_SKETCH_FLUX("ImageToSketchFlux","10"),
POSE_TRANSFORMATION("PoseTransformation","10"),
OTHER("Other","5"),
SCETCH_TEXT2IMG("SketchText2Image","10"),
SCETCH_IMG2IMG("SketchImg2Image","15"),
WX_TEXT2IMG("WX_Text2Image", "5"),
QWEN_TEXT2IMG("QWEN_Text2Image", "10"),
DOUBAO_TEXT2IMG("Doubao_Text2Image", "10"),
DOUBAO_IMG2IMG_ADVANCED("Doubao_img2image_advanced", "10"),
DOUBAO_IMG2IMG_HIGH("Doubao_img2image_high", "15"),
WX_ANIMATION("WX_Animation", "30"),
FREEPIK_IMG2IMG("Freepik_img2img", "20"),
FLUX_IMG2IMG("Flux_img2img","10"),
LOCAL_TEXT2IMG("Local_text2img","1.25"),
LOCAL_IMG2IMG("Local_img2img","1.25"),
LOCAL_TEXT2IMG_HIGH("Local_text2img_high","5"),
LOCAL_IMG2IMG_HIGH("Local_img2img_high","5"),
LOCAL_ANIMATION("Local_Animation","15"),
LLM_CONVERSATION("LLM_Conversation", "0")
;
private final String name;
/**
* 对应事件需要消耗or获得的积分
*/
private final String value;
public static List<String> generateFunctionNames() {
return Arrays.asList(SLOGAN.name, LOGO.name, PATTERN.name, MOOD_BOARD.name, SKETCH_BOARD.name,
TO_PRODUCT_IMAGE.name, RELIGHT.name, IMAGE_TO_SKETCH.name, POSE_TRANSFORMATION.name);
}
private static final Map<String, CreditsEventsEnum> BY_TASK_NAME = Arrays.stream(values())
.collect(Collectors.toMap(CreditsEventsEnum::getName, Function.identity()));
public static CreditsEventsEnum getByTaskName(String taskName){
return BY_TASK_NAME.get(taskName);
}
}

View File

@@ -1,40 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
public enum CurrencyCodesEnum {
AUSTRALIAN_DOLLAR("AUD"),
BRAZILIAN_REAL("BRL"),
CANADIAN_DOLLAR("CAD"),
CHINESE_RENMENBI("CNY"),
CZECH_KORUNA("CZK"),
DANISH_KRONE("DKK"),
EURO("EUR"),
HONG_KONG_DOLLAR("HKD"),
HUNGARIAN_FORINT("HUF"),
ISRAELI_NEW_SHEKEL("ILS"),
JAPANESE_YEN("JPY"),
MALAYSIAN_RINGGIT("MYR"),
MEXICAN_PESO("MXN"),
NEW_TAIWAN_DOLLAR("TWD"),
NEW_ZEALAND_DOLLAR("NZD"),
NORWEGIAN_KRONE("NOK"),
PHILIPPINE_PESO("PHP"),
POLISH_ZLOTY("PLN"),
POUND_STERLING("GBP"),
RUSSIAN_RUBLE("RUB"),
SINGAPORE_DOLLAR("SGD"),
SWEDISH_KRONA("SEK"),
SWISS_FRANC("CHF"),
THAI_BAHT("THB"),
UNITED_STATES_DOLLAR("USD");
private String code;
CurrencyCodesEnum(String code) {
this.code = code;
}
}

View File

@@ -16,19 +16,19 @@ public enum CurrentDesignPictureTypeEnum {
/** /**
* PIN * PIN
*/ */
PIN(1, "PIN"), PIN(1,"PIN"),
/** /**
* USER_LIBRARY * USER_LIBRARY
*/ */
// USER_LIBRARY(2, "userLibrary"), USER_LIBRARY(2,"userLibrary"),
/** /**
* SYS_FILE * SYS_FILE
*/ */
SYS_FILE(2, "sysFile"), SYS_FILE(3,"sysFile"),
/** /**
* noPIN * noPIN
*/ */
NO_PIN(3, "noPIN"); NO_PIN(4,"noPIN");
private Integer code; private Integer code;
private String desc; private String desc;
@@ -38,11 +38,10 @@ public enum CurrentDesignPictureTypeEnum {
this.desc = desc; this.desc = desc;
} }
public static CurrentDesignPictureTypeEnum of(String name) { public static CurrentDesignPictureTypeEnum of(String name){
return Stream.of(CurrentDesignPictureTypeEnum.values()).filter(v -> v.name().equals(name)).findFirst().orElse(null); return Stream.of(CurrentDesignPictureTypeEnum.values()).filter(v ->v.name().equals(name)).findFirst().orElse(null);
} }
public static List<CurrentDesignPictureTypeEnum> ofList(List<Integer> codes){
public static List<CurrentDesignPictureTypeEnum> ofList(List<Integer> codes) { return Stream.of(CurrentDesignPictureTypeEnum.values()).filter(v ->codes.contains(v.code)).collect(Collectors.toList());
return Stream.of(CurrentDesignPictureTypeEnum.values()).filter(v -> codes.contains(v.code)).collect(Collectors.toList());
} }
} }

View File

@@ -16,15 +16,15 @@ public enum CurrentDesignPrintPictureTypeEnum {
/** /**
* 空白 * 空白
*/ */
NO(1, "空白"), NO(1,"空白"),
/** /**
* PIN * PIN
*/ */
PIN(2, "PIN"), PIN(2,"PIN"),
/** /**
* noPIN * noPIN
*/ */
NO_PIN(3, "noPIN"); NO_PIN(3,"noPIN");
private Integer code; private Integer code;
private String desc; private String desc;
@@ -33,8 +33,7 @@ public enum CurrentDesignPrintPictureTypeEnum {
this.code = code; this.code = code;
this.desc = desc; this.desc = desc;
} }
public static List<CurrentDesignPrintPictureTypeEnum> ofList(List<Integer> codes){
public static List<CurrentDesignPrintPictureTypeEnum> ofList(List<Integer> codes) { return Stream.of(CurrentDesignPrintPictureTypeEnum.values()).filter(v ->codes.contains(v.code)).collect(Collectors.toList());
return Stream.of(CurrentDesignPrintPictureTypeEnum.values()).filter(v -> codes.contains(v.code)).collect(Collectors.toList());
} }
} }

View File

@@ -15,8 +15,7 @@ public enum DesignTypeEnum {
/** /**
* Library * Library
*/ */
LIBRARY("Library"), LIBRARY("Library");
GENERATE("Generate");
private String realName; private String realName;

View File

@@ -1,34 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum FluxTaskStatusEnum {
SUCCESS("Ready"),
TASK_NOT_FOUND("Task not found"),
REQUEST_MODERATED("Request Moderated"),
CONTENT_MODERATED("Content Moderated"),
ERROR("Error"),
PENDING_F("Pending");
private final String name;
public static FluxTaskStatusEnum fromName(String name) {
for (FluxTaskStatusEnum status : values()) {
if (status.name.equalsIgnoreCase(name)) {
return status;
}
}
// 或者返回默认值
return TASK_NOT_FOUND;
}
}

View File

@@ -1,45 +0,0 @@
package com.ai.da.common.enums;
import lombok.Getter;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Getter
public enum GenerateModeEnum {
/**
* 通过文本生成
*/
TEXT(1, "text","txt2img"),
/**
* 通过图片生成
*/
IMAGE(2, "image", "img2img"),
/**
* 通过文本和图片生成
*/
TEXT_IMAGE(2, "text-image","img2img");
private Integer code;
private String value;
private String type;
GenerateModeEnum(int code, String value) {
this.code = code;
this.value = value;
}
GenerateModeEnum(Integer code, String value, String type) {
this.code = code;
this.value = value;
this.type = type;
}
public static List<String> getGenerateModeList(){
return Stream.of(TEXT,IMAGE,TEXT_IMAGE).map(GenerateModeEnum::getValue).collect(Collectors.toList());
}
}

View File

@@ -1,56 +0,0 @@
package com.ai.da.common.enums;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public enum LayersPriorityEnum {
EARRING_FRONT("earring_front","Earring",99),
BAG_FRONT("bag_front","Bag",98),
HAIRSTYLE_FRONT("hairstyle_front","Hairstyle",97),
OUTWEAR_FRONT("outwear_front","Outwear",20),
TOPS_FRONT("tops_front","Tops",19),
DRESS_FRONT("dress_front","Dress",18),
BLOUSE_FRONT("blouse_front","Blouse",17),
SKIRT_FRONT("skirt_front","Skirt",16),
TROUSERS_FRONT("trousers_front","Trousers",15),
BOTTOMS_FRONT("bottoms_front","Bottoms",14),
SHOES_RIGHT("shoes_right","Shoes",1),
SHOES_LEFT("shoes_left","Shoes",1),
BODY("body","Body",0),
BOTTOMS_BACK("bottoms_back","Bottoms",-14),
TROUSERS_BACK("trousers_back","Trousers",-15),
SKIRT_BACK("skirt_back","Skirt",-16),
BLOUSE_BACK("blouse_back","Blouse",-17),
DRESS_BACK("dress_back","Dress",-18),
TOPS_BACK("tops_back","Tops",-19),
OUTWEAR_BACK("outwear_back","Outwear",-20),
HAIRSTYLE_BACK("hairstyle_back","Hairstyle",-97),
BAG_BACK("bag_back","Bag",-98),
EARRING_BACK("earring_back","Earring",-99);
@Getter
private String realName;
@Getter
private String type;
@Getter
private Integer value;
LayersPriorityEnum(String realName, String type,Integer value) {
this.realName = realName;
this.type = type;
this.value = value;
}
public static LayersPriorityEnum getValueByType(String type){
return Stream.of(LayersPriorityEnum.values()).filter(l -> l.getType().equals(type)).findFirst().orElse(null);
}
public static LayersPriorityEnum getValueByLayerCategory(String layerCategory){
return Stream.of(LayersPriorityEnum.values()).filter(l -> l.getRealName().equals(layerCategory)).findFirst().orElse(null);
}
}

View File

@@ -27,10 +27,7 @@ public enum LibraryLevel1TypeEnum {
/** /**
* 模特 * 模特
*/ */
MODELS("Models"), MODELS("Models");
DESIGN_ELEMENTS("DesignElements"),
BRAND_DNA("BrandDNA");
private String realName; private String realName;
@@ -42,8 +39,8 @@ public enum LibraryLevel1TypeEnum {
return realName; return realName;
} }
public static LibraryLevel1TypeEnum uploadOf(String realName) { public static LibraryLevel1TypeEnum uploadOf(String realName){
return Stream.of(LibraryLevel1TypeEnum.values()) return Stream.of(LibraryLevel1TypeEnum.values())
.filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); .filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
} }

View File

@@ -30,10 +30,9 @@ public enum LibraryTopTypeEnum {
public String getRealName() { public String getRealName() {
return realName; return realName;
} }
public static LibraryTopTypeEnum uploadOf(String realName){
public static LibraryTopTypeEnum uploadOf(String realName) {
return Stream.of(LibraryTopTypeEnum.values()) return Stream.of(LibraryTopTypeEnum.values())
.filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); .filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
} }

View File

@@ -17,7 +17,7 @@ public enum LoginTypeEnum {
*/ */
PASSWORD; PASSWORD;
public static LoginTypeEnum of(String name) { public static LoginTypeEnum of(String name){
return Stream.of(LoginTypeEnum.values()).filter(v -> v.name().equals(name)).findFirst().orElse(null); return Stream.of(LoginTypeEnum.values()).filter(v ->v.name().equals(name)).findFirst().orElse(null);
} }
} }

View File

@@ -1,22 +0,0 @@
package com.ai.da.common.enums;
import lombok.Getter;
@Getter
public enum ModelNameEnum {
/**
* 使用模型0
*/
MODEL_0("0", "model_0");
private String code;
private String modelName;
ModelNameEnum(String code, String modelName) {
this.code = code;
this.modelName = modelName;
}
}

View File

@@ -1,29 +0,0 @@
package com.ai.da.common.enums;
import lombok.Getter;
import java.util.stream.Stream;
@Getter
public enum MotionModeEnum {
POSE_TO_VIDEO(1, "/api/comfyui_image_pose_2_video"),
PROMPT_TO_VIDEO(2, "/api/comfyui_image_2_video"),
FIRST_LAST_FRAME_TO_VIDEO(3, "/api/comfyui_flf_2_video")
;
private int code;
private String url;
MotionModeEnum(int code, String url) {
this.code = code;
this.url = url;
}
public static MotionModeEnum of(int code) {
return Stream.of(MotionModeEnum.values()).filter(v -> v.getCode()== code).findFirst().orElse(null);
}
}

View File

@@ -0,0 +1,31 @@
package com.ai.da.common.enums;
import java.util.stream.Stream;
/**
* @author: yanglei
* @description: 操作类型 登入 忘记密码
* @create: 2022-8-10 17:33
**/
public enum OperationTypeEnum {
/**
*登入
*/
LOGIN,
/**
* 异常ip
*/
EXCEPTION_IP,
/**
* 绑定邮箱
*/
BIND_MAILBOX,
/**
* 忘记密码
*/
FORGET_PWD;
public static OperationTypeEnum of(String name){
return Stream.of(OperationTypeEnum.values()).filter(v ->v.name().equals(name)).findFirst().orElse(null);
}
}

View File

@@ -1,50 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum OrderStatusEnum {
/**
* 未支付
*/
NOT_PAY("未支付"),
/**
* 支付成功
*/
SUCCESS("支付成功"),
/**
* 支付失败
*/
FAILURE("支付失败"),
/**
* 已关闭
*/
TIMEOUT_CLOSED("超时已关闭"),
/**
* 已取消
*/
CANCEL("用户已取消"),
/**
* 退款中
*/
REFUND_PROCESSING("退款中"),
/**
* 已退款
*/
REFUND_SUCCESS("已退款"),
/**
* 退款异常
*/
REFUND_ABNORMAL("退款异常"),
/**
* paypal订单状态为 APPROVED
*/
ORDER_PROCESSING("订单处理中");
/**
* 类型
*/
private final String type;
}

View File

@@ -6,5 +6,5 @@ package com.ai.da.common.enums;
* @create: 2020-01-14 17:33 * @create: 2020-01-14 17:33
**/ **/
public enum OrderType { public enum OrderType {
DESC, ASC; DESC,ASC;
} }

View File

@@ -1,30 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum PayPalOrderStatusEnum {
// The order was created with the specified context.
// 订单已创建并具有指定的上下文。
CREATED("CREATED"),
// The order was saved and persisted. The order status continues to be in progress until a capture is made with final_capture = true for all purchase units within the order.
// 订单已保存并持久化。订单状态仍处于进行中,直到对订单中的所有购买单元进行了 final_capture = true 的捕获为止
SAVED("SAVED"),
// The customer approved the payment through the PayPal wallet or another form of guest or unbranded payment. For example, a card, bank account, or so on.
// 客户通过PayPal钱包或其他形式的游客或非品牌支付批准了付款。例如信用卡、银行账户等。
APPROVED("APPROVED"),
// All purchase units in the order are voided.
// 订单中的所有购买单元都已作废。
VOIDED("VOIDED"),
// The payment was authorized or the authorized payment was captured for the order.
// 订单的支付已被授权或已捕获授权的支付。
COMPLETED("COMPLETED"),
// The order requires an action from the payer (e.g. 3DS authentication). Redirect the payer to the "rel":"payer-action" HATEOAS link returned as part of the response prior to authorizing or capturing the order.
// 订单需要支付者执行某项操作例如3DS身份验证。在授权或捕获订单之前请将支付者重定向到响应中返回的"rel":"payer-action" HATEOAS链接。
PAYER_ACTION_REQUIRED("PAYER_ACTION_REQUIRED");
private final String status;
}

View File

@@ -1,38 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum PayTypeEnum {
/**
* 微信
*/
WXPAY("微信"),
/**
* 支付宝
*/
ALIPAY("支付宝"),
/**
* PayPal
*/
PAYPAL("PayPal"),
/**
* 香港支付宝
*/
ALIPAY_HK("Alipay-HK"),
/**
* Stripe
*/
STRIPE("Stripe");
/**
* 类型
*/
private final String type;
}

View File

@@ -1,81 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@AllArgsConstructor
@Getter
public enum PoseEnum {
// POSE_1(1, "aida-sys-image/pose/pose-1.mp4", "aida-sys-image/pose/pose-1.gif", "aida-sys-image/pose/pose-1-first_frame.jpeg", "AACT.8090e67b.-E3pujumEfCbDTI_rjSH-A.LwIlGT3j"),
POSE_1(1, "aida-sys-image/pose/pose-1-1.mp4", "aida-sys-image/pose/pose-1-1.gif", "aida-sys-image/pose/pose-1-first_frame.jpeg", "AACT.8090e67b.qNMWJlyKEfCuORaRJeW4dg.x3wUteVO"),
// POSE_2(2, "aida-sys-image/pose/pose-2.mp4", "aida-sys-image/pose/pose-2.gif", "aida-sys-image/pose/pose-2-first_frame.jpeg", "AACT.8090e67b.TwJLxEv3EfCbDTI_rjSH-A.IOQZCYhf"),
POSE_2(2, "aida-sys-image/pose/pose-2-1.mp4", "aida-sys-image/pose/pose-2-1.gif", "aida-sys-image/pose/pose-2-first_frame.jpeg", "AACT.8090e67b.QpaGOlyLEfCuuJo8eQGF2Q.62EiJj-6"),
// POSE_3(3, "aida-sys-image/pose/pose-3.mp4", "aida-sys-image/pose/pose-3.gif", "aida-sys-image/pose/pose-3-first_frame.jpeg", "AACT.8090e67b.gd3OCkv4EfCxyZo8eQGF2Q.qMm-a1XI"),
POSE_3(3, "aida-sys-image/pose/pose-3-1.mp4", "aida-sys-image/pose/pose-3-1.gif", "aida-sys-image/pose/pose-3-first_frame.jpeg", "AACT.8090e67b.2q5qjFyLEfCImjI_rjSH-A.5cFMwOvi"),
// POSE_4(4, "aida-sys-image/pose/pose-4.mp4", "aida-sys-image/pose/pose-4.gif", "aida-sys-image/pose/pose-4-first_frame.jpeg", "AACT.8090e67b.AUDnuEwDEfCEHBaRJeW4dg.rlx36xEY"),
POSE_4(4, "aida-sys-image/pose/pose-4-1.mp4", "aida-sys-image/pose/pose-4-1.gif", "aida-sys-image/pose/pose-4-first_frame.jpeg", "AACT.8090e67b.KoYMplyPEfCuORaRJeW4dg.MuuBTG78"),
// POSE_5(5, "aida-sys-image/pose/pose-5.mp4", "aida-sys-image/pose/pose-5.gif", "aida-sys-image/pose/pose-5-first_frame.jpeg", "AACT.8090e67b.G8BvkEwEEfCxyZo8eQGF2Q.fo4ryrgR"),
POSE_5(5, "aida-sys-image/pose/pose-5-1.mp4", "aida-sys-image/pose/pose-5-1.gif", "aida-sys-image/pose/pose-5-first_frame.jpeg", "AACT.8090e67b.x54FNFyPEfCuuJo8eQGF2Q.P1egmEZ_"),
// POSE_6(6, "aida-sys-image/pose/pose-6.mp4", "aida-sys-image/pose/pose-6.gif", "aida-sys-image/pose/pose-6-first_frame.jpeg", "AACT.8090e67b.yBIPnEwEEfCxyZo8eQGF2Q.boSFwTG9");
POSE_6(6, "aida-sys-image/pose/pose-6-1.mp4", "aida-sys-image/pose/pose-6-1.gif", "aida-sys-image/pose/pose-6-first_frame.jpeg", "AACT.8090e67b.QSCvBlyQEfCImjI_rjSH-A.G9-Z5ffW");
private final Integer id;
private final String videoPath;
private final String gifPath;
private final String firstFramePath;
private final String templateId;
private static final List<Map<String, String>> PROPERTY_LIST;
static {
PROPERTY_LIST = Arrays.stream(values())
.map(PoseEnum::toMap)
.collect(Collectors.toList());
}
private static final Map<Integer, PoseEnum> BY_ID = Arrays.stream(values())
.collect(Collectors.toMap(PoseEnum::getId, Function.identity()));
private static final Map<String, PoseEnum> BY_VIDEO_PATH = Arrays.stream(values())
.collect(Collectors.toMap(PoseEnum::getVideoPath, Function.identity()));
private static final List<String> VIDEO_PATH = Arrays.stream(values())
.map(PoseEnum::getVideoPath).collect(Collectors.toList());
public static PoseEnum getById(Integer id) {
return BY_ID.get(id);
}
public static PoseEnum getByVideoPath(String videoPath) {
return BY_VIDEO_PATH.get(videoPath);
}
private Map<String, String> toMap() {
Map<String, String> map = new HashMap<>();
map.put("id", String.valueOf(id));
map.put("gif", gifPath);
map.put("video", videoPath);
map.put("firstFrame", firstFramePath);
return map;
}
public static List<Map<String, String>> getPropertyList() {
return PROPERTY_LIST.stream()
.map(HashMap::new) // 深拷贝每个 Map
.collect(Collectors.toList());
}
public static List<String> getVideoList() {
return new ArrayList<>(VIDEO_PATH); // 返回副本以保证不可变性
}
}

View File

@@ -1,33 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ProductEnum {
// 积分购买
CreditsProduct("AiDA credits purchase", 10L, 50L),
// 年度订阅
AnnualSubscription("AiDA Annual Subscription", 5000L, 50000L),
// 月度订阅订阅费500每月3500 积分)
MonthlySubscription("AiDA Monthly Subscription", 500L, 3500L),
// 月度订阅 -- 经济实惠版 订阅费100每月500 积分)
Eco_MonthlySubscription("AiDA Eco Monthly Subscription", 100L, 500L),
// 季度订阅
QuarterlySubscription("AiDA Quarterly Subscription", 1500L, 12000L),
// 月度订阅 -- 教育版
EDUMonthlySubscription("AiDA Edu Monthly Subscription", 200L, 3500L),
// 测试
DailySubscription("AiDA Daily Subscription", 5L, 100L),
;
/**
* 类型
*/
private final String name;
private final Long price;
private final Long credits;
}

View File

@@ -4,7 +4,7 @@ import java.util.stream.Stream;
/** /**
* @author yanglei * @author yanglei
* @description python调用java 操作数类型 generatePrint ->生成印花 designCollection ->设计collection generateSketch->设计草图 * @description python调用java 操作数类型 generatePrint ->生成印花 designCollection ->设计collection
* @create 2022-10-3 17:33 * @create 2022-10-3 17:33
**/ **/
public enum PythonToJavaApiOperationTypeEnum { public enum PythonToJavaApiOperationTypeEnum {
@@ -19,12 +19,7 @@ public enum PythonToJavaApiOperationTypeEnum {
/** /**
* 设计collection * 设计collection
*/ */
DESIGN_COLLECTION("designCollection"), DESIGN_COLLECTION("designCollection");
/**
* 生成草图
*/
GENERATE_SKETCH("generateSketch");
private String realName; private String realName;
@@ -36,7 +31,7 @@ public enum PythonToJavaApiOperationTypeEnum {
return realName; return realName;
} }
public static PythonToJavaApiOperationTypeEnum uploadOf(String realName) { public static PythonToJavaApiOperationTypeEnum uploadOf(String realName){
return Stream.of(PythonToJavaApiOperationTypeEnum.values()).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); return Stream.of(PythonToJavaApiOperationTypeEnum.values()).filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
} }

View File

@@ -27,7 +27,7 @@ public enum SingleOverallEnum {
return realName; return realName;
} }
public static SingleOverallEnum of(String realName) { public static SingleOverallEnum of(String realName){
return Stream.of(SingleOverallEnum.values()).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); return Stream.of(SingleOverallEnum.values()).filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
} }

View File

@@ -28,8 +28,6 @@ public enum SwitchCategoryEnum {
* 裤子 * 裤子
*/ */
TROUSERS("Trousers"), TROUSERS("Trousers"),
TOPS("Tops"),
BOTTOMS("Bottoms"),
; ;
private String realName; private String realName;
@@ -42,7 +40,7 @@ public enum SwitchCategoryEnum {
return realName; return realName;
} }
public static SwitchCategoryEnum of(String realName) { public static SwitchCategoryEnum of(String realName){
return Stream.of(SwitchCategoryEnum.values()).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); return Stream.of(SwitchCategoryEnum.values()).filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
} }

View File

@@ -9,11 +9,11 @@ import java.util.stream.Stream;
**/ **/
public enum SysFileLevel1TypeEnum { public enum SysFileLevel1TypeEnum {
IMAGES("Images", "images"), IMAGES("Images","images"),
ICON_C("Iconc", "iconc"), ICON_C("Iconc","iconc"),
ACCESSORIES("Accessories", "accessories"); ACCESSORIES("Accessories","accessories");
private String realName; private String realName;
/** /**
@@ -34,7 +34,7 @@ public enum SysFileLevel1TypeEnum {
return uploadPathName; return uploadPathName;
} }
public static SysFileLevel1TypeEnum uploadOf(String uploadPathName) { public static SysFileLevel1TypeEnum uploadOf(String uploadPathName){
return Stream.of(SysFileLevel1TypeEnum.values()).filter(v -> v.getUploadPathName().equals(uploadPathName)).findFirst().orElse(null); return Stream.of(SysFileLevel1TypeEnum.values()).filter(v ->v.getUploadPathName().equals(uploadPathName)).findFirst().orElse(null);
} }
} }

View File

@@ -1,6 +1,5 @@
package com.ai.da.common.enums; package com.ai.da.common.enums;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -14,27 +13,27 @@ public enum SysFileLevel2TypeEnum {
/** /**
* ICON * ICON
*/ */
ICON("Icon", "icon"), ICON("Icon","icon"),
BAG("Bag", "bag"), BAG("Bag","bag"),
EARRINGS("Earring", "earring"), EARRINGS("Earring","earring"),
HAIRSTYLE("Hairstyle", "hairstyle"), HAIRSTYLE("Hairstyle","hairstyle"),
SHOES("Shoes", "shoes"), SHOES("Shoes","shoes"),
BODY("Body", "body"), BODY("Body","body"),
BLOUSE("Blouse", "blouse"), BLOUSE("Blouse","blouse"),
DRESS("Dress", "dress"), DRESS("Dress","dress"),
OUTWEAR("Outwear", "outwear"), OUTWEAR("Outwear","outwear"),
SKIRT("Skirt", "skirt"), SKIRT("Skirt","skirt"),
TROUSERS("Trousers", "trousers"); TROUSERS("Trousers","trousers");
private String realName; private String realName;
/** /**
@@ -55,40 +54,20 @@ public enum SysFileLevel2TypeEnum {
return uploadPathName; return uploadPathName;
} }
public static SysFileLevel2TypeEnum uploadOf(String uploadPathName) { public static SysFileLevel2TypeEnum uploadOf(String uploadPathName){
return Stream.of(SysFileLevel2TypeEnum.values()).filter(v -> v.getUploadPathName().equals(uploadPathName)).findFirst().orElse(null); return Stream.of(SysFileLevel2TypeEnum.values()).filter(v ->v.getUploadPathName().equals(uploadPathName)).findFirst().orElse(null);
}
public static SysFileLevel2TypeEnum realNameOf(String realName){
return Stream.of(SysFileLevel2TypeEnum.values()).filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
public static SysFileLevel2TypeEnum realNameOf(String realName) { public static SysFileLevel2TypeEnum realNameOfPython(String realName){
return Stream.of(SysFileLevel2TypeEnum.values()).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null); return Stream.of(BLOUSE,DRESS,OUTWEAR,SKIRT,TROUSERS).filter(v ->v.getRealName().equals(realName)).findFirst().orElse(null);
} }
public static List<String> ofPython(){
public static SysFileLevel2TypeEnum realNameOfPython(String realName) { return Stream.of(BLOUSE,DRESS,OUTWEAR,SKIRT,TROUSERS).map(SysFileLevel2TypeEnum::getRealName).collect(Collectors.toList());
return Stream.of(BLOUSE, DRESS, OUTWEAR, SKIRT, TROUSERS).filter(v -> v.getRealName().equals(realName)).findFirst().orElse(null);
} }
public static List<String> ofPythonPath(){
public static List<String> ofPython() { return Stream.of(BLOUSE,DRESS,OUTWEAR,SKIRT,TROUSERS).map(SysFileLevel2TypeEnum::getUploadPathName).collect(Collectors.toList());
return Stream.of(BLOUSE, DRESS, OUTWEAR, SKIRT, TROUSERS).map(SysFileLevel2TypeEnum::getRealName).collect(Collectors.toList());
} }
public static List<String> ofPythonPath() {
return Stream.of(BLOUSE, DRESS, OUTWEAR, SKIRT, TROUSERS).map(SysFileLevel2TypeEnum::getUploadPathName).collect(Collectors.toList());
}
public static final List<String> ACCESSORIES_LIST = Arrays.asList(
SysFileLevel2TypeEnum.BAG.getRealName(),
SysFileLevel2TypeEnum.EARRINGS.getRealName(),
SysFileLevel2TypeEnum.HAIRSTYLE.getRealName(),
SysFileLevel2TypeEnum.SHOES.getRealName(),
SysFileLevel2TypeEnum.BODY.getRealName()
);
public static final List<String> IMAGES_LIST = Arrays.asList(
SysFileLevel2TypeEnum.BLOUSE.getRealName(),
SysFileLevel2TypeEnum.DRESS.getRealName(),
SysFileLevel2TypeEnum.OUTWEAR.getRealName(),
SysFileLevel2TypeEnum.SKIRT.getRealName(),
SysFileLevel2TypeEnum.TROUSERS.getRealName()
);
} }

View File

@@ -1,32 +0,0 @@
package com.ai.da.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum WangXiangTaskStatusEnum {
SUCCEEDED("SUCCEEDED"),
UNKNOWN_W("UNKNOWN"),
FAILED("FAILED"),
RUNNING("RUNNING"),
PENDING_W("PENDING");
private final String name;
// 通过name查找枚举的静态方法
public static WangXiangTaskStatusEnum fromName(String name) {
for (WangXiangTaskStatusEnum status : values()) {
if (status.name.equalsIgnoreCase(name)) {
return status;
}
}
// 或者返回默认值
return UNKNOWN_W;
}
}

View File

@@ -0,0 +1,33 @@
package com.ai.da.common.httpdata.token;
public enum TokenApis {
/**
* token
*/
GET_TOKEN("POST", "/api/openApi/v2/Weixin/QrCodeLoginCheck?session="),
GENERATE_USER("POST", "/api/openApi/v2/Welink/TopicGetjson");
private String method;
private String url;
TokenApis(String method, String url) {
this.method = method;
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}

View File

@@ -0,0 +1,41 @@
package com.ai.da.common.httpdata.token;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class TokenQuery {
private static final String GET_TOKEN_DOMAIN = "https://www.szsige.com";
private static final String GENERATE_USER_DOMAIN = "https://www.szsige.com";
public static JSONObject getToken(String session) {
String url = GET_TOKEN_DOMAIN + TokenApis.GET_TOKEN.getUrl()+ session;
log.info("获取用户token接口请求url:" + url);
HttpResponse httpResponse = HttpUtil.createPost(url).execute();
log.info("获取用户token接口响应" + httpResponse);
if(httpResponse.isOk() && StrUtil.isNotEmpty(httpResponse.body())){
return JSONObject.parseObject(httpResponse.body());
}
return null;
}
public static JSONObject generateUser(Map<String, Object> param,String token) {
HttpResponse httpResponse = HttpUtil.createPost(GENERATE_USER_DOMAIN + TokenApis.GENERATE_USER.getUrl())
.body(JSONObject.toJSONString(param!=null?param:new HashMap<>()))
.header("Authorization", "Bearer "+token)
.header("X-Promiss", "9672233956")
.execute();
log.info("生成用户信息接口响应:" + httpResponse);
if(httpResponse.isOk() && StrUtil.isNotEmpty(httpResponse.body())){
return JSONObject.parseObject(httpResponse.body());
}
return null;
}
}

View File

@@ -1,51 +0,0 @@
package com.ai.da.common.interceptor;
import com.ai.da.common.context.UserContext;
import com.ai.da.model.vo.AuthPrincipalVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* 从 Gateway 转发的请求头中读取已鉴权的用户身份,写入 UserContext。
* <p>
* Gateway 验证 JWT 后将 X-User-Id 和 X-User-Info 写入请求头,
* 此拦截器负责将信息填充到 ThreadLocal供业务代码使用。
* 不需要 Gateway 鉴权路径(如 login、静态资源不会有这两个头
* 此时 UserContext 保持为空,业务代码应自行处理。
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class UserContextInterceptor implements HandlerInterceptor {
private static final String USER_ID_HEADER = "X-User-Id";
private static final String USER_INFO_HEADER = "X-User-Info";
private final ObjectMapper objectMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String userInfoJson = request.getHeader(USER_INFO_HEADER);
if (userInfoJson != null && !userInfoJson.isBlank()) {
try {
AuthPrincipalVo principal = objectMapper.readValue(userInfoJson, AuthPrincipalVo.class);
UserContext.setUserHolder(principal);
} catch (Exception e) {
log.warn("Failed to parse X-User-Info header: {}", e.getMessage());
}
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
UserContext.delete();
}
}

View File

@@ -1,7 +1,8 @@
package com.ai.da.common.response; package com.ai.da.common.response;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -15,20 +16,21 @@ import java.util.List;
*/ */
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@Schema(description = "分页响应结果") @ApiModel("分页响应结果")
public class PageBaseResponse<T> { public class PageBaseResponse<T>{
@Schema(description = "页码") @ApiModelProperty("页码")
private long page; private long page;
@Schema(description = "每页数量") @ApiModelProperty("每页数量")
private long size; private long size;
@Schema(description = "总页数") @ApiModelProperty("总页数")
private long pages; private long pages;
@Schema(description = "总条数") @ApiModelProperty("总条数")
private long total; private long total;
@Schema(description = "结果集") @ApiModelProperty("结果集")
private List<T> content; private List<T> content;
public PageBaseResponse(List<T> list, long page, long size, long total, long pages) { public PageBaseResponse(List<T> list, long page, long size, long total, long pages) {
this.page = page; this.page = page;
this.size = size; this.size = size;
@@ -37,7 +39,7 @@ public class PageBaseResponse<T> {
this.content = list; this.content = list;
} }
public static <T> PageBaseResponse<T> success(IPage<T> page) { public static <T> PageBaseResponse<T> success(IPage<T> page){
return new PageBaseResponse<>(page.getRecords(), page.getCurrent(), page.getSize(), page.getTotal(), page.getPages()); return new PageBaseResponse<>(page.getRecords() , page.getCurrent(), page.getSize(), page.getTotal(), page.getPages());
} }
} }

View File

@@ -1,7 +1,8 @@
package com.ai.da.common.response; package com.ai.da.common.response;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -15,23 +16,24 @@ import java.util.List;
*/ */
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@Schema(description = "分页响应结果") @ApiModel("分页响应结果")
public class PageResponse<T> extends Response<List<T>> { public class PageResponse<T> extends Response<List<T>> {
@Schema(description = "页码") @ApiModelProperty("页码")
private long page; private long page;
@Schema(description = "每页数量") @ApiModelProperty("每页数量")
private long size; private long size;
@Schema(description = "总页数") @ApiModelProperty("总页数")
private long pages; private long pages;
@Schema(description = "总条数") @ApiModelProperty("总条数")
private long total; private long total;
@Schema(description = "结果集") @ApiModelProperty("结果集")
private List<T> content; private List<T> content;
public PageResponse(Response<List<T>> response, long page, long size, long total, long pages) { public PageResponse(Response<List<T>> response, long page, long size, long total, long pages) {
if (response != null) { if(response != null) {
this.setData(response.getData()); this.setData(response.getData());
this.setErrCode(response.getErrCode()); this.setErrCode(response.getErrCode());
this.setErrMsg(response.getErrMsg()); this.setErrMsg(response.getErrMsg());
@@ -43,8 +45,8 @@ public class PageResponse<T> extends Response<List<T>> {
this.content = response.getData(); this.content = response.getData();
} }
public static <T> PageResponse<T> success(IPage<T> page) { public static <T> PageResponse<T> success(IPage<T> page){
Response<List<T>> response = success(page.getRecords()); Response<List<T>> response = success(page.getRecords());
return new PageResponse<>(response, page.getCurrent(), page.getSize(), page.getTotal(), page.getPages()); return new PageResponse<>(response , page.getCurrent(), page.getSize(), page.getTotal(), page.getPages());
} }
} }

View File

@@ -1,6 +1,7 @@
package com.ai.da.common.response; package com.ai.da.common.response;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -16,37 +17,38 @@ import java.io.Serializable;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Schema(description = "响应结果") @ApiModel("响应结果")
public class Response<T> implements Serializable { public class Response<T> implements Serializable {
@Schema(description = "响应状态码 0成功 -1失败") @ApiModelProperty("响应状态码 0成功 -1失败")
private int errCode; private int errCode;
@Schema(description = "提示消息") @ApiModelProperty("提示消息")
private String errMsg; private String errMsg;
@Schema(description = "数据结果") @ApiModelProperty("数据结果")
private T data; private T data;
public static <T> Response<T> success() { public static <T> Response<T> success(){
return success(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), null); return success(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), null);
} }
// public static <T> Response<T> success(String msg) { public static <T> Response<T> success(String msg){
// return success(ResultEnum.SUCCESS.getCode(), msg, null); return success(ResultEnum.SUCCESS.getCode(), msg, null);
// } }
public static <T> Response<T> success(T data) { public static <T> Response<T> success(T data){
return success(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), data); return success(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), data);
} }
public static <T> Response<T> success(int code, T data) { public static <T> Response<T> success(int code, T data){
return success(code, ResultEnum.SUCCESS.getMsg(), data); return success(code, ResultEnum.SUCCESS.getMsg(), data);
} }
public static <T> Response<T> success(int code, String msg, T data) { public static <T> Response<T> success(int code, String msg, T data){
return getResponse(code, msg, data); return getResponse(code, msg, data);
} }
public static <T> Response<T> fail(String msg) { public static <T> Response<T> fail(String msg) {
return fail(ResultEnum.FAIL.getCode(), msg); return fail(ResultEnum.FAIL.getCode(), msg);
} }
@@ -83,7 +85,7 @@ public class Response<T> implements Serializable {
return getResponse(code, msg, data); return getResponse(code, msg, data);
} }
private static <T> Response<T> getResponse(int code, String msg, T data) { private static <T> Response<T> getResponse(int code, String msg, T data){
return new Response<>(code, msg, data); return new Response<>(code, msg, data);
} }

View File

@@ -13,20 +13,17 @@ public enum ResultEnum {
ERROR(false, -1, "system error!"), ERROR(false, -1, "system error!"),
PARAMETER_ERROR(false, -2, "parameter error!"), PARAMETER_ERROR(false, -2, "parameter error!"),
NO_LOGIN(false, -100, "User not logged in"), NO_LOGIN(false,-100,"User not logged in"),
NO_PERMISSION(false, -200, "No access"), NO_PERMISSION(false,-200,"No access"),
ACCOUNT_LOCK(false, -300, "Account frozen"), ACCOUNT_LOCK(false,-300,"Account frozen");
PROMPT(false, 1, "Prompt"),
WARNING(false, 2, "Warning"),
;
private int code; private int code;
private String msg; private String msg;
private boolean isOK; private boolean isOK;
ResultEnum(boolean isOK, int code, String msg) {
ResultEnum(boolean isOK, int code, String msg){
this.isOK = isOK; this.isOK = isOK;
this.code = code; this.code = code;
this.msg = msg; this.msg = msg;

View File

@@ -1,15 +0,0 @@
package com.ai.da.common.response;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@NoArgsConstructor
@Schema(description = "交易记录分页响应结果")
public class TransactionPageResponse<T> extends PageBaseResponse<T> {
private BigDecimal totalAmount;
}

View File

@@ -0,0 +1,27 @@
package com.ai.da.common.security;
import com.ai.da.common.response.Response;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.JSONResponseUtils;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName UserAuthAccessDeniedHandler
* @Description 无权限处理类
* @Author dwjian
* @Date 2020/7/9 20:30
*/
@Component
public class UserAuthAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException exception) throws IOException {
Response<String> response = Response.error(ResultEnum.NO_PERMISSION.getCode(), ResultEnum.NO_PERMISSION.getMsg());
JSONResponseUtils.build(httpServletResponse, response);
}
}

View File

@@ -0,0 +1,29 @@
package com.ai.da.common.security;
import com.ai.da.common.response.Response;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.JSONResponseUtils;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName UserAuthenticationEntryPointHandler
* @Description 未登录处理类
* @Author dwjian
* @Date 2020/7/9 20:13
*/
@Component
public class UserAuthenticationEntryPointHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
Response<String> response = Response.error(ResultEnum.NO_LOGIN.getCode(), ResultEnum.NO_LOGIN.getMsg());
httpServletResponse.setStatus(401);
JSONResponseUtils.build(httpServletResponse, response);
}
}

View File

@@ -0,0 +1,25 @@
package com.ai.da.common.security;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author: dangweijian
* @description: 认证管理器
* @create: 2020-07-10 15:58
**/
@Component
public class UserAuthenticationManager implements AuthenticationManager {
@Resource
private UserAuthenticationProvider userAuthenticationProvider;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return userAuthenticationProvider.authenticate(authentication);
}
}

View File

@@ -0,0 +1,59 @@
package com.ai.da.common.security;
import com.ai.da.common.config.RsaProperties;
import com.ai.da.common.utils.RsaDecryptUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
/**
* @author: dangweijian
* @description: 登录校验处理类
* @create: 2020-07-09 14:39
**/
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String userName = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
try {
password = RsaDecryptUtils.decrypt(password, RsaProperties.privateKey);
} catch (Exception e) {
throw new BadCredentialsException("用户名或密码错误");
}
// User user = userService.getByUsername(userName);
// if (user == null) {
// throw new UsernameNotFoundException("用户名或密码错误");
// }
// //账号已冻结
// if(user.getStatus() == 1){
// throw new LockedException("账号已冻结");
// }
// if(!passwordEncoder.matches(password, user.getPassword())){
// throw new BadCredentialsException("用户名或密码错误");
// }
// //超级管理员
// Set<SimpleGrantedAuthority> authorities = new HashSet<>();
// if(user.getIsAdmin()) {
// authorities.add(new SimpleGrantedAuthority("admin"));
// return new UsernamePasswordAuthenticationToken(user, password, authorities);
// }else {
// List<RoleMenuDto> userMenus = menuService.getRoleMenusByUserId(user.getId(), null);
// if(CollUtil.isNotEmpty(userMenus)){
// authorities.addAll(userMenus.stream().map(RoleMenuDto::getPermission).filter(StringUtils::isNotEmpty).map(SimpleGrantedAuthority::new).collect(Collectors.toSet()));
// }
// return new UsernamePasswordAuthenticationToken(user, password, authorities);
// }
return null;
}
@Override
public boolean supports(Class<?> aClass) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
}
}

View File

@@ -0,0 +1,48 @@
package com.ai.da.common.security;
import com.ai.da.common.response.Response;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.JSONResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName UserLoginFailureHandler
* @Description 登录失败处理类
* @Author dwjian
* @Date 2020/7/9 20:17
*/
@Slf4j
@Component
public class UserLoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
Response<String> response;
if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
response = Response.fail(e.getMessage());
} else if (e instanceof LockedException) {
response = Response.fail(ResultEnum.ACCOUNT_LOCK);
} else if (e instanceof CredentialsExpiredException) {
response = Response.fail("证书过期,请联系管理员!");
} else if (e instanceof AccountExpiredException) {
response = Response.fail("账户过期,请联系管理员!");
} else if (e instanceof DisabledException) {
response = Response.fail("账户被禁用,请联系管理员!");
} else if (e instanceof AuthenticationServiceException) {
response = Response.fail(e.getMessage());
} else {
log.error("登录失败:", e);
response = Response.fail("登录失败!");
}
JSONResponseUtils.build(httpServletResponse,response);
}
}

View File

@@ -0,0 +1,51 @@
package com.ai.da.common.security;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.JSONResponseUtils;
import com.ai.da.common.response.Response;
import com.ai.da.common.security.jwt.JWTTokenHelper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author: dangweijian
* @description: 登录成功处理类
* @create: 2020-07-09 14:58
**/
@Component
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
@Resource
private JWTTokenHelper jwtTokenHelper;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// User user = (User) authentication.getPrincipal();
// AuthPrincipalVo principal = new AuthPrincipalVo();
// BeanUtils.copyProperties(user, principal);
// // 获取用户角色
// List<UserRoleDto> userRoles = roleService.getUserRoles(user.getId(), 0);
// principal.setRoles(userRoles);
// // 获取角色部门
// if(CollUtil.isNotEmpty(userRoles)){
// principal.setDepts(deptService.getDeptByRoleIds(userRoles.stream().map(UserRoleDto::getRoleId).collect(Collectors.toList())));
// }
// // 用户角色权限
// List<String> authorities = new ArrayList<>(authentication.getAuthorities()).stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
// principal.setAuthorities(authorities);
// AuthVo authVo = new AuthVo();
// authVo.setAuthorities(authorities);
// authVo.setToken(jwtTokenHelper.createToken(principal));
// authVo.setPrincipal(principal);
// user.setLastLoginTime(new Date());
// userService.updateById(user);
JSONResponseUtils.build(response, Response.success(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), null));
}
}

View File

@@ -0,0 +1,34 @@
package com.ai.da.common.security;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* @ClassName UserPermissionEvaluator
* @Description 权限校验处理器
* @Author dwjian
* @Date 2020/7/12 10:16
*/
@Component
public class UserPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
System.out.println(authentication);
System.out.println(targetUrl);
System.out.println(permission);
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
System.out.println(authentication);
System.out.println(targetId);
System.out.println(targetType);
System.out.println(permission);
return false;
}
}

View File

@@ -0,0 +1,84 @@
package com.ai.da.common.security.config;
import com.ai.da.common.security.*;
import com.ai.da.common.security.filter.AuthenticationFilter;
import com.ai.da.common.security.filter.UserAuthenticationProcessingFilter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.annotation.Resource;
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableConfigurationProperties(SecurityProperties.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private SecurityProperties securityProperties;
@Resource
private UserLoginSuccessHandler userLoginSuccessHandler;
@Resource
private UserLoginFailureHandler userLoginFailureHandler;
@Resource
private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
@Resource
private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
@Resource
private UserAuthenticationManager userAuthenticationManager;
@Resource
private UserAuthenticationProcessingFilter userAuthenticationProcessingFilter;
/**
* 不通过注入spring管理 让Security来管理 这样自定义的Filter就不会走,.permitAll()才能起作用
*/
@Resource
private AuthenticationFilter authenticationFilter;
@Resource
private UserPermissionEvaluator userPermissionEvaluator;
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return this.userAuthenticationManager;
}
@Override
protected void configure(HttpSecurity httpSecurity/*, WebSecurity web*/) throws Exception {
// web.ignoring().antMatchers("/test/**");//禁止所有过滤器
httpSecurity.cors().disable()//禁用 CSRF
.authorizeRequests()//认证请求
.antMatchers(securityProperties.getIgnorePaths()).permitAll()//忽略的请求
.anyRequest().authenticated()//其余所有的请求都需要认证
.and().headers().frameOptions().disable()// 防止iframe 造成跨域
.and().exceptionHandling().authenticationEntryPoint(userAuthenticationEntryPointHandler)//未登录请求处理
.accessDeniedHandler(userAuthAccessDeniedHandler)//无权限访问处理类 (此配置可以忽略全局异常会先于Security框架处理异常全局异常已特殊处理)
.and().formLogin().loginProcessingUrl(securityProperties.getAuthApi())//指定认证接口
.successHandler(userLoginSuccessHandler)//登录成功处理器
.failureHandler(userLoginFailureHandler)//登录失败处理器
.and().cors().and().csrf().disable();//允许跨域
//自定义过滤器在登录时认证用户名、密码
httpSecurity.addFilterAt(userAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(authenticationFilter, BasicAuthenticationFilter.class);
//不创建session会话
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//取消头缓存控制
httpSecurity.headers().cacheControl();
}
@Bean
public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
handler.setPermissionEvaluator(userPermissionEvaluator);
return handler;
}
}

View File

@@ -0,0 +1,26 @@
package com.ai.da.common.security.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author: dangweijian
* @description: JWT配置类
* @create: 2020-07-09 09:38
**/
@Data
@ConfigurationProperties(prefix = "spring.security")
public class SecurityProperties {
private String jwtSecret;
private String jwtTokenHeader;
private String jwtTokenPrefix;
private long jwtExpiration;
private String[] ignorePaths;
private String authApi;
}

View File

@@ -0,0 +1,122 @@
package com.ai.da.common.security.filter;
import cn.hutool.core.util.StrUtil;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.security.config.SecurityProperties;
import com.ai.da.common.security.jwt.JWTTokenHelper;
import com.ai.da.common.utils.LocalCacheUtils;
import com.ai.da.common.utils.MultiReadHttpServletRequest;
import com.ai.da.common.utils.MultiReadHttpServletResponse;
import com.ai.da.model.vo.AuthPrincipalVo;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.security.sasl.AuthenticationException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
/**
* @author: dangweijian
* @description: 认证拦截器
* @create: 2020-07-10 16:50
**/
@Slf4j
@Configuration
public class AuthenticationFilter extends OncePerRequestFilter {
@Resource
private JWTTokenHelper jwtTokenHelper;
@Resource
private SecurityProperties properties;
private static final List<String> FILTER_URL =
Arrays.asList("/favicon.ico","/doc.html","api/account/login","api/account/preLogin","api/account/sendEmail",
"/webjars/","/swagger-resources","/v2/api-docs","api/account/resetPwd",
"/api/python/saveGeneratePicture", "/api/python/getLibraryByUserId",
"/api/third/party/addUser","/api/third/party/editUser","/api/element/initDefaultSysFile");
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) throws ServletException, IOException {
String requestURI = httpServletRequest.getRequestURI();
if(calculateUrl(requestURI)){
StopWatch stopWatch = new StopWatch();
HttpServletRequest wrappedRequest = httpServletRequest;
HttpServletResponse wrappedResponse = httpServletResponse;
try{
stopWatch.start();
if ((httpServletRequest.getContentType() == null && httpServletRequest.getContentLength() > 0) || (httpServletRequest.getContentType() != null && !httpServletRequest.getContentType().contains("application/json"))) {
extracted(wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
}else {
wrappedRequest = new MultiReadHttpServletRequest(httpServletRequest);
wrappedResponse = new MultiReadHttpServletResponse(httpServletResponse);
extracted(wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
}
} catch (Exception e) {
SecurityContextHolder.clearContext();
throw e;
} finally {
stopWatch.stop();
}
}else {
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
private Boolean calculateUrl(String requestURI ){
String filterUrl = FILTER_URL.stream().filter(url ->requestURI.contains(url)).findFirst().orElse(null);
return null == filterUrl ? Boolean.TRUE :Boolean.FALSE;
}
private void extracted(HttpServletRequest request) throws AuthenticationException {
String jwtToken = request.getHeader(properties.getJwtTokenHeader());
log.debug("后台检查令牌:{}", jwtToken);
if (StrUtil.isBlank(jwtToken)) {
throw new RuntimeException("请传入token");
}
// 检查token
boolean validate = jwtTokenHelper.validateToken(jwtToken);
if(validate){
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(jwtToken);
if (principal == null) {
throw new RuntimeException("TOKEN已过期请重新登录");
}
//先清空当前线程变量,防止上一个线程遗留
UserContext.delete();
//存取用户信息到缓存
UserContext.setUserHolder(principal);
//校验token
String cacheToken = LocalCacheUtils.getTokenCache(String.valueOf(principal.getId()));
if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){
//写死 暂时放行
return;
}
if(StringUtils.isEmpty(cacheToken)){
throw new RuntimeException("TOKEN已过期请重新登录");
}
if(!cacheToken.equals(jwtToken) ){
throw new RuntimeException("TOKEN已过期请重新登录");
}
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(null, null);
// SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}

View File

@@ -0,0 +1,69 @@
package com.ai.da.common.security.filter;
import cn.hutool.core.util.StrUtil;
import com.ai.da.common.security.UserLoginSuccessHandler;
import com.ai.da.common.security.config.SecurityProperties;
import com.ai.da.common.utils.RedisCacheUtils;
import com.alibaba.fastjson.JSONObject;
import com.ai.da.common.security.UserAuthenticationManager;
import com.ai.da.common.security.UserLoginFailureHandler;
import com.ai.da.common.utils.MultiReadHttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author: dangweijian
* @description: 用户认证过滤器
* @create: 2020-07-10 15:58
**/
@Slf4j
@Component
public class UserAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
/**
* @param securityProperties 配置从配置中读取登录url
* @param authenticationManager 认证管理器
* @param adminAuthenticationSuccessHandler 认证成功处理器
* @param adminAuthenticationFailureHandler 认证失败处理器
*/
public UserAuthenticationProcessingFilter(SecurityProperties securityProperties, UserAuthenticationManager authenticationManager, UserLoginSuccessHandler adminAuthenticationSuccessHandler, UserLoginFailureHandler adminAuthenticationFailureHandler) {
super(new AntPathRequestMatcher(securityProperties.getAuthApi(), HttpMethod.POST.name()));
this.setAuthenticationManager(authenticationManager);
this.setAuthenticationSuccessHandler(adminAuthenticationSuccessHandler);
this.setAuthenticationFailureHandler(adminAuthenticationFailureHandler);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (request.getContentType() == null || !request.getContentType().contains("application/json")) {
throw new AuthenticationServiceException("请求头类型不支持: " + request.getContentType());
}
UsernamePasswordAuthenticationToken authRequest;
try {
MultiReadHttpServletRequest wrappedRequest = new MultiReadHttpServletRequest(request);
// 将前端传递的数据转换成jsonBean数据格式
JSONObject jsonObject = JSONObject.parseObject(wrappedRequest.getBodyJsonStrByJson(wrappedRequest));
String code = jsonObject.getString("code");
String uuid = jsonObject.getString("uuid");
if (StrUtil.isEmpty(code) || StrUtil.isEmpty(uuid) || !code.equals(RedisCacheUtils.get("code-key-" + uuid, String.class))) {
throw new AuthenticationServiceException("验证码错误");
}
RedisCacheUtils.delete("code-key-" + uuid);
authRequest = new UsernamePasswordAuthenticationToken(jsonObject.get("username"), jsonObject.get("password"), null);
authRequest.setDetails(authenticationDetailsSource.buildDetails(wrappedRequest));
} catch (Exception e) {
throw new AuthenticationServiceException(e.getMessage());
}
return this.getAuthenticationManager().authenticate(authRequest);
}
}

View File

@@ -0,0 +1,68 @@
package com.ai.da.common.security.jwt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.ai.da.common.security.config.SecurityProperties;
import com.ai.da.model.vo.AuthPrincipalVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
/**
* @author: dangweijian
* @description: JWT工具
* @create: 2020-07-09 09:27
**/
@Slf4j
@Component
public class JWTTokenHelper {
@Resource
private SecurityProperties securityProperties;
private static final String ISSUER = "DWJ";
private static final String AUTHORITIES = "authorities";
public String createToken(AuthPrincipalVo principal){
String token = Jwts.builder()
.setId(String.valueOf(principal.getId()))
.setSubject(JSONObject.toJSONString(principal))
.setIssuedAt(new Date())
.setIssuer(ISSUER)
.claim(AUTHORITIES, JSON.toJSONString(new ArrayList<>()))//自定义属性 权限
.setExpiration(new Date(System.currentTimeMillis() + securityProperties.getJwtExpiration()))
.signWith(SignatureAlgorithm.HS512, securityProperties.getJwtSecret())
.compact();
token = securityProperties.getJwtTokenPrefix() + token;
return token;
}
public boolean validateToken(String token){
Claims claims = parser(token);
if (MapUtil.isEmpty(claims)){
return false;
}
return true;
}
public AuthPrincipalVo parserToUser(String token){
String subject = parser(token).getSubject();
if(StrUtil.isNotEmpty(subject)){
return JSONObject.parseObject(subject, AuthPrincipalVo.class);
}
return null;
}
public Claims parser(String token) {
token = token.replaceAll(securityProperties.getJwtTokenPrefix(),"");
return Jwts.parser().setSigningKey(securityProperties.getJwtSecret()).parseClaimsJws(token).getBody();
}
}

View File

@@ -1,102 +0,0 @@
package com.ai.da.common.task;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.mapper.primary.entity.Account;
import com.ai.da.service.AccountService;
import com.ai.da.service.SubscriptionPlanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.List;
@Component
@Slf4j
public class AccountTask {
@Resource
private AccountService accountService;
@Resource
private RedisUtil redisUtil;
@Resource
private SubscriptionPlanService subscriptionPlanService;
/**
* 每周日晚上刷新 年付用户、月付用户的积分
* 替换为
* 每个月月初只刷新教育子账号的积分
*/
// @Scheduled(cron = "0 25 14 * * ?")
// @Scheduled(cron = "0 0 0 1 * ?")
public void refreshCreditsMonthly() {
log.info("每月1号0点 重置教育版子账号为默认积分");
accountService.refreshCreditsMonthly();
}
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
public void getPaidUser() {
// 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单
accountService.extendValidityForCC();
}
// 每天凌晨0点执行一次 目前已没有角色类型为4的用户
/*@Scheduled(cron = "0 0 0 * * ?")
public void cancelActivityBenefits() {
// 1、查询当前所有参与了活动且过期的用户
List<Account> accountList = accountService.getExpiredUserBySystemUser(4);
// 2、将到期用户置为游客
for (Account account : accountList) {
log.info("参与活动的用户{} : {} 于 {} 账号有效期到期,置为游客", account.getId(), account.getUserEmail(), account.getValidEndTime());
accountService.toVisitor(account);
}
}*/
// 每天检测正式用户到期情况每天凌晨0点执行
// @Scheduled(cron = "0 0 0 * * ?")
public void paidUserToVisitor() {
// 1、查询当前已过期正式用户或试用用户
List<Account> accountList = accountService.getExpiredUserBySystemUser(1);
accountList.addAll(accountService.getExpiredUserBySystemUser(2));
accountList.addAll(accountService.getExpiredUserBySystemUser(3));
// 2、将到期用户置为游客
for (Account account : accountList) {
log.info("用户{} : {} 于 {}账号有效期到期,置为游客", account.getId(), account.getUserEmail(), account.getValidEndTime());
accountService.toVisitor(account);
}
}
/**
* 关闭此定时器不再从Code-Create上默认创建AiDA游客
* 将Code-Create上注册的用户添加为AiDA的游客
*/
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
public void registerUserToVisitor() {
accountService.registerUserToVisitor();
}
// @Scheduled(cron = "0 0 0 1 * ?")
// 每月初刷新所有用户用户名剩余修改次数
public void resetUsernameModifyTimes(){
log.info("重置所有用户的用户名修改次数");
redisUtil.batchDeleteKeysWithSamePrefix(RedisUtil.NICKNAME_MODIFY_TIMES);
}
// @Scheduled(cron = "0 35 14 * * ?")
// @Scheduled(cron = "0 5 0 * * ?")
public void checkEduAdminExpireStatus() {
accountService.checkEduAdminExpireStatus();
}
// @Scheduled(cron = "0 5 0 * * ?")
public void activeSubscriptionPlan() {
subscriptionPlanService.activeSubscriptionPlan(null);
}
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
public void expireSubscription() {
subscriptionPlanService.expireSubscription();
}
}

View File

@@ -1,140 +0,0 @@
package com.ai.da.common.task;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.utils.DateUtil;
import com.ai.da.mapper.primary.PoseTransformationMapper;
import com.ai.da.mapper.primary.ToProductImageResultMapper;
import com.ai.da.mapper.primary.entity.*;
import com.ai.da.model.vo.PoseTransformationVO;
import com.ai.da.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.netty.util.internal.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import static com.ai.da.common.enums.CreditsEventsEnum.TO_PRODUCT_IMAGE;
@Slf4j
@Component
@RequiredArgsConstructor
public class GenerateTask {
private final APIGenerateService apiGenerateService;
private final CreditsService creditsService;
private final GenerateService generateService;
private final PoseTransformationMapper poseTransformationMapper;
private final ToProductImageResultMapper toProductImageResultMapper;
/*
* 对于使用了第三方api的允许异步获得结果的生成功能可能在第三方接口的结果Ready时没有及时存储结果导致第三方链接失效
* 万相 24h失效
* flux 10mins失效 使用了flux接口的功能 ToProductImage || Relight, Pattern这里不做补偿
* 故这里通过定时任务做补偿
* flux五分钟查询一次万相1小时查询一次
*/
// @Scheduled(cron = "0 */4 * * * ?")
public void fluxCompensationMechanism(){
// 1、查所有 任务还没成功、还没失败正在等待或者执行中的任务id有哪些
// 由于获取结果的polling_url在redis中只存一天大部分结果超过一天之后就无法再找到任务小部分可以通过公共路径查到结果
List<APIGenerate> apiGenerates = apiGenerateService.getPendingTaskByStatus("flux");
if (apiGenerates != null && !apiGenerates.isEmpty()){
for (APIGenerate apiGenerate : apiGenerates){
String taskId = apiGenerate.getTaskId();
// 1. 根据taskId查toProductImageResult 判断当前任务状态与超时状态
ToProductImageResult toProductImageResult = toProductImageResultMapper.selectOne(new QueryWrapper<ToProductImageResult>().eq("task_id", taskId));
if (Objects.nonNull(toProductImageResult) && "Pending".equals(toProductImageResult.getStatus())){
// 判断当前任务的超时状态
if (!DateUtil.isMoreThanOneDayApart(toProductImageResult.getCreateTime())){
// 1. 未超时,获取当前任务结果
String fileName = toProductImageResult.getResultType().equals(TO_PRODUCT_IMAGE.getName()) ? "product_image" : "relight_image";
String objectName = apiGenerate.getAccountId() + "/" + fileName +"/" + taskId + ".png";
String fluxResult = generateService.getFluxResult(taskId, objectName);
// 2. 成功获取结果下载图片上传至minio,更新toProductImageResult表
if (StringUtil.isNullOrEmpty(fluxResult) || fluxResult.equals("Fail")){
toProductImageResult.setStatus("Fail");
toProductImageResultMapper.updateById(toProductImageResult);
apiGenerate.setStatus("Fail");
apiGenerate.setUpdateTime(LocalDateTime.now());
apiGenerateService.updateById(apiGenerate);
} else if (!fluxResult.equals("Pending")){
if (StringUtil.isNullOrEmpty(toProductImageResult.getUrl())){
toProductImageResult.setStatus("Success");
toProductImageResult.setUrl(fluxResult);
toProductImageResultMapper.updateById(toProductImageResult);
apiGenerate.setStatus("Success");
apiGenerate.setUpdateTime(LocalDateTime.now());
apiGenerateService.updateById(apiGenerate);
}
// 扣积分
Boolean flag = creditsService.taskCreditsDeduction(apiGenerate.getAccountId(), taskId);
if (flag) creditsService.updateChangedCredits(String.valueOf(apiGenerate.getAccountId()), taskId);
}
} else {
// 超时,设置状态为失败
toProductImageResult.setStatus("Fail");
toProductImageResultMapper.updateById(toProductImageResult);
apiGenerate.setStatus("Fail");
apiGenerate.setUpdateTime(LocalDateTime.now());
apiGenerateService.updateById(apiGenerate);
}
// 将积分暂扣区的积分移除
if (toProductImageResult.getStatus().equals("Fail")){
creditsService.deleteCreditsDeduction(apiGenerate.getAccountId(), taskId);
}
}
}
}
}
// 万相 -> pose transformation 补偿 当前任务执行完后5分钟再执行一次不会出现任务重叠的情况
// @Scheduled(fixedDelay = 5 * 60 * 1000)
public void wxCompensationMechanism(){
List<APIGenerate> apiGenerates = apiGenerateService.getPendingTaskByStatus("wx");
if (apiGenerates != null && !apiGenerates.isEmpty()){
log.info("=====万相补偿获取结果开始=====");
for (APIGenerate apiGenerate : apiGenerates){
String taskId = apiGenerate.getTaskId();
PoseTransformation poseTransformation = poseTransformationMapper.selectOne(new QueryWrapper<PoseTransformation>().eq("unique_id", taskId));
if (Objects.nonNull(poseTransformation) && ("Pending".equals(poseTransformation.getTaskStatus()) || "Executing".equals(poseTransformation.getTaskStatus()))){
// 判断当前任务的超时状态
if (!DateUtil.isMoreThanOneDayApart(poseTransformation.getCreateTime())){
try {
// 方法中已经完成了pose_transformation和api_generate表的更新不用额外做处理
PoseTransformationVO animateResult = generateService.getAnimateResult(taskId);
if (animateResult.getStatus().equals("Success")){
log.info("补偿获取结果成功,发送系统消息");
}
} catch (BusinessException e){
log.warn("万相 animation 生成失败,原因:{}", e.getMessage());
}
}
} else {
poseTransformation.setTaskStatus("Fail");
poseTransformation.setUpdateTime(LocalDateTime.now());
poseTransformationMapper.updateById(poseTransformation);
apiGenerate.setStatus("Fail");
apiGenerate.setUpdateTime(LocalDateTime.now());
apiGenerateService.updateById(apiGenerate);
generateService.sendSysMsgForPT(poseTransformation);
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More