Compare commits
282 Commits
4e4b8bd4d2
...
dev/3.1_re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
921d2d956e | ||
|
|
d700f94f9d | ||
|
|
b277479e73 | ||
|
|
83cbd57dea | ||
|
|
4d3b22de82 | ||
|
|
6b5c2cfec0 | ||
|
|
b676de054a | ||
|
|
4c169ef67e | ||
|
|
f2bce066b6 | ||
|
|
6af442eb15 | ||
|
|
768df55309 | ||
|
|
f351277b73 | ||
|
|
a799162ea4 | ||
|
|
c035eb9d7d | ||
|
|
906a54b3c8 | ||
|
|
643799546b | ||
|
|
f582464cd3 | ||
|
|
b864b393bc | ||
|
|
c03a8762e7 | ||
|
|
cb87ad1099 | ||
|
|
fb229764f8 | ||
|
|
8bec1f842d | ||
|
|
b54bd04cff | ||
|
|
b4ccad6242 | ||
|
|
6068bf7d7d | ||
|
|
d36baf747f | ||
| 7c8f1bee6a | |||
|
|
62bd145e2c | ||
|
|
23716984cc | ||
|
|
d0b8b8d674 | ||
|
|
92e7dbf258 | ||
|
|
32a228485b | ||
|
|
560e47747a | ||
|
|
c8dc38575a | ||
|
|
c00d906083 | ||
| 4df3f9cc53 | |||
|
|
b0343be544 | ||
|
|
d33cb9f0bf | ||
|
|
40f2735831 | ||
| 01d3806d5f | |||
| 107e4e9771 | |||
|
|
716d720782 | ||
|
|
6b5bacc49b | ||
|
|
409bc7b1fd | ||
|
|
ec6a5df8af | ||
|
|
029b96ae99 | ||
|
|
14002e7331 | ||
| 14dfe2806c | |||
| 798c7b0592 | |||
| 9bd10581f4 | |||
| 1f288fe5e3 | |||
| 72602eb245 | |||
| 983d53268d | |||
| f3aeeb3584 | |||
| 5d3692a204 | |||
| f2a074b2f6 | |||
| 6a7a37dcec | |||
|
|
c4d2780f0e | ||
|
|
1da6b7728c | ||
|
|
0faf77899b | ||
|
|
e4940019bf | ||
|
|
0da66ff210 | ||
|
|
5dd862ff79 | ||
|
|
edaec9884d | ||
|
|
76eeb2be53 | ||
|
|
cb6f94d2d4 | ||
|
|
28656c44c8 | ||
|
|
6757a89d04 | ||
|
|
9be1a1e307 | ||
|
|
2168978f61 | ||
|
|
54466b935d | ||
|
|
c970ebe691 | ||
|
|
1c5a3a12b9 | ||
|
|
6e06000083 | ||
|
|
dea2b3be42 | ||
|
|
bcf51aea23 | ||
|
|
0c9d5404c6 | ||
|
|
93429839c0 | ||
|
|
27859c3e28 | ||
|
|
f02c0930a6 | ||
|
|
d57bb83b25 | ||
| 731e34f133 | |||
| 75eca8d6ba | |||
| 3e53401f76 | |||
|
|
b6a068ebcd | ||
|
|
dc291ea086 | ||
|
|
2e846e671a | ||
|
|
a5093311f9 | ||
|
|
aed338a6d7 | ||
|
|
8bdb49d25c | ||
|
|
5d53a8cd42 | ||
|
|
61b7f3072f | ||
|
|
a1f489f3a1 | ||
|
|
fc3fd877a8 | ||
|
|
fc72d2c430 | ||
|
|
1ac01dd090 | ||
|
|
3bbdf7c672 | ||
|
|
0646484fba | ||
|
|
96b8613741 | ||
|
|
cf30226a51 | ||
|
|
3c15a3ff68 | ||
|
|
0c904be227 | ||
|
|
7759b56123 | ||
|
|
d5bfaa8822 | ||
| 967c0cbc01 | |||
| 417e34b41a | |||
|
|
d51aa84647 | ||
|
|
5895bc6ab6 | ||
|
|
3301869f20 | ||
|
|
1ec42f4ad5 | ||
| cc506ff7e9 | |||
|
|
f2d43f06f4 | ||
|
|
9251df49f8 | ||
| 430156f4e8 | |||
|
|
d1123aedcc | ||
| 8c007077a3 | |||
|
|
d63b4b4e63 | ||
|
|
b826f0bf39 | ||
|
|
1decd8e258 | ||
|
|
1286e84488 | ||
| a252fdf7f9 | |||
| 807d802178 | |||
| 53f1b548be | |||
| 45dd78032a | |||
| c160da5132 | |||
| b23faeeee2 | |||
| 67789abca4 | |||
| 1c78d66aab | |||
| 528bc69923 | |||
|
|
22880d128d | ||
| 9c56a102cc | |||
| 2f59fe074f | |||
| 9c61b1c8fe | |||
| e30fdf7401 | |||
| ba2d10afbc | |||
| 6146112d04 | |||
| 412550df27 | |||
| 497421e7fe | |||
| 891527426c | |||
|
|
3e334d7956 | ||
|
|
8f0d0953b2 | ||
| f5c3621a5d | |||
|
|
9a1a0045e0 | ||
| 6223c8e994 | |||
| 67bbee49fd | |||
| ad62ceb32a | |||
| 082afe9e94 | |||
| 49288c3a31 | |||
| 81624e36db | |||
| a526b122d1 | |||
|
|
d882b2e817 | ||
|
|
ebf6427d42 | ||
| 77fe03d361 | |||
| 7a44d67dbf | |||
| 55ce2c6c7e | |||
| a426caaca3 | |||
| 7cb7ce2836 | |||
| 8e075f1da4 | |||
|
|
0f0fde2a3e | ||
|
|
8c6389a1f6 | ||
| 652f82b6a4 | |||
| 7ca2528dcf | |||
|
|
a7800913d2 | ||
|
|
1eaec64ff4 | ||
| e603952332 | |||
| 2bc8b8ef96 | |||
| 0ce968b919 | |||
|
|
dfc9ae4db2 | ||
|
|
a3505c6d95 | ||
|
|
6db0afd515 | ||
|
|
b1e6183dd1 | ||
| 30d08356c0 | |||
| 64cc29f456 | |||
|
|
2b3e12a11c | ||
|
|
d4a4724f61 | ||
|
|
ba6e2bd24c | ||
|
|
a38895b028 | ||
|
|
69a95e66ca | ||
|
|
40518cab37 | ||
|
|
46d61cb73f | ||
| 08f20fd1fe | |||
| d7edc166b3 | |||
|
|
79ad02f66b | ||
|
|
5e261b55c7 | ||
|
|
bc92fcbaf4 | ||
|
|
c6aec917c2 | ||
| 6bc500e78f | |||
| 4c43b98c02 | |||
|
|
5bae785a9f | ||
|
|
7b619aa4cb | ||
| c93ad6daa9 | |||
| 0047be7a03 | |||
| 4ef209cfd4 | |||
| a19751b4b7 | |||
|
|
bb0e5a4263 | ||
|
|
9e9df5367d | ||
| ba8a2c52de | |||
| 39d8c7efcf | |||
|
|
401910901a | ||
|
|
3f5ce6e0e7 | ||
| 0787025151 | |||
| 08b26872ff | |||
| 5bbf1326bb | |||
|
|
c5e27cd220 | ||
|
|
112e9c3bc9 | ||
|
|
ce95cb5080 | ||
|
|
71211bfbc3 | ||
| 72ad977dcb | |||
|
|
6400e79929 | ||
|
|
dd8c72f7d7 | ||
| 13151b65f5 | |||
| 9f523d5953 | |||
| 4879cfeb60 | |||
| 9e252b16ef | |||
| e64add14af | |||
| 3beb27e491 | |||
| 501032ef17 | |||
|
|
cb25bdd2e0 | ||
|
|
7a9fb0213b | ||
| cd767dce6f | |||
| bf95b85841 | |||
| 9e58bd9e7d | |||
| d0ec5c5c26 | |||
| ab8aa5ea5c | |||
| aefcd2fdb0 | |||
| e74eab1070 | |||
|
|
34da437a26 | ||
|
|
f84935d0bd | ||
| 35edaa0f27 | |||
| f43099e19e | |||
| 8079877734 | |||
| ef686e38ac | |||
| 100019d2a4 | |||
|
|
12af237d76 | ||
|
|
44dbbb2a4b | ||
| 9f42e153a4 | |||
| 4fa70a1c90 | |||
| dfb34916e7 | |||
| 9f7987306c | |||
|
|
d3fc70fbf2 | ||
|
|
17645d17e5 | ||
|
|
258eea5277 | ||
|
|
bb1d3bd359 | ||
|
|
6a8c87ed95 | ||
|
|
eb3826927d | ||
|
|
7720c8c771 | ||
|
|
b459148d58 | ||
|
|
eadda18d1e | ||
|
|
d403df51ec | ||
| 6903b98b60 | |||
| 81bf65515c | |||
| 8e984eb283 | |||
|
|
afc6041570 | ||
| bce368248c | |||
| ca7121dcda | |||
|
|
9a206f9979 | ||
|
|
eb7a46c7e8 | ||
|
|
95ef68a784 | ||
|
|
6429288fd9 | ||
| c5af194876 | |||
| da84e1e4b4 | |||
| 95a9c81a1b | |||
| 81c0d7eeac | |||
|
|
fbc473735c | ||
|
|
9f48a2ce09 | ||
| 459c743ce4 | |||
| ce3516916d | |||
| 0692b29065 | |||
| 94cafbd10c | |||
| 5c2008ec4a | |||
| 7f094265da | |||
| 22bc8750c8 | |||
| 6cd42b799a | |||
| 6e1ed7f9b8 | |||
| b7be16738b | |||
| 6da5e91ec1 | |||
| a710fdd432 | |||
| d598f53d3c | |||
| 96170a9956 | |||
| 8205fb5290 | |||
| fcbe4762b3 | |||
| e750adcc94 |
111
.gitea/workflows/develop_3.1_MS_build_manual.yaml
Normal file
111
.gitea/workflows/develop_3.1_MS_build_manual.yaml
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
name: 手动 AiDA back-java 开发分支构建部署
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_deploy:
|
||||||
|
runs-on: java21
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
build_status: ${{ job.status }}
|
||||||
|
build_url: ${{ gitea.server_url }}/${{ gitea.repository.owner.name }}/${{ gitea.repository.name }}/actions/runs/${{ gitea.run_id }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
REMOTE_DEPLOY_PATH: /workspace/workspace_aida/DevelopVersion/develop-MS-version-aida-back
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 0.记录开始时间
|
||||||
|
id: build_start_time
|
||||||
|
run: echo "current_time=$(TZ='Asia/Hong_Kong' date '+%Y-%m-%d %H:%M:%S %Z')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: 1.检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: dev/3.1_release_merge_MS
|
||||||
|
|
||||||
|
|
||||||
|
- name: 3.缓存 Maven 依赖
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
|
||||||
|
- name: 4.构建项目
|
||||||
|
run: |
|
||||||
|
java -version
|
||||||
|
mvn -v
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
|
||||||
|
- name: 5.生成Dockerfile
|
||||||
|
run: |
|
||||||
|
echo "===== 生成Dockerfile ====="
|
||||||
|
cat > Dockerfile << 'EOF'
|
||||||
|
FROM openjdk:21-ea-21-jdk-slim
|
||||||
|
VOLUME /tmp
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||||
|
RUN echo 'Asia/Shanghai' > /etc/timezone
|
||||||
|
ADD ./target/aida-0.0.1-SNAPSHOT.jar /app.jar
|
||||||
|
ENTRYPOINT ["java","-jar","/app.jar"]
|
||||||
|
EOF
|
||||||
|
echo "Dockerfile内容:"
|
||||||
|
cat Dockerfile
|
||||||
|
|
||||||
|
- name: 6.生成docker-compose.yml
|
||||||
|
run: |
|
||||||
|
echo "===== 生成docker-compose.yml ====="
|
||||||
|
cat > docker-compose.yml << 'EOF'
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
aida_back:
|
||||||
|
container_name: develop-aida-ms
|
||||||
|
build: .
|
||||||
|
volumes:
|
||||||
|
# 数据挂载
|
||||||
|
- ./log:/log
|
||||||
|
- ./temp:/temp
|
||||||
|
- ./uploads:/temp/uploads
|
||||||
|
ports:
|
||||||
|
- '10092:10092'
|
||||||
|
restart: always
|
||||||
|
EOF
|
||||||
|
# 验证docker-compose.yml生成
|
||||||
|
echo "docker-compose.yml内容:"
|
||||||
|
cat docker-compose.yml
|
||||||
|
|
||||||
|
- name: 7.上传jar到远程服务器
|
||||||
|
uses: appleboy/scp-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SERVER_HOST }}
|
||||||
|
port: 22
|
||||||
|
username: ${{ secrets.SERVER_USER }}
|
||||||
|
key: ${{ secrets.SSH_KEY }}
|
||||||
|
source: "target/*.jar,Dockerfile,docker-compose.yml"
|
||||||
|
target: ${{ env.REMOTE_DEPLOY_PATH }}
|
||||||
|
preserve_host_directory_structure: false
|
||||||
|
|
||||||
|
- name: 8. 重启 Docker 服务
|
||||||
|
uses: appleboy/ssh-action@master # 👈 专门执行命令的 action
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SERVER_HOST }}
|
||||||
|
username: ${{ secrets.SERVER_USER }}
|
||||||
|
key: ${{ secrets.SSH_KEY }}
|
||||||
|
key_base64: true
|
||||||
|
script: |
|
||||||
|
echo "========= 进入部署目录 ========="
|
||||||
|
cd ${{ env.REMOTE_DEPLOY_PATH }}
|
||||||
|
ls -l
|
||||||
|
|
||||||
|
echo "========= 停止旧服务 ========="
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
echo "========= 启动新服务 ========="
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
echo "========= 查看运行状态 ========="
|
||||||
|
docker compose ps
|
||||||
@@ -99,9 +99,17 @@ 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内容:"
|
||||||
|
|||||||
70
pom.xml
70
pom.xml
@@ -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.1.6</version>
|
<version>3.2.5</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.aida</groupId>
|
<groupId>com.aida</groupId>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<description>ai da</description>
|
<description>ai da</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>21</java.version>
|
<java.version>21</java.version>
|
||||||
<mybatis.plus.version>3.5.5</mybatis.plus.version>
|
<mybatis.plus.version>3.5.7</mybatis.plus.version>
|
||||||
<hutool.version>5.8.23</hutool.version>
|
<hutool.version>5.8.23</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.43</fastjson.version>
|
||||||
@@ -28,6 +28,11 @@
|
|||||||
<javacv.version>1.5.5</javacv.version>
|
<javacv.version>1.5.5</javacv.version>
|
||||||
<system.windowsx64>windows-x86_64</system.windowsx64>
|
<system.windowsx64>windows-x86_64</system.windowsx64>
|
||||||
<javacpp.platform.linux-x86_64>linux-x86_64</javacpp.platform.linux-x86_64>
|
<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>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -38,6 +43,22 @@
|
|||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -74,9 +95,14 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-spring-boot3-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>
|
||||||
@@ -237,6 +263,12 @@
|
|||||||
<version>2.15.1</version>
|
<version>2.15.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.13.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.stripe</groupId>
|
<groupId>com.stripe</groupId>
|
||||||
<artifactId>stripe-java</artifactId>
|
<artifactId>stripe-java</artifactId>
|
||||||
@@ -427,6 +459,38 @@
|
|||||||
<artifactId>bcpkix-jdk18on</artifactId>
|
<artifactId>bcpkix-jdk18on</artifactId>
|
||||||
<version>1.78.1</version>
|
<version>1.78.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- AOP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- ==================== 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>
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
package com.ai.da;
|
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.scheduling.annotation.EnableAsync;
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
@Slf4j
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
@SpringBootApplication
|
|
||||||
@EnableScheduling
|
@Slf4j
|
||||||
@EnableAsync
|
@SpringBootApplication
|
||||||
public class AiDaApplication {
|
@EnableScheduling
|
||||||
|
@EnableAsync
|
||||||
public static void main(String[] args) {
|
@EnableFeignClients
|
||||||
SpringApplication.run(AiDaApplication.class, args);
|
@EnableDiscoveryClient
|
||||||
log.info("AiDaApplication 启动完成!");
|
public class AiDaApplication {
|
||||||
}
|
|
||||||
|
public static void main(String[] args) {
|
||||||
}
|
SpringApplication.run(AiDaApplication.class, args);
|
||||||
|
log.info("AiDaApplication 启动完成!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -559,103 +559,103 @@ public class GenerateConsumer {
|
|||||||
log.info("============ProcessPoseTransformResult End listening==========");
|
log.info("============ProcessPoseTransformResult End listening==========");
|
||||||
}
|
}
|
||||||
|
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer1(Message msg, Channel channel) {
|
// public void generateConsumer1(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 1");
|
// generate(msg, channel, "consumer 1");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer2(Message msg, Channel channel) {
|
// public void generateConsumer2(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 2");
|
// generate(msg, channel, "consumer 2");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer3(Message msg, Channel channel) {
|
// public void generateConsumer3(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 3");
|
// generate(msg, channel, "consumer 3");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer4(Message msg, Channel channel) {
|
// public void generateConsumer4(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 4");
|
// generate(msg, channel, "consumer 4");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer5(Message msg, Channel channel) {
|
// public void generateConsumer5(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 5");
|
// generate(msg, channel, "consumer 5");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer6(Message msg, Channel channel) {
|
// public void generateConsumer6(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 6");
|
// generate(msg, channel, "consumer 6");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer7(Message msg, Channel channel) {
|
// public void generateConsumer7(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 7");
|
// generate(msg, channel, "consumer 7");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer8(Message msg, Channel channel) {
|
// public void generateConsumer8(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 8");
|
// generate(msg, channel, "consumer 8");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generate}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void generateConsumer9(Message msg, Channel channel) {
|
// public void generateConsumer9(Message msg, Channel channel) {
|
||||||
generate(msg, channel, "consumer 9");
|
// generate(msg, channel, "consumer 9");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.generateResult}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.generateResult}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getGenerateResult(Message msg, Channel channel) {
|
// public void getGenerateResult(Message msg, Channel channel) {
|
||||||
processGenerateResult(msg, channel);
|
// processGenerateResult(msg, channel);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageResult}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageResult}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getToProductImageResult(Message msg, Channel channel) {
|
// public void getToProductImageResult(Message msg, Channel channel) {
|
||||||
processToProductImageResult(msg, channel);
|
// processToProductImageResult(msg, channel);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.relightResult}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.relightResult}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getRelightResult(Message msg, Channel channel) {
|
// public void getRelightResult(Message msg, Channel channel) {
|
||||||
processRelightResult(msg, channel);
|
// processRelightResult(msg, channel);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransform}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransform}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getPoseTransformationResult(Message msg, Channel channel) {
|
// public void getPoseTransformationResult(Message msg, Channel channel) {
|
||||||
processPoseTransformResult(msg, channel);
|
// processPoseTransformResult(msg, channel);
|
||||||
}
|
// }
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.designBatch}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.designBatch}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getDesignBatchResult(Message msg, Channel channel) {
|
// public void getDesignBatchResult(Message msg, Channel channel) {
|
||||||
processDesignBatchResult(msg, channel);
|
// processDesignBatchResult(msg, channel);
|
||||||
}
|
// }
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageBatch}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.toProductImageBatch}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getToProductImageBatchResult(Message msg, Channel channel) {
|
// public void getToProductImageBatchResult(Message msg, Channel channel) {
|
||||||
processToProductImageBatchResult(msg, channel);
|
// processToProductImageBatchResult(msg, channel);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.relightBatch}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.relightBatch}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getRelightBatchResult(Message msg, Channel channel) {
|
// public void getRelightBatchResult(Message msg, Channel channel) {
|
||||||
processRelightBatchResult(msg, channel);
|
// processRelightBatchResult(msg, channel);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransformBatch}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.poseTransformBatch}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void getPoseTransformBatchResult(Message msg, Channel channel) {
|
// public void getPoseTransformBatchResult(Message msg, Channel channel) {
|
||||||
processPoseTransformBatchResult(msg, channel);
|
// processPoseTransformBatchResult(msg, channel);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ public class MQPublisher {
|
|||||||
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getSr(), mm);
|
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getSr(), mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendGenerateResultMessage(String mm) {
|
||||||
|
log.info("send generate result message: {}", mm);
|
||||||
|
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getGenerateResult(), mm);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param mailParams 含有的字段
|
* @param mailParams 含有的字段
|
||||||
|
|||||||
@@ -222,16 +222,16 @@ public class SRConsumer {
|
|||||||
taskListService.updateTaskStatusOrOutputRedis(uniqueId, "fail", null);
|
taskListService.updateTaskStatusOrOutputRedis(uniqueId, "fail", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.sr}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.sr}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void SRConsumer1(Message msg, Channel channel) {
|
// public void SRConsumer1(Message msg, Channel channel) {
|
||||||
superResolution(msg, channel, "consumer 1");
|
// superResolution(msg, channel, "consumer 1");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@RabbitListener(queues = "#{rabbitMQProperties.queues.srResult}")
|
// @RabbitListener(queues = "#{rabbitMQProperties.queues.srResult}")
|
||||||
@RabbitHandler
|
// @RabbitHandler
|
||||||
public void SRResultConsumer1(Message msg, Channel channel) {
|
// public void SRResultConsumer1(Message msg, Channel channel) {
|
||||||
getSRResult(msg, channel, "consumer 1");
|
// getSRResult(msg, channel, "consumer 1");
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
package com.ai.da.common.aspect;
|
||||||
|
|
||||||
|
import com.ai.da.common.context.UserContext;
|
||||||
|
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller日志切面
|
||||||
|
* 记录所有Controller接口的请求参数和用户信息
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class ControllerLoggingAspect {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ControllerLoggingAspect.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义切点:所有Controller方法
|
||||||
|
*/
|
||||||
|
@Pointcut("execution(* com.ai.da.controller..*(..))")
|
||||||
|
public void controllerMethods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller方法执行前记录日志
|
||||||
|
*/
|
||||||
|
// @Before("controllerMethods()")
|
||||||
|
public void logControllerBefore(JoinPoint joinPoint) {
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
if (attributes != null) {
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
|
||||||
|
// 获取当前用户ID
|
||||||
|
Long userId = null;
|
||||||
|
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||||
|
if (authPrincipalVo != null) {
|
||||||
|
userId = authPrincipalVo.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请求参数
|
||||||
|
Map<String, Object> params = getRequestParams(joinPoint, request);
|
||||||
|
|
||||||
|
logger.info("=== 请求开始 ===");
|
||||||
|
logger.info("用户ID: {}", userId);
|
||||||
|
logger.info("请求URL: {}", request.getRequestURL().toString());
|
||||||
|
logger.info("请求方法: {}", request.getMethod());
|
||||||
|
logger.info("请求IP: {}", getClientIpAddress(request));
|
||||||
|
logger.info("调用方法: {}.{}", joinPoint.getSignature().getDeclaringType().getSimpleName(), joinPoint.getSignature().getName());
|
||||||
|
logger.info("请求参数: {}", params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> getRequestParams(JoinPoint joinPoint, HttpServletRequest request) {
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
|
||||||
|
// 1. 获取Query String参数
|
||||||
|
String queryString = request.getQueryString();
|
||||||
|
if (queryString != null && !queryString.isEmpty()) {
|
||||||
|
params.put("queryString", queryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取方法参数(包含 @PathVariable, @RequestParam, @RequestBody 等)
|
||||||
|
Object[] args = joinPoint.getArgs();
|
||||||
|
|
||||||
|
if (args != null && args.length > 0) {
|
||||||
|
Map<String, Object> methodParams = new HashMap<>();
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
Object arg = args[i];
|
||||||
|
// 过滤掉不可序列化的参数
|
||||||
|
if (arg != null) {
|
||||||
|
if (isIgnorable(arg)) {
|
||||||
|
// 对于可忽略的类型,记录类型名
|
||||||
|
methodParams.put("arg" + i, "[" + arg.getClass().getSimpleName() + "]");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
methodParams.put("arg" + i, arg);
|
||||||
|
} catch (Exception e) {
|
||||||
|
methodParams.put("arg" + i, arg.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!methodParams.isEmpty()) {
|
||||||
|
params.put("methodParams", methodParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否需要过滤的参数类型
|
||||||
|
*/
|
||||||
|
private boolean isIgnorable(Object obj) {
|
||||||
|
return obj instanceof HttpServletRequest
|
||||||
|
|| obj instanceof HttpServletResponse
|
||||||
|
|| obj instanceof MultipartFile
|
||||||
|
|| obj instanceof MultipartFile[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller方法抛出异常时记录日志
|
||||||
|
*/
|
||||||
|
@AfterThrowing(pointcut = "controllerMethods()", throwing = "exception")
|
||||||
|
public void logControllerAfterThrowing(JoinPoint joinPoint, Throwable exception) {
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
|
||||||
|
Long userId = null;
|
||||||
|
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||||
|
if (authPrincipalVo != null) {
|
||||||
|
userId = authPrincipalVo.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取请求参数
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
if (attributes != null) {
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
params = getRequestParams(joinPoint, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error("=== 请求异常 ===");
|
||||||
|
logger.error("用户ID: {}", userId);
|
||||||
|
logger.error("调用方法: {}.{}", joinPoint.getSignature().getDeclaringType().getSimpleName(), joinPoint.getSignature().getName());
|
||||||
|
logger.error("请求参数: {}", params);
|
||||||
|
logger.error("异常信息: ", exception);
|
||||||
|
logger.error("=== 异常结束 ===");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端真实IP地址
|
||||||
|
*/
|
||||||
|
private String getClientIpAddress(HttpServletRequest request) {
|
||||||
|
String xForwardedFor = request.getHeader("X-Forwarded-For");
|
||||||
|
if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
|
||||||
|
return xForwardedFor.split(",")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
String xRealIp = request.getHeader("X-Real-IP");
|
||||||
|
if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
|
||||||
|
return xRealIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String proxyClientIp = request.getHeader("Proxy-Client-IP");
|
||||||
|
if (proxyClientIp != null && !proxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(proxyClientIp)) {
|
||||||
|
return proxyClientIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String wlProxyClientIp = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
if (wlProxyClientIp != null && !wlProxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(wlProxyClientIp)) {
|
||||||
|
return wlProxyClientIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -202,7 +202,7 @@ public class MyTaskScheduler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Scheduled(cron = "0 0 9 * * ?")
|
// @Scheduled(cron = "0 0 9 * * ?")
|
||||||
public void sendTrialOrderExcelToManagements() {
|
public void sendTrialOrderExcelToManagements() {
|
||||||
// 获取前一天日期
|
// 获取前一天日期
|
||||||
LocalDate yesterday = LocalDate.now().minusDays(1);
|
LocalDate yesterday = LocalDate.now().minusDays(1);
|
||||||
@@ -308,7 +308,7 @@ public class MyTaskScheduler {
|
|||||||
private MinioUtil minioUtil;
|
private MinioUtil minioUtil;
|
||||||
@Resource
|
@Resource
|
||||||
private UserLikeService userLikeService;
|
private UserLikeService userLikeService;
|
||||||
public void clearMinio() {
|
/* public void clearMinio() {
|
||||||
List<CollectionElement> collectionElements = collectionElementMapper.selectDeleteList();
|
List<CollectionElement> collectionElements = collectionElementMapper.selectDeleteList();
|
||||||
for (CollectionElement collectionElement : collectionElements) {
|
for (CollectionElement collectionElement : collectionElements) {
|
||||||
String url = collectionElement.getUrl();
|
String url = collectionElement.getUrl();
|
||||||
@@ -472,7 +472,7 @@ public class MyTaskScheduler {
|
|||||||
// }
|
// }
|
||||||
// String preSignedUrl = minioUtil.getPreSignedUrl("aida-clothing/image/image_1698374859.3031476.png", 10000);
|
// String preSignedUrl = minioUtil.getPreSignedUrl("aida-clothing/image/image_1698374859.3031476.png", 10000);
|
||||||
// System.out.println(preSignedUrl);
|
// System.out.println(preSignedUrl);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AttributeRetrievalMapper attributeRetrievalMapper;
|
private AttributeRetrievalMapper attributeRetrievalMapper;
|
||||||
|
|||||||
34
src/main/java/com/ai/da/common/config/SecurityConfig.java
Normal file
34
src/main/java/com/ai/da/common/config/SecurityConfig.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
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 配置。
|
||||||
|
* 由于鉴权逻辑已迁移至 Gateway(GlobalAuthWebFilter),
|
||||||
|
* 后端服务 (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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
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.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Validation;
|
import jakarta.validation.Validation;
|
||||||
import jakarta.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
import jakarta.validation.ValidatorFactory;
|
import jakarta.validation.ValidatorFactory;
|
||||||
@@ -17,11 +20,20 @@ public class WebConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
static final String ORIGINS[] = new String[]{"GET", "POST", "PUT", "DELETE"};
|
static final String ORIGINS[] = new String[]{"GET", "POST", "PUT", "DELETE"};
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserContextInterceptor userContextInterceptor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCorsMappings(CorsRegistry registry) {
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
registry.addMapping("/**").allowedOriginPatterns("*").allowCredentials(true).allowedMethods(ORIGINS).maxAge(3600);
|
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() {
|
||||||
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
|
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
|
||||||
|
|||||||
@@ -1,89 +1,99 @@
|
|||||||
package com.ai.da.common.config.exception;
|
package com.ai.da.common.config.exception;
|
||||||
|
|
||||||
import com.ai.da.common.response.Response;
|
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.validation.BindException;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.validation.BindException;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
/**
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
* @author: dangweijian
|
|
||||||
* @description: 全局异常捕获
|
/**
|
||||||
* @create: 2019-12-03 10:24
|
* @author: dangweijian
|
||||||
**/
|
* @description: 全局异常捕获
|
||||||
@Slf4j
|
* @create: 2019-12-03 10:24
|
||||||
@ControllerAdvice
|
**/
|
||||||
public class ExceptionCatch {
|
@Slf4j
|
||||||
|
@ControllerAdvice
|
||||||
/**
|
public class ExceptionCatch {
|
||||||
* 线程安全,且构建后不可更改
|
|
||||||
*/
|
/**
|
||||||
private static ImmutableMap<Class<? extends Throwable>, ResultEnum> EXCEPTIONS;
|
* 线程安全,且构建后不可更改
|
||||||
|
*/
|
||||||
/**
|
private static ImmutableMap<Class<? extends Throwable>, ResultEnum> EXCEPTIONS;
|
||||||
* 用于构建ImmutableMap
|
|
||||||
*/
|
/**
|
||||||
private static ImmutableMap.Builder<Class<? extends Throwable>, ResultEnum> builder = ImmutableMap.builder();
|
* 用于构建ImmutableMap
|
||||||
|
*/
|
||||||
@ResponseBody
|
private static ImmutableMap.Builder<Class<? extends Throwable>, ResultEnum> builder = ImmutableMap.builder();
|
||||||
@ExceptionHandler(BusinessException.class)
|
|
||||||
public Response<String> businessExceptionCatch(BusinessException e) {
|
@ResponseBody
|
||||||
log.error("发生业务异常,code:[{}],msg:[{}]", e.getCode(), e.getMsg(), e);
|
@ExceptionHandler(BusinessException.class)
|
||||||
return Response.error(e.getCode(), e.getMsg());
|
public Response<String> businessExceptionCatch(BusinessException e) {
|
||||||
}
|
log.error("发生业务异常,code:[{}],msg:[{}]", e.getCode(), e.getMsg(), e);
|
||||||
|
return Response.error(e.getCode(), e.getMsg());
|
||||||
@ResponseBody
|
}
|
||||||
@ExceptionHandler(Exception.class)
|
|
||||||
public Response<String> exceptionCatch(Exception e) {
|
@ResponseBody
|
||||||
log.error("发生系统异常,message:[{}]", e.getMessage(), e);
|
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||||
//如果ImmutableMap集合为空,构建ImmutableMap
|
@ExceptionHandler(UnauthorizedException.class)
|
||||||
if (EXCEPTIONS == null || EXCEPTIONS.size() == 0) {
|
public Response<String> unauthorizedExceptionCatch(UnauthorizedException e) {
|
||||||
EXCEPTIONS = builder.build();
|
log.error("Unauthorized: {}", e.getMessage());
|
||||||
}
|
return Response.error(401, e.getMessage());
|
||||||
//获取不可预知异常自定义错误码
|
}
|
||||||
if (EXCEPTIONS != null) {
|
|
||||||
ResultEnum resultEnum = EXCEPTIONS.get(e.getClass());
|
@ResponseBody
|
||||||
if (resultEnum != null) {
|
@ExceptionHandler(Exception.class)
|
||||||
return Response.error(resultEnum.getCode(), resultEnum.getMsg());
|
public Response<String> exceptionCatch(Exception e) {
|
||||||
}
|
log.error("发生系统异常,message:[{}]", e.getMessage(), e);
|
||||||
}
|
//如果ImmutableMap集合为空,构建ImmutableMap
|
||||||
return Response.error(ResultEnum.ERROR.getCode(), e.getMessage() == null ? ResultEnum.ERROR.getMsg() : e.getMessage());
|
if (EXCEPTIONS == null || EXCEPTIONS.size() == 0) {
|
||||||
}
|
EXCEPTIONS = builder.build();
|
||||||
|
}
|
||||||
/**
|
//获取不可预知异常自定义错误码
|
||||||
* 处理参数校验异常
|
if (EXCEPTIONS != null) {
|
||||||
*
|
ResultEnum resultEnum = EXCEPTIONS.get(e.getClass());
|
||||||
* @param e
|
if (resultEnum != null) {
|
||||||
* @return ResponseData
|
return Response.error(resultEnum.getCode(), resultEnum.getMsg());
|
||||||
*/
|
}
|
||||||
@ResponseBody
|
}
|
||||||
@ExceptionHandler(BindException.class)
|
return Response.error(ResultEnum.ERROR.getCode(), e.getMessage() == null ? ResultEnum.ERROR.getMsg() : e.getMessage());
|
||||||
public Response<String> bindExceptionHandler(BindException e) {
|
}
|
||||||
log.error("参数错误bind:{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
|
||||||
BusinessException businessException = new BusinessException(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
/**
|
||||||
return Response.error(businessException.getCode(), businessException.getMsg());
|
* 处理参数校验异常
|
||||||
}
|
*
|
||||||
|
* @param e
|
||||||
/**
|
* @return ResponseData
|
||||||
* 处理参数校验异常
|
*/
|
||||||
*
|
@ResponseBody
|
||||||
* @param e
|
@ExceptionHandler(BindException.class)
|
||||||
* @return ResponseData
|
public Response<String> bindExceptionHandler(BindException e) {
|
||||||
*/
|
log.error("参数错误bind:{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||||
@ResponseBody
|
BusinessException businessException = new BusinessException(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
return Response.error(businessException.getCode(), businessException.getMsg());
|
||||||
public Response<String> handleValidationException(MethodArgumentNotValidException e) {
|
}
|
||||||
log.error("参数错误bind:{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
|
||||||
BusinessException businessException = new BusinessException(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
/**
|
||||||
return Response.error(businessException.getCode(), businessException.getMsg());
|
* 处理参数校验异常
|
||||||
}
|
*
|
||||||
|
* @param e
|
||||||
//初始化,不可预知异常自定义错误编码
|
* @return ResponseData
|
||||||
static {
|
*/
|
||||||
// builder.put(FileNotFoundException.class, ResultEnum.FILE_NOT_EXIST);
|
@ResponseBody
|
||||||
}
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
}
|
public Response<String> handleValidationException(MethodArgumentNotValidException e) {
|
||||||
|
log.error("参数错误bind:{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||||
|
BusinessException businessException = new BusinessException(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||||
|
return Response.error(businessException.getCode(), businessException.getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
//初始化,不可预知异常自定义错误编码
|
||||||
|
static {
|
||||||
|
// builder.put(FileNotFoundException.class, ResultEnum.FILE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.ai.da.common.config.exception;
|
|
||||||
|
|
||||||
public class TokenMissingOrExpiredException extends RuntimeException {
|
|
||||||
public TokenMissingOrExpiredException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Throwable fillInStackTrace() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.ai.da.common.config.exception;
|
||||||
|
|
||||||
|
public class UnauthorizedException extends RuntimeException {
|
||||||
|
|
||||||
|
public UnauthorizedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnauthorizedException() {
|
||||||
|
super("Gateway token verification failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ public class CommonConstant {
|
|||||||
// 单位 秒 两天过期
|
// 单位 秒 两天过期
|
||||||
public static final Long CREDITS_EXPIRE_TIME = 2 * 24 * 60 * 60L;
|
public static final Long CREDITS_EXPIRE_TIME = 2 * 24 * 60 * 60L;
|
||||||
// 单位 分钟
|
// 单位 分钟
|
||||||
public static final Integer MINIO_IMAGE_EXPIRE_TIME = 24 * 60;
|
public static final Integer MINIO_IMAGE_EXPIRE_TIME = 24 * 60 * 7;
|
||||||
// 单位 秒 一天过期 in redis
|
// 单位 秒 一天过期 in redis
|
||||||
public static final Long GENERATE_RESULT_EXPIRE_TIME = 24 * 60 * 60L;
|
public static final Long GENERATE_RESULT_EXPIRE_TIME = 24 * 60 * 60L;
|
||||||
// 单位 秒 7天过期
|
// 单位 秒 7天过期
|
||||||
@@ -23,6 +23,7 @@ public class CommonConstant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static final String GENERATE_PATH = "/api/generate_image";
|
public static final String GENERATE_PATH = "/api/generate_image";
|
||||||
|
public static final String GENERATE_PATH_FLUX2_KLEIN = "/api/generate_image_flux2_klein";
|
||||||
|
|
||||||
public static final String GENERATE_SINGLE_LOGO = "/api/generate_single_logo";
|
public static final String GENERATE_SINGLE_LOGO = "/api/generate_single_logo";
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ public class ModelConstants {
|
|||||||
|
|
||||||
// 模型名称常量
|
// 模型名称常量
|
||||||
public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image";
|
public static final String PRINTBOARD_ADVANCED_T2I = "qwen-image";
|
||||||
public static final String MOODBOARD_ADVANCED = "doubao-seedream-3-0-t2i-250415";
|
public static final String MOODBOARD_ADVANCED = "doubao-seedream-4-5-251128";
|
||||||
public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-3-0-t2i-250415";
|
public static final String PRINTBOARD_HIGH_T2I = "doubao-seedream-4-0-250828-high";
|
||||||
public static final String PRINTBOARD_HIGH_I2I = "doubao-seededit-3-0-i2i-250628";
|
public static final String PRINTBOARD_HIGH_I2I = "doubao-seedream-4-0-250828-fast";
|
||||||
public static final String PRINTBOARD_ADVANCED_I2I = "doubao-seedream-4-0-250828";
|
public static final String PRINTBOARD_ADVANCED_I2I = "doubao-seedream-4-0-250828";
|
||||||
public static final String IMAGEN_MODEL = "imagen-4.0-generate-001";
|
public static final String IMAGEN_MODEL = "imagen-4.0-generate-001";
|
||||||
public static final String NANO_BANANA = "gemini-2.5-flash-image";
|
public static final String NANO_BANANA = "gemini-2.5-flash-image";
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
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";
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,41 @@
|
|||||||
package com.ai.da.common.context;
|
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 ThreadLocal<AuthPrincipalVo> userHolder = new ThreadLocal<AuthPrincipalVo>();
|
private static final ThreadLocal<AuthPrincipalVo> userHolder = new ThreadLocal<>();
|
||||||
|
|
||||||
public static AuthPrincipalVo getUserHolder() {
|
public static void setUserHolder(AuthPrincipalVo authPrincipalVo) {
|
||||||
return userHolder.get();
|
userHolder.set(authPrincipalVo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void delete() {
|
public static AuthPrincipalVo getUserHolder() {
|
||||||
userHolder.remove();
|
AuthPrincipalVo holder = userHolder.get();
|
||||||
}
|
if (holder == null) {
|
||||||
|
throw new RuntimeException("User not authenticated");
|
||||||
public static void setUserHolder(AuthPrincipalVo authPrincipalVo) {
|
}
|
||||||
userHolder.set(authPrincipalVo);
|
if (!"AIDA".equals(holder.getSource())) {
|
||||||
}
|
throw new RuntimeException("Access denied: source must be AIDA");
|
||||||
}
|
}
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete() {
|
||||||
|
userHolder.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getUserId() {
|
||||||
|
return getUserHolder().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getBuyerId() {
|
||||||
|
AuthPrincipalVo holder = userHolder.get();
|
||||||
|
if (holder == null) {
|
||||||
|
throw new RuntimeException("User not authenticated");
|
||||||
|
}
|
||||||
|
if (!"BUYER".equals(holder.getSource())) {
|
||||||
|
throw new RuntimeException("Access denied: source must be BUYER");
|
||||||
|
}
|
||||||
|
return holder.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ public enum AuthenticationOperationTypeEnum {
|
|||||||
*/
|
*/
|
||||||
UPDATE_USERINFO,
|
UPDATE_USERINFO,
|
||||||
|
|
||||||
REGISTER;
|
REGISTER,
|
||||||
|
/**
|
||||||
|
* Global_Award 活动验证
|
||||||
|
*/
|
||||||
|
GLOBAL_AWARD;
|
||||||
|
|
||||||
public static AuthenticationOperationTypeEnum of(String name) {
|
public static AuthenticationOperationTypeEnum of(String name) {
|
||||||
return Stream.of(AuthenticationOperationTypeEnum.values()).filter(v -> v.name().equals(name)).findFirst().orElse(null);
|
return Stream.of(AuthenticationOperationTypeEnum.values()).filter(v -> v.name().equals(name)).findFirst().orElse(null);
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
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.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@@ -16,17 +15,17 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ApiModel("分页响应结果")
|
@Schema(description = "分页响应结果")
|
||||||
public class PageBaseResponse<T> {
|
public class PageBaseResponse<T> {
|
||||||
@ApiModelProperty("页码")
|
@Schema(description = "页码")
|
||||||
private long page;
|
private long page;
|
||||||
@ApiModelProperty("每页数量")
|
@Schema(description = "每页数量")
|
||||||
private long size;
|
private long size;
|
||||||
@ApiModelProperty("总页数")
|
@Schema(description = "总页数")
|
||||||
private long pages;
|
private long pages;
|
||||||
@ApiModelProperty("总条数")
|
@Schema(description = "总条数")
|
||||||
private long total;
|
private long total;
|
||||||
@ApiModelProperty("结果集")
|
@Schema(description = "结果集")
|
||||||
private List<T> content;
|
private List<T> content;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
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.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@@ -16,18 +15,18 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ApiModel("分页响应结果")
|
@Schema(description = "分页响应结果")
|
||||||
public class PageResponse<T> extends Response<List<T>> {
|
public class PageResponse<T> extends Response<List<T>> {
|
||||||
@ApiModelProperty("页码")
|
@Schema(description = "页码")
|
||||||
private long page;
|
private long page;
|
||||||
@ApiModelProperty("每页数量")
|
@Schema(description = "每页数量")
|
||||||
private long size;
|
private long size;
|
||||||
@ApiModelProperty("总页数")
|
@Schema(description = "总页数")
|
||||||
private long pages;
|
private long pages;
|
||||||
@ApiModelProperty("总条数")
|
@Schema(description = "总条数")
|
||||||
private long total;
|
private long total;
|
||||||
|
|
||||||
@ApiModelProperty("结果集")
|
@Schema(description = "结果集")
|
||||||
private List<T> content;
|
private List<T> content;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ai.da.common.response;
|
package com.ai.da.common.response;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -17,14 +16,14 @@ import java.io.Serializable;
|
|||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ApiModel("响应结果")
|
@Schema(description = "响应结果")
|
||||||
public class Response<T> implements Serializable {
|
public class Response<T> implements Serializable {
|
||||||
|
|
||||||
@ApiModelProperty("响应状态码 0:成功 -1:失败")
|
@Schema(description = "响应状态码 0:成功 -1:失败")
|
||||||
private int errCode;
|
private int errCode;
|
||||||
@ApiModelProperty("提示消息")
|
@Schema(description = "提示消息")
|
||||||
private String errMsg;
|
private String errMsg;
|
||||||
@ApiModelProperty("数据结果")
|
@Schema(description = "数据结果")
|
||||||
private T data;
|
private T data;
|
||||||
|
|
||||||
public static <T> Response<T> success() {
|
public static <T> Response<T> success() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.ai.da.common.response;
|
package com.ai.da.common.response;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import java.math.BigDecimal;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ApiModel("交易记录分页响应结果")
|
@Schema(description = "交易记录分页响应结果")
|
||||||
public class TransactionPageResponse<T> extends PageBaseResponse<T> {
|
public class TransactionPageResponse<T> extends PageBaseResponse<T> {
|
||||||
|
|
||||||
private BigDecimal totalAmount;
|
private BigDecimal totalAmount;
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
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 jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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 jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
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 jakarta.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
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 jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
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 jakarta.annotation.Resource;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
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.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.config.Customizer;
|
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
|
||||||
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.config.annotation.web.configurers.HeadersConfigurer;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
|
||||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
||||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@EnableMethodSecurity(prePostEnabled = true)
|
|
||||||
@EnableConfigurationProperties(SecurityProperties.class)
|
|
||||||
public class SecurityConfig {
|
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationManager authenticationManager() throws Exception {
|
|
||||||
return this.userAuthenticationManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
|
|
||||||
httpSecurity
|
|
||||||
.cors(Customizer.withDefaults())
|
|
||||||
.authorizeHttpRequests(auth -> auth
|
|
||||||
.requestMatchers(
|
|
||||||
new AntPathRequestMatcher("/doc.html"),
|
|
||||||
new AntPathRequestMatcher("/swagger-ui.html"),
|
|
||||||
new AntPathRequestMatcher("/swagger-ui/**"),
|
|
||||||
new AntPathRequestMatcher("/swagger-resources/**"),
|
|
||||||
new AntPathRequestMatcher("/v2/api-docs"),
|
|
||||||
new AntPathRequestMatcher("/v3/api-docs/**"),
|
|
||||||
new AntPathRequestMatcher("/webjars/**")
|
|
||||||
).permitAll()
|
|
||||||
.requestMatchers(securityProperties.getIgnorePaths()).permitAll()
|
|
||||||
.anyRequest().authenticated()
|
|
||||||
)
|
|
||||||
.headers(headers -> headers
|
|
||||||
.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)
|
|
||||||
.cacheControl(cache -> cache.disable())
|
|
||||||
)
|
|
||||||
.exceptionHandling(exception -> exception
|
|
||||||
.authenticationEntryPoint(userAuthenticationEntryPointHandler)
|
|
||||||
.accessDeniedHandler(userAuthAccessDeniedHandler)
|
|
||||||
)
|
|
||||||
.formLogin(form -> form
|
|
||||||
.loginProcessingUrl(securityProperties.getAuthApi())
|
|
||||||
.successHandler(userLoginSuccessHandler)
|
|
||||||
.failureHandler(userLoginFailureHandler)
|
|
||||||
)
|
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
|
||||||
.sessionManagement(session -> session
|
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
|
||||||
);
|
|
||||||
|
|
||||||
//自定义过滤器在登录时认证用户名、密码
|
|
||||||
httpSecurity.addFilterAt(userAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class)
|
|
||||||
.addFilterBefore(authenticationFilter, BasicAuthenticationFilter.class);
|
|
||||||
|
|
||||||
return httpSecurity.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
|
|
||||||
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
|
|
||||||
handler.setPermissionEvaluator(userPermissionEvaluator);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
package com.ai.da.common.security.filter;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.ai.da.common.config.exception.TokenMissingOrExpiredException;
|
|
||||||
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.common.utils.RequestInfoUtil;
|
|
||||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.util.StopWatch;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
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", "/swagger-ui.html",
|
|
||||||
"/swagger-resources", "/swagger-resources/", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security",
|
|
||||||
"/webjars/", "/v2/api-docs", "/v3/api-docs", "/v3/api-docs/swagger-config",
|
|
||||||
"/api/account/login", "/api/account/preLogin", "api/account/sendEmail","api/account/noLoginRequired",
|
|
||||||
"/api/account/resetPwd",
|
|
||||||
"/api/python/saveGeneratePicture", "/api/python/getLibraryByUserId",
|
|
||||||
"/api/third/party/addUser","/api/third/party/addTrialUser", "/api/third/party/editUser", "/api/element/initDefaultSysFile",
|
|
||||||
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew","/api/third/party/updateNoLoginRequiredNew",
|
|
||||||
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
|
|
||||||
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
|
|
||||||
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
|
|
||||||
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify",
|
|
||||||
"/notification","/api/account/activateNewEmail","/api/third/party/auth/google_callback","/api/third/party/parseGoogleCredential","/api/third/party/receiveDesignResults","/api/third/party/parseWeChatCode","/api/third/party/receiveDesignParams"
|
|
||||||
, "/api/account/schoolLogin", "/api/account/enterpriseLogin", "/api/account/organizationNameSearch",
|
|
||||||
"/api/llm/stream"
|
|
||||||
);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) throws ServletException, IOException {
|
|
||||||
String requestURI = httpServletRequest.getRequestURI();
|
|
||||||
|
|
||||||
if (calculateUrl(requestURI)/* || hasAuthorizationToken(httpServletRequest)*/) {
|
|
||||||
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);
|
|
||||||
// excel导出使用原始response,不对响应做包装
|
|
||||||
if (requestURI.equals("/api/account/exportAccountsToExcel")) {
|
|
||||||
filterChain.doFilter(httpServletRequest, httpServletResponse); // 不包装
|
|
||||||
} else {
|
|
||||||
filterChain.doFilter(wrappedRequest, wrappedResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
SecurityContextHolder.clearContext();
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
stopWatch.stop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//先清空当前线程变量,防止上一个线程遗留
|
|
||||||
UserContext.delete();
|
|
||||||
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 boolean hasAuthorizationToken(HttpServletRequest request) {
|
|
||||||
String authorizationHeader = request.getHeader("Authorization");
|
|
||||||
return authorizationHeader != null && authorizationHeader.startsWith("Bearer");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void extracted(HttpServletRequest request) {
|
|
||||||
String jwtToken = request.getHeader(properties.getJwtTokenHeader());
|
|
||||||
// log.debug("后台检查令牌:{}", jwtToken);
|
|
||||||
|
|
||||||
if (StrUtil.isBlank(jwtToken)) {
|
|
||||||
String ipAddress = RequestInfoUtil.getIpAddress(request);
|
|
||||||
log.info("本次请求的ip为 : " + ipAddress);
|
|
||||||
// throw new RuntimeException("请传入token!");
|
|
||||||
throw new TokenMissingOrExpiredException("请传入token!");
|
|
||||||
}
|
|
||||||
if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){
|
|
||||||
//写死 暂时放行
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 检查token
|
|
||||||
boolean validate = jwtTokenHelper.validateToken(jwtToken);
|
|
||||||
if (validate) {
|
|
||||||
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(jwtToken);
|
|
||||||
if (principal == null) {
|
|
||||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
|
||||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(token without userInfo)");
|
|
||||||
}
|
|
||||||
//先清空当前线程变量,防止上一个线程遗留
|
|
||||||
UserContext.delete();
|
|
||||||
//存取用户信息到缓存
|
|
||||||
UserContext.setUserHolder(principal);
|
|
||||||
//校验token
|
|
||||||
String cacheToken = LocalCacheUtils.getTokenCache(String.valueOf(principal.getId()));
|
|
||||||
|
|
||||||
if(StringUtils.isEmpty(cacheToken)){
|
|
||||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
|
||||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(local cache empty)");
|
|
||||||
}
|
|
||||||
if(!cacheToken.equals(jwtToken) ){
|
|
||||||
// throw new RuntimeException("TOKEN已过期,请重新登录!");
|
|
||||||
throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(token not match local cache)");
|
|
||||||
}
|
|
||||||
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(null, null);
|
|
||||||
// SecurityContextHolder.getContext().setAuthentication(authentication);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
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 jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
package com.ai.da.common.security.jwt;
|
|
||||||
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.crypto.digest.DigestUtil;
|
|
||||||
import com.ai.da.common.constant.CommonConstant;
|
|
||||||
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.security.Keys;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
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";
|
|
||||||
private static final String CHANGE_MAILBOX = "changeMailbox";
|
|
||||||
|
|
||||||
public String createToken(AuthPrincipalVo principal) {
|
|
||||||
SecretKey key = buildSigningKey();
|
|
||||||
String token = Jwts.builder()
|
|
||||||
.id(String.valueOf(principal.getId()))
|
|
||||||
.subject(JSONObject.toJSONString(principal))
|
|
||||||
.issuedAt(new Date())
|
|
||||||
.issuer(ISSUER)
|
|
||||||
.claim(AUTHORITIES, JSON.toJSONString(new ArrayList<>()))//自定义属性 权限
|
|
||||||
.expiration(new Date(System.currentTimeMillis() + securityProperties.getJwtExpiration()))
|
|
||||||
.signWith(key)
|
|
||||||
.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(), "");
|
|
||||||
SecretKey key = buildSigningKey();
|
|
||||||
return Jwts.parser()
|
|
||||||
.verifyWith(key)
|
|
||||||
.build()
|
|
||||||
.parseSignedClaims(token)
|
|
||||||
.getPayload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String createToken(Long userId, String userEmail){
|
|
||||||
SecretKey key = buildSigningKey();
|
|
||||||
String token = Jwts.builder()
|
|
||||||
.id(String.valueOf(userId))
|
|
||||||
.subject(userEmail + "_" + userId)
|
|
||||||
.issuedAt(new Date())
|
|
||||||
.issuer(ISSUER)
|
|
||||||
.claim(CHANGE_MAILBOX, JSON.toJSONString(new ArrayList<>()))//自定义属性 权限
|
|
||||||
.expiration(new Date(System.currentTimeMillis() + CommonConstant.CHANGE_MAILBOX_LINK_VALIDITY))
|
|
||||||
.signWith(key)
|
|
||||||
.compact();
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String parseToEmailAndId(String token) {
|
|
||||||
return parser(token).getSubject();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JWT 要求 HMAC-SHA 的密钥至少 256 bit,这里统一扩展/哈希密钥长度避免 WeakKeyException。
|
|
||||||
*/
|
|
||||||
private SecretKey buildSigningKey() {
|
|
||||||
byte[] raw = securityProperties.getJwtSecret().getBytes(StandardCharsets.UTF_8);
|
|
||||||
if (raw.length < 32) {
|
|
||||||
raw = DigestUtil.sha256(raw);
|
|
||||||
}
|
|
||||||
return Keys.hmacShaKeyFor(raw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ package com.ai.da.common.task;
|
|||||||
import com.ai.da.common.utils.RedisUtil;
|
import com.ai.da.common.utils.RedisUtil;
|
||||||
import com.ai.da.mapper.primary.entity.Account;
|
import com.ai.da.mapper.primary.entity.Account;
|
||||||
import com.ai.da.service.AccountService;
|
import com.ai.da.service.AccountService;
|
||||||
|
import com.ai.da.service.SubscriptionPlanService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -18,6 +19,8 @@ public class AccountTask {
|
|||||||
private AccountService accountService;
|
private AccountService accountService;
|
||||||
@Resource
|
@Resource
|
||||||
private RedisUtil redisUtil;
|
private RedisUtil redisUtil;
|
||||||
|
@Resource
|
||||||
|
private SubscriptionPlanService subscriptionPlanService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每周日晚上刷新 年付用户、月付用户的积分
|
* 每周日晚上刷新 年付用户、月付用户的积分
|
||||||
@@ -25,20 +28,20 @@ public class AccountTask {
|
|||||||
* 每个月月初只刷新教育子账号的积分
|
* 每个月月初只刷新教育子账号的积分
|
||||||
*/
|
*/
|
||||||
// @Scheduled(cron = "0 25 14 * * ?")
|
// @Scheduled(cron = "0 25 14 * * ?")
|
||||||
@Scheduled(cron = "0 0 0 1 * ?")
|
// @Scheduled(cron = "0 0 0 1 * ?")
|
||||||
public void refreshCreditsMonthly() {
|
public void refreshCreditsMonthly() {
|
||||||
log.info("每月1号0点 重置教育版子账号为默认积分");
|
log.info("每月1号0点 重置教育版子账号为默认积分");
|
||||||
accountService.refreshCreditsMonthly();
|
accountService.refreshCreditsMonthly();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||||
public void getPaidUser() {
|
public void getPaidUser() {
|
||||||
// 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单
|
// 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单
|
||||||
accountService.extendValidityForCC();
|
accountService.extendValidityForCC();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 每天凌晨0点执行一次
|
// 每天凌晨0点执行一次 目前已没有角色类型为4的用户
|
||||||
@Scheduled(cron = "0 0 0 * * ?")
|
/*@Scheduled(cron = "0 0 0 * * ?")
|
||||||
public void cancelActivityBenefits() {
|
public void cancelActivityBenefits() {
|
||||||
// 1、查询当前所有参与了活动且过期的用户
|
// 1、查询当前所有参与了活动且过期的用户
|
||||||
List<Account> accountList = accountService.getExpiredUserBySystemUser(4);
|
List<Account> accountList = accountService.getExpiredUserBySystemUser(4);
|
||||||
@@ -48,10 +51,10 @@ public class AccountTask {
|
|||||||
log.info("参与活动的用户{} : {} 于 {} 账号有效期到期,置为游客", account.getId(), account.getUserEmail(), account.getValidEndTime());
|
log.info("参与活动的用户{} : {} 于 {} 账号有效期到期,置为游客", account.getId(), account.getUserEmail(), account.getValidEndTime());
|
||||||
accountService.toVisitor(account);
|
accountService.toVisitor(account);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// 每天检测正式用户到期情况,每天凌晨0点执行
|
// 每天检测正式用户到期情况,每天凌晨0点执行
|
||||||
@Scheduled(cron = "0 0 0 * * ?")
|
// @Scheduled(cron = "0 0 0 * * ?")
|
||||||
public void paidUserToVisitor() {
|
public void paidUserToVisitor() {
|
||||||
// 1、查询当前已过期正式用户或试用用户
|
// 1、查询当前已过期正式用户或试用用户
|
||||||
List<Account> accountList = accountService.getExpiredUserBySystemUser(1);
|
List<Account> accountList = accountService.getExpiredUserBySystemUser(1);
|
||||||
@@ -74,7 +77,7 @@ public class AccountTask {
|
|||||||
accountService.registerUserToVisitor();
|
accountService.registerUserToVisitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 0 1 * ?")
|
// @Scheduled(cron = "0 0 0 1 * ?")
|
||||||
// 每月初刷新所有用户用户名剩余修改次数
|
// 每月初刷新所有用户用户名剩余修改次数
|
||||||
public void resetUsernameModifyTimes(){
|
public void resetUsernameModifyTimes(){
|
||||||
log.info("重置所有用户的用户名修改次数");
|
log.info("重置所有用户的用户名修改次数");
|
||||||
@@ -82,8 +85,18 @@ public class AccountTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @Scheduled(cron = "0 35 14 * * ?")
|
// @Scheduled(cron = "0 35 14 * * ?")
|
||||||
@Scheduled(cron = "0 5 0 * * ?")
|
// @Scheduled(cron = "0 5 0 * * ?")
|
||||||
public void checkEduAdminExpireStatus() {
|
public void checkEduAdminExpireStatus() {
|
||||||
accountService.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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class GenerateTask {
|
|||||||
* 故这里通过定时任务做补偿
|
* 故这里通过定时任务做补偿
|
||||||
* flux五分钟查询一次,万相1小时查询一次
|
* flux五分钟查询一次,万相1小时查询一次
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 */4 * * * ?")
|
// @Scheduled(cron = "0 */4 * * * ?")
|
||||||
public void fluxCompensationMechanism(){
|
public void fluxCompensationMechanism(){
|
||||||
// 1、查所有 任务还没成功、还没失败,正在等待或者执行中的任务id有哪些
|
// 1、查所有 任务还没成功、还没失败,正在等待或者执行中的任务id有哪些
|
||||||
// (由于获取结果的polling_url在redis中只存一天,大部分结果超过一天之后就无法再找到任务,小部分可以通过公共路径查到结果)
|
// (由于获取结果的polling_url在redis中只存一天,大部分结果超过一天之后就无法再找到任务,小部分可以通过公共路径查到结果)
|
||||||
@@ -98,7 +98,7 @@ public class GenerateTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 万相 -> pose transformation 补偿 当前任务执行完后,5分钟再执行一次(不会出现任务重叠的情况)
|
// 万相 -> pose transformation 补偿 当前任务执行完后,5分钟再执行一次(不会出现任务重叠的情况)
|
||||||
@Scheduled(fixedDelay = 5 * 60 * 1000)
|
// @Scheduled(fixedDelay = 5 * 60 * 1000)
|
||||||
public void wxCompensationMechanism(){
|
public void wxCompensationMechanism(){
|
||||||
List<APIGenerate> apiGenerates = apiGenerateService.getPendingTaskByStatus("wx");
|
List<APIGenerate> apiGenerates = apiGenerateService.getPendingTaskByStatus("wx");
|
||||||
if (apiGenerates != null && !apiGenerates.isEmpty()){
|
if (apiGenerates != null && !apiGenerates.isEmpty()){
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class PaymentTask {
|
|||||||
@Resource
|
@Resource
|
||||||
private PayPalCheckoutService payPalCheckoutService;
|
private PayPalCheckoutService payPalCheckoutService;
|
||||||
|
|
||||||
// @Scheduled(cron = "0/30 * * * * ?")
|
// @Scheduled(cron = "0/30 * * * * ?")
|
||||||
public void orderConfirmForPaypal() throws SerializeException {
|
public void orderConfirmForPaypal() throws SerializeException {
|
||||||
|
|
||||||
// log.info("PayPal orderConfirm 被执行......");
|
// log.info("PayPal orderConfirm 被执行......");
|
||||||
@@ -97,19 +97,19 @@ public class PaymentTask {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||||
public void updateAffiliateInfoWithPayment(){
|
public void updateAffiliateInfoWithPayment(){
|
||||||
// log.info("佣金计算定时器");
|
// log.info("佣金计算定时器");
|
||||||
affiliateService.updateAffiliateInfoWithPayment();
|
affiliateService.updateAffiliateInfoWithPayment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定时同步(每分钟一次)
|
// 定时同步(每分钟一次)
|
||||||
@Scheduled(fixedRate = 60000)
|
// @Scheduled(fixedRate = 60000)
|
||||||
public void syncLinkViewCountToDB(){
|
public void syncLinkViewCountToDB(){
|
||||||
affiliateService.syncLinkViewCountToDB();
|
affiliateService.syncLinkViewCountToDB();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Scheduled(cron = "0 0 8 28-31 * ?")
|
// @Scheduled(cron = "0 0 8 28-31 * ?")
|
||||||
public void commissionSummaryReminder(){
|
public void commissionSummaryReminder(){
|
||||||
// 每个月末的最后一天的早上八点执行
|
// 每个月末的最后一天的早上八点执行
|
||||||
LocalDate today = LocalDate.now();
|
LocalDate today = LocalDate.now();
|
||||||
@@ -120,7 +120,7 @@ public class PaymentTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
|
||||||
public void calcCouponsCommission(){
|
public void calcCouponsCommission(){
|
||||||
// log.info("优惠券佣金计算定时器");
|
// log.info("优惠券佣金计算定时器");
|
||||||
affiliateService.calcCouponsCommission();
|
affiliateService.calcCouponsCommission();
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class SubscriptionReminderTask {
|
|||||||
REMINDER_DAYS_CONFIG.put("year", 14);
|
REMINDER_DAYS_CONFIG.put("year", 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 9 * * ?")
|
// @Scheduled(cron = "0 0 9 * * ?")
|
||||||
public void subscriptionReminder() {
|
public void subscriptionReminder() {
|
||||||
// 获取所有需要通知的订阅
|
// 获取所有需要通知的订阅
|
||||||
List<SubscriptionInfo> subscriptionInfos = getDueSubscriptions();
|
List<SubscriptionInfo> subscriptionInfos = getDueSubscriptions();
|
||||||
@@ -97,7 +97,7 @@ public class SubscriptionReminderTask {
|
|||||||
return subscriptionInfoMapper.selectList(qw);
|
return subscriptionInfoMapper.selectList(qw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 9 * * ?")
|
// @Scheduled(cron = "0 0 9 * * ?")
|
||||||
public void trialReminder() {
|
public void trialReminder() {
|
||||||
// 今天的 00:00:00 和 23:59:59
|
// 今天的 00:00:00 和 23:59:59
|
||||||
LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay();
|
LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay();
|
||||||
|
|||||||
@@ -1,178 +1,171 @@
|
|||||||
package com.ai.da.common.utils;
|
package com.ai.da.common.utils;
|
||||||
|
|
||||||
import com.ai.da.common.constant.CommonConstant;
|
import com.ai.da.common.constant.CommonConstant;
|
||||||
import com.ai.da.model.dto.BasicEmailParamDTO;
|
import com.ai.da.model.dto.BasicEmailParamDTO;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.sun.mail.smtp.SMTPTransport;
|
import io.netty.util.internal.StringUtil;
|
||||||
import io.netty.util.internal.StringUtil;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.core.io.InputStreamSource;
|
||||||
import org.springframework.core.io.InputStreamSource;
|
import org.springframework.mail.MailException;
|
||||||
import org.springframework.mail.MailException;
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.stereotype.Component;
|
import org.thymeleaf.TemplateEngine;
|
||||||
import org.thymeleaf.TemplateEngine;
|
import org.thymeleaf.context.Context;
|
||||||
import org.thymeleaf.context.Context;
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.mail.MessagingException;
|
||||||
import jakarta.mail.MessagingException;
|
import jakarta.mail.internet.*;
|
||||||
import jakarta.mail.internet.*;
|
import java.util.List;
|
||||||
import java.util.List;
|
import java.util.Objects;
|
||||||
import java.util.Objects;
|
|
||||||
|
@Slf4j
|
||||||
@Slf4j
|
@Component
|
||||||
@Component
|
public class MailUtil {
|
||||||
public class MailUtil {
|
|
||||||
|
@Resource
|
||||||
@Resource
|
private JavaMailSender javaMailSender;
|
||||||
private JavaMailSender javaMailSender;
|
|
||||||
|
@Resource
|
||||||
@Resource
|
private TemplateEngine templateEngine;
|
||||||
private TemplateEngine templateEngine;
|
|
||||||
|
/**
|
||||||
/**
|
* 发送邮件 - 默认发件人
|
||||||
* 发送邮件 - 默认发件人
|
*
|
||||||
*
|
* @param basicEmailParamDTO 发送邮件所需参数
|
||||||
* @param basicEmailParamDTO 发送邮件所需参数
|
* @param fileName 附件名(如果有)
|
||||||
* @param inputStreamSource 附件(如果有)
|
* @param inputStreamSource 附件(如果有)
|
||||||
*/
|
*/
|
||||||
public int sendMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
|
public int sendMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
|
||||||
MimeMessage mimeMessage = createSimpleMail(basicEmailParamDTO, fileName, inputStreamSource);
|
MimeMessage mimeMessage = createSimpleMail(basicEmailParamDTO, fileName, inputStreamSource);
|
||||||
// 提取配置
|
// 提取配置
|
||||||
String host;
|
String host;
|
||||||
String username;
|
String username;
|
||||||
String password;
|
String password;
|
||||||
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
|
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
|
||||||
host = ((JavaMailSenderImpl) javaMailSender).getHost();
|
host = ((JavaMailSenderImpl) javaMailSender).getHost();
|
||||||
} else {
|
} else {
|
||||||
host = basicEmailParamDTO.getServiceAddress();
|
host = basicEmailParamDTO.getServiceAddress();
|
||||||
}
|
}
|
||||||
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getSenderUser())) {
|
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getSenderUser())) {
|
||||||
username = ((JavaMailSenderImpl) javaMailSender).getUsername();
|
username = ((JavaMailSenderImpl) javaMailSender).getUsername();
|
||||||
} else {
|
} else {
|
||||||
username = basicEmailParamDTO.getSenderUser();
|
username = basicEmailParamDTO.getSenderUser();
|
||||||
}
|
}
|
||||||
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
|
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
|
||||||
password = ((JavaMailSenderImpl) javaMailSender).getPassword();
|
password = ((JavaMailSenderImpl) javaMailSender).getPassword();
|
||||||
} else {
|
} else {
|
||||||
password = basicEmailParamDTO.getPassword();
|
password = basicEmailParamDTO.getPassword();
|
||||||
}
|
}
|
||||||
return sendMail(mimeMessage, host, username, password);
|
return sendMail(mimeMessage, host, username, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sendMail(MimeMessage mimeMessage, String host, String username, String password) throws MessagingException {
|
private int sendMail(MimeMessage mimeMessage, String host, String username, String password) throws MessagingException {
|
||||||
SMTPTransport transport = null;
|
try {
|
||||||
try {
|
// 配置连接属性
|
||||||
// 获取 SMTPTransport
|
java.util.Properties props = mimeMessage.getSession().getProperties();
|
||||||
transport = (SMTPTransport) mimeMessage.getSession().getTransport("smtp");
|
props.put("mail.smtp.auth", "true");
|
||||||
// 连接到 SMTP 服务器
|
props.put("mail.smtp.host", host);
|
||||||
transport.connect(host, username, password);
|
props.put("mail.user", username);
|
||||||
// 发送邮件
|
props.put("mail.password", password);
|
||||||
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
|
|
||||||
// 获取 SMTP 服务器的响应
|
// 使用 JavaMailSender 发送邮件(Spring Boot 3.x 标准方式)
|
||||||
String lastServerResponse = transport.getLastServerResponse();
|
javaMailSender.send(mimeMessage);
|
||||||
int lastReturnCode = transport.getLastReturnCode();
|
log.info("邮件发送成功至: {}", host);
|
||||||
|
return 1;
|
||||||
log.info("SMTP 状态码: {}, SMTP 服务器响应: {}", lastReturnCode, lastServerResponse);
|
} catch (MailException e) {
|
||||||
return lastReturnCode;
|
log.info("邮件发送失败:{}", e.getMessage());
|
||||||
} catch (MailException | MessagingException e) {
|
return 0;
|
||||||
// 记录日志或执行其他补偿逻辑
|
}
|
||||||
log.info("邮件发送失败:{}", e.getMessage());
|
}
|
||||||
} finally {
|
|
||||||
// 关闭连接
|
/**
|
||||||
assert transport != null;
|
* 创建一封邮件
|
||||||
transport.close();
|
*
|
||||||
}
|
* @param basicEmailParamDTO 创建邮件需要的参数
|
||||||
return 0;
|
* @param inputStreamSource 附件(如果有)
|
||||||
}
|
* @return 一封邮件
|
||||||
|
*/
|
||||||
/**
|
private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
|
||||||
* 创建一封邮件
|
// 创建邮件对象
|
||||||
*
|
MimeMessage message = javaMailSender.createMimeMessage();
|
||||||
* @param basicEmailParamDTO 创建邮件需要的参数
|
// 使用 MimeMessageHelper 简化邮件内容和附件的设置
|
||||||
* @param inputStreamSource 附件(如果有)
|
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
|
||||||
* @return 一封邮件
|
// 设置发件人
|
||||||
*/
|
mimeMessageHelper.setFrom(new InternetAddress(basicEmailParamDTO.getSenderUserMail()));
|
||||||
private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
|
// 设置收件人
|
||||||
// 创建邮件对象
|
mimeMessageHelper.setTo(basicEmailParamDTO.getMailTo());
|
||||||
MimeMessage message = javaMailSender.createMimeMessage();
|
// 设置抄送人
|
||||||
// 使用 MimeMessageHelper 简化邮件内容和附件的设置
|
if (basicEmailParamDTO.getCc() != null && basicEmailParamDTO.getCc().length > 0) {
|
||||||
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
|
mimeMessageHelper.setCc(basicEmailParamDTO.getCc());
|
||||||
// 设置发件人
|
}
|
||||||
mimeMessageHelper.setFrom(new InternetAddress(basicEmailParamDTO.getSenderUserMail()));
|
// 设置暗送人
|
||||||
// 设置收件人
|
if (basicEmailParamDTO.getBcc() != null && basicEmailParamDTO.getBcc().length > 0) {
|
||||||
mimeMessageHelper.setTo(basicEmailParamDTO.getMailTo());
|
mimeMessageHelper.setBcc(basicEmailParamDTO.getBcc());
|
||||||
// 设置抄送人
|
}
|
||||||
if (basicEmailParamDTO.getCc() != null && basicEmailParamDTO.getCc().length > 0) {
|
// 设置邮件主题
|
||||||
mimeMessageHelper.setCc(basicEmailParamDTO.getCc());
|
mimeMessageHelper.setSubject(basicEmailParamDTO.getSubject());
|
||||||
}
|
// 设置邮件内容(HTML 格式)
|
||||||
// 设置暗送人
|
mimeMessageHelper.setText(basicEmailParamDTO.getContent(), true);
|
||||||
if (basicEmailParamDTO.getBcc() != null && basicEmailParamDTO.getBcc().length > 0) {
|
// 设置附件
|
||||||
mimeMessageHelper.setBcc(basicEmailParamDTO.getBcc());
|
if (inputStreamSource != null) {
|
||||||
}
|
mimeMessageHelper.addAttachment(fileName, inputStreamSource);
|
||||||
// 设置邮件主题
|
}
|
||||||
mimeMessageHelper.setSubject(basicEmailParamDTO.getSubject());
|
return message;
|
||||||
// 设置邮件内容(HTML 格式)
|
}
|
||||||
mimeMessageHelper.setText(basicEmailParamDTO.getContent(), true);
|
|
||||||
// 设置附件
|
|
||||||
if (inputStreamSource != null) {
|
/**
|
||||||
mimeMessageHelper.addAttachment(fileName, inputStreamSource);
|
* 设置实体参数
|
||||||
}
|
*
|
||||||
return message;
|
* @param mailTo 接收邮件的邮箱地址
|
||||||
}
|
* @param jsonObject 模板中变量的值
|
||||||
|
* @return 返回一个MailEntity
|
||||||
|
* @throws AddressException 邮箱地址值异常
|
||||||
/**
|
*/
|
||||||
* 设置实体参数
|
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, JSONObject jsonObject, String templatePath, String title) throws AddressException {
|
||||||
*
|
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
|
||||||
* @param mailTo 接收邮件的邮箱地址
|
// basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
|
||||||
* @param jsonObject 模板中变量的值
|
basicEmailParamDTO.setSenderUserMail(CommonConstant.senderEmail);
|
||||||
* @return 返回一个MailEntity
|
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
|
||||||
* @throws AddressException 邮箱地址值异常
|
basicEmailParamDTO.setSubject(title);
|
||||||
*/
|
// todo 邮件模板不存在的报错与重试机制
|
||||||
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, JSONObject jsonObject, String templatePath, String title) throws AddressException {
|
basicEmailParamDTO.setContent(setContent(jsonObject, templatePath));
|
||||||
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
|
return basicEmailParamDTO;
|
||||||
// basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
|
}
|
||||||
basicEmailParamDTO.setSenderUserMail(CommonConstant.senderEmail);
|
|
||||||
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
|
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, String title) throws AddressException {
|
||||||
basicEmailParamDTO.setSubject(title);
|
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
|
||||||
// todo 邮件模板不存在的报错与重试机制
|
basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
|
||||||
basicEmailParamDTO.setContent(setContent(jsonObject, templatePath));
|
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
|
||||||
return basicEmailParamDTO;
|
basicEmailParamDTO.setSubject(title);
|
||||||
}
|
return basicEmailParamDTO;
|
||||||
|
}
|
||||||
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, String title) throws AddressException {
|
|
||||||
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
|
/**
|
||||||
basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
|
* 将地址转换为InternetAddress类型
|
||||||
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
|
*
|
||||||
basicEmailParamDTO.setSubject(title);
|
* @param addressList 普通的地址字符串列表
|
||||||
return basicEmailParamDTO;
|
* @return InternetAddress类型的地址列表
|
||||||
}
|
* @throws AddressException 地址异常
|
||||||
|
*/
|
||||||
/**
|
public InternetAddress[] getInternetAddressList(List<String> addressList) throws AddressException {
|
||||||
* 将地址转换为InternetAddress类型
|
InternetAddress[] toAddress = new InternetAddress[addressList.size()];
|
||||||
*
|
for (String address : addressList) {
|
||||||
* @param addressList 普通的地址字符串列表
|
toAddress[addressList.indexOf(address)] = new InternetAddress(address);
|
||||||
* @return InternetAddress类型的地址列表
|
}
|
||||||
* @throws AddressException 地址异常
|
return toAddress;
|
||||||
*/
|
}
|
||||||
public InternetAddress[] getInternetAddressList(List<String> addressList) throws AddressException {
|
|
||||||
InternetAddress[] toAddress = new InternetAddress[addressList.size()];
|
public String setContent(JSONObject jsonObject, String templatePath) {
|
||||||
for (String address : addressList) {
|
Context context = new Context();
|
||||||
toAddress[addressList.indexOf(address)] = new InternetAddress(address);
|
if (Objects.nonNull(jsonObject)) {
|
||||||
}
|
for (String key : jsonObject.keySet()) {
|
||||||
return toAddress;
|
context.setVariable(key, jsonObject.get(key));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public String setContent(JSONObject jsonObject, String templatePath) {
|
return templateEngine.process(templatePath, context);
|
||||||
Context context = new Context();
|
}
|
||||||
if (Objects.nonNull(jsonObject)) {
|
|
||||||
for (String key : jsonObject.keySet()) {
|
}
|
||||||
context.setVariable(key, jsonObject.get(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return templateEngine.process(templatePath, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import io.netty.util.internal.StringUtil;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -41,6 +42,28 @@ public class MinioUtil {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private MinioClient minioClient;
|
private MinioClient minioClient;
|
||||||
|
|
||||||
|
@Value("${minio.endpoint}")
|
||||||
|
private String endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取MinIO客户端实例
|
||||||
|
*/
|
||||||
|
public MinioClient getMinioClient() {
|
||||||
|
return minioClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis缓存key前缀,用于Minio签名URL缓存
|
||||||
|
*/
|
||||||
|
private static final String REDIS_MINIO_URL_PREFIX = "minio:url:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名URL缓存过期时间(秒),默认1天
|
||||||
|
*/
|
||||||
|
private static final long URL_CACHE_EXPIRE_SECONDS = 24 * 60 * 60;
|
||||||
/**
|
/**
|
||||||
* description: 判断bucket是否存在,不存在则创建
|
* description: 判断bucket是否存在,不存在则创建
|
||||||
*
|
*
|
||||||
@@ -381,6 +404,11 @@ public class MinioUtil {
|
|||||||
* @return 文件的临时URL,如果出现异常则返回null
|
* @return 文件的临时URL,如果出现异常则返回null
|
||||||
*/
|
*/
|
||||||
public String getPreSignedUrl(String bucketName, String fileName, int expiry) {
|
public String getPreSignedUrl(String bucketName, String fileName, int expiry) {
|
||||||
|
String cacheKey = REDIS_MINIO_URL_PREFIX + bucketName + "/" + fileName;
|
||||||
|
Object cachedUrl = redisUtil.getFromString(cacheKey);
|
||||||
|
if (cachedUrl != null) {
|
||||||
|
return cachedUrl.toString();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String lowerName = fileName.toLowerCase();
|
String lowerName = fileName.toLowerCase();
|
||||||
@@ -408,8 +436,9 @@ public class MinioUtil {
|
|||||||
|
|
||||||
builder.extraQueryParams(queryParams);
|
builder.extraQueryParams(queryParams);
|
||||||
}
|
}
|
||||||
|
String presignedObjectUrl = minioClient.getPresignedObjectUrl(builder.build());
|
||||||
return minioClient.getPresignedObjectUrl(builder.build());
|
redisUtil.addToString(cacheKey, presignedObjectUrl, URL_CACHE_EXPIRE_SECONDS);
|
||||||
|
return presignedObjectUrl;
|
||||||
} catch (MinioException | InvalidKeyException
|
} catch (MinioException | InvalidKeyException
|
||||||
| IOException | NoSuchAlgorithmException | IllegalArgumentException e) {
|
| IOException | NoSuchAlgorithmException | IllegalArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -951,6 +980,166 @@ public class MinioUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测字符串是否为预签名URL
|
||||||
|
* 通过检查URL中是否包含minio endpoint来判断
|
||||||
|
*
|
||||||
|
* @param str 待检测的字符串
|
||||||
|
* @return true表示是预签名URL,false表示不是
|
||||||
|
*/
|
||||||
|
public boolean isPresignedUrl(String str) {
|
||||||
|
if (str == null || str.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 检查字符串是否是一个有效的URL
|
||||||
|
URL url = new URL(str);
|
||||||
|
String host = url.getHost();
|
||||||
|
// 获取endpoint中的主机部分(去掉http://或https://)
|
||||||
|
String endpointHost = endpoint;
|
||||||
|
if (endpointHost.startsWith("http://")) {
|
||||||
|
endpointHost = endpointHost.substring(7);
|
||||||
|
} else if (endpointHost.startsWith("https://")) {
|
||||||
|
endpointHost = endpointHost.substring(8);
|
||||||
|
}
|
||||||
|
// 去掉端口号
|
||||||
|
if (endpointHost.contains(":")) {
|
||||||
|
endpointHost = endpointHost.substring(0, endpointHost.indexOf(":"));
|
||||||
|
}
|
||||||
|
// 检查URL的host是否与endpoint的host匹配
|
||||||
|
return host.equals(endpointHost);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 不是有效的URL
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测字符串是否为MinIO逻辑路径(bucketName/objectName格式)
|
||||||
|
* 逻辑路径特点:
|
||||||
|
* 1. 包含 "/"(桶名和对象名之间的分隔符)
|
||||||
|
* 2. 不是完整的URL(不以http://或https://开头)
|
||||||
|
* 3. 路径中没有查询参数
|
||||||
|
*
|
||||||
|
* @param str 待检测的字符串
|
||||||
|
* @return true表示是MinIO逻辑路径,false表示不是
|
||||||
|
*/
|
||||||
|
public boolean isMinioLogicalPath(String str) {
|
||||||
|
if (str == null || str.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 必须是字符串
|
||||||
|
if (!(str instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String trimStr = str.trim();
|
||||||
|
// 不应该以http://或https://开头
|
||||||
|
if (trimStr.startsWith("http://") || trimStr.startsWith("https://")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 应该包含 "/"(bucket/object格式)
|
||||||
|
if (!trimStr.contains("/")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 不应该包含空格或特殊字符
|
||||||
|
if (trimStr.contains(" ") || trimStr.contains("\n") || trimStr.contains("\t")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将预签名URL转换为逻辑路径
|
||||||
|
*
|
||||||
|
* @param presignedUrl 预签名URL
|
||||||
|
* @return 逻辑路径(格式:bucketName/objectName)
|
||||||
|
*/
|
||||||
|
public String getLogicalPathFromPresignedUrl(String presignedUrl) {
|
||||||
|
try {
|
||||||
|
// 解析URL
|
||||||
|
URL url = new URL(presignedUrl);
|
||||||
|
|
||||||
|
// 获取路径部分(去掉开头的/)
|
||||||
|
String path = url.getPath();
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路径格式为 bucketName/objectName
|
||||||
|
// Minio路径中可能包含多个/,需要正确分割
|
||||||
|
int firstSlashIndex = path.indexOf("/");
|
||||||
|
if (firstSlashIndex <= 0) {
|
||||||
|
throw new MinioException("预签名URL路径格式无效,应包含桶名和对象名: " + presignedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
String bucketName = path.substring(0, firstSlashIndex);
|
||||||
|
String objectName = path.substring(firstSlashIndex + 1);
|
||||||
|
|
||||||
|
// log.info("预签名URL转换成功,桶名: {}, 对象名: {}", bucketName, objectName);
|
||||||
|
return bucketName + "/" + objectName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("预签名URL解析失败: {}", e.getMessage(), e);
|
||||||
|
throw new BusinessException("system.error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理MinIO资源(预签名URL或逻辑路径),统一生成预签名URL
|
||||||
|
*
|
||||||
|
* @param resource 预签名URL或逻辑路径
|
||||||
|
* @param expires 过期时间(秒)
|
||||||
|
* @return 新的预签名URL
|
||||||
|
*/
|
||||||
|
public String processMinioResource(String resource, int expires) {
|
||||||
|
try {
|
||||||
|
String logicalPath;
|
||||||
|
if (isPresignedUrl(resource)) {
|
||||||
|
// 是预签名URL,解析为逻辑路径
|
||||||
|
logicalPath = getLogicalPathFromPresignedUrl(resource);
|
||||||
|
} else if (isMinioLogicalPath(resource)) {
|
||||||
|
// 本身就是逻辑路径
|
||||||
|
logicalPath = resource.trim();
|
||||||
|
} else {
|
||||||
|
// 不认识的内容,直接返回原始值
|
||||||
|
log.warn("未识别的MinIO资源格式: {}", resource);
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一生成预签名URL
|
||||||
|
return getPreSignedUrl(logicalPath, expires);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理MinIO资源失败: {}, error: {}", resource, e.getMessage(), e);
|
||||||
|
// 如果失败,返回原始内容
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将任意MinIO URL转换为逻辑路径
|
||||||
|
* 检测URL类型并转换为逻辑路径返回
|
||||||
|
*
|
||||||
|
* @param url 预签名URL或逻辑路径
|
||||||
|
* @return 逻辑路径(格式:bucketName/objectName)
|
||||||
|
* @throws MinioException 如果不是有效的MinIO资源
|
||||||
|
*/
|
||||||
|
public String convertToLogicalPath(String url) {
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
throw new BusinessException("url.cannot.be.empty");
|
||||||
|
}
|
||||||
|
if (isMinioLogicalPath(url)) {
|
||||||
|
// 本身就是逻辑路径,直接返回
|
||||||
|
return url.trim();
|
||||||
|
} else if (isPresignedUrl(url)) {
|
||||||
|
// 是预签名URL,转换为逻辑路径
|
||||||
|
return getLogicalPathFromPresignedUrl(url);
|
||||||
|
} else {
|
||||||
|
// 不认识的内容,抛出异常
|
||||||
|
throw new BusinessException("无法识别的MinIO资源格式: " + url + ",请提供有效的预签名URL或逻辑路径");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
|||||||
package com.ai.da.common.utils;
|
|
||||||
|
|
||||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
|
|
||||||
public class SecurityContextUtils {
|
|
||||||
|
|
||||||
public static AuthPrincipalVo getCurrentUser() {
|
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
if (authentication != null && authentication.getPrincipal() != null) {
|
|
||||||
return (AuthPrincipalVo) authentication.getPrincipal();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Long getCurrentUserId() {
|
|
||||||
AuthPrincipalVo currentUser = getCurrentUser();
|
|
||||||
if (currentUser != null) {
|
|
||||||
return currentUser.getId();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getCurrentUsername() {
|
|
||||||
AuthPrincipalVo currentUser = getCurrentUser();
|
|
||||||
if (currentUser != null) {
|
|
||||||
return currentUser.getUsername();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -883,8 +883,8 @@ public class SendEmailUtil {
|
|||||||
|
|
||||||
if (!type.equals("cancel") && !type.equals("fail_new")) {
|
if (!type.equals("cancel") && !type.equals("fail_new")) {
|
||||||
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
||||||
// SendEmailResponse respUser = client.SendEmail(user);
|
SendEmailResponse respUser = client.SendEmail(user);
|
||||||
log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), /*SendEmailResponse.toJsonString(respUser)*/null, receiverAddress);
|
log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), SendEmailResponse.toJsonString(respUser), receiverAddress);
|
||||||
}
|
}
|
||||||
if (!type.startsWith("reminder")) {
|
if (!type.startsWith("reminder")) {
|
||||||
SendEmailResponse respMerchant = client.SendEmail(merchant);
|
SendEmailResponse respMerchant = client.SendEmail(merchant);
|
||||||
@@ -1024,7 +1024,7 @@ public class SendEmailUtil {
|
|||||||
log.info("邮件发送结果res###{}", SendEmailResponse.toJsonString(resp));
|
log.info("邮件发送结果res###{}", SendEmailResponse.toJsonString(resp));
|
||||||
} catch (TencentCloudSDKException e) {
|
} catch (TencentCloudSDKException e) {
|
||||||
log.info("邮件发送失败###{}", e.toString());
|
log.info("邮件发送失败###{}", e.toString());
|
||||||
throw new BusinessException("failed.to.send.mail");
|
// throw new BusinessException("failed.to.send.mail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class SendRequestUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sendFluxPost(String url, String requestBodyStr){
|
/*public String sendFluxPost(String url, String requestBodyStr){
|
||||||
int status;
|
int status;
|
||||||
String body;
|
String body;
|
||||||
try (HttpResponse execute = HttpRequest.post(url)
|
try (HttpResponse execute = HttpRequest.post(url)
|
||||||
@@ -103,9 +103,63 @@ public class SendRequestUtil {
|
|||||||
if (status == 200) {
|
if (status == 200) {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
if (status == 402 || status == 403) {
|
||||||
|
SendEmailUtil.commonExceptionReminder("Flux账户积分不足,flux生成任务",
|
||||||
|
new String[]{"xupei3360@163.com, fangjianliao@aidlab.hk, investigation@aidlab.hk"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.warn("请求失败,状态码为 : {}", status);
|
log.warn("请求失败,状态码为 : {}", status);
|
||||||
return null;
|
return null;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public String sendFluxPost(String url, String requestBodyStr) {
|
||||||
|
// 尝试两个API key
|
||||||
|
String[] apiKeys = {"84e8f5d5-b0b3-49aa-b244-ab7ba27e7ae7",
|
||||||
|
"d447a0ac-2291-4f1c-9a36-f7614c385989"};
|
||||||
|
boolean[] notified = {false, false}; // 记录是否已发送过不足提醒
|
||||||
|
|
||||||
|
for (int i = 0; i < apiKeys.length; i++) {
|
||||||
|
int status;
|
||||||
|
String body;
|
||||||
|
|
||||||
|
try (HttpResponse execute = HttpRequest.post(url)
|
||||||
|
.header(Header.CONTENT_TYPE, "application/json")
|
||||||
|
.header("x-key", apiKeys[i])
|
||||||
|
.body(requestBodyStr)
|
||||||
|
.timeout(180000)
|
||||||
|
.execute()) {
|
||||||
|
|
||||||
|
status = execute.getStatus();
|
||||||
|
body = execute.body();
|
||||||
|
|
||||||
|
if (status == 200) {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额不足处理
|
||||||
|
if (status == 402 || status == 403) {
|
||||||
|
if (!notified[i]) {
|
||||||
|
SendEmailUtil.commonExceptionReminder(
|
||||||
|
"Flux账户积分不足,flux生成任务失败。(key:)" + apiKeys[i],
|
||||||
|
new String[]{"xupei3360@163.com", "fangjianliao@aidlab.hk", "investigation@aidlab.hk"}
|
||||||
|
);
|
||||||
|
notified[i] = true;
|
||||||
|
}
|
||||||
|
continue; // 尝试下一个key
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他错误直接返回null
|
||||||
|
log.warn("请求失败,状态码为:{},使用key:{}", status, apiKeys[i]);
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("请求异常,使用key:{}", apiKeys[i], e);
|
||||||
|
if (i == apiKeys.length - 1) return null; // 最后一个key也失败则返回null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn("所有API key均余额不足");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sendPost(String url, String requestBodyStr){
|
public String sendPost(String url, String requestBodyStr){
|
||||||
|
|||||||
131
src/main/java/com/ai/da/common/utils/TokenGenerateUtils.java
Normal file
131
src/main/java/com/ai/da/common/utils/TokenGenerateUtils.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package com.ai.da.common.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
|
import com.ai.da.common.constant.CommonConstant;
|
||||||
|
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token 生成工具类(仅负责生成,不负责鉴权)。
|
||||||
|
* 鉴权逻辑已迁移至 Gateway(GlobalAuthWebFilter)。
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class TokenGenerateUtils {
|
||||||
|
|
||||||
|
private static final String ISSUER = "DWJ";
|
||||||
|
|
||||||
|
@Value("${spring.security.jwtSecret:JWTSECRET}")
|
||||||
|
private String jwtSecret;
|
||||||
|
|
||||||
|
@Value("${spring.security.jwtExpiration:8640000000}")
|
||||||
|
private long jwtExpiration;
|
||||||
|
|
||||||
|
@Value("${spring.security.jwtTokenPrefix:Bearer-}")
|
||||||
|
private String jwtTokenPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 JWT Token。
|
||||||
|
* @param principal 用户信息
|
||||||
|
* @return 完整的 token(含 prefix)
|
||||||
|
*/
|
||||||
|
public String createToken(AuthPrincipalVo principal) {
|
||||||
|
SecretKey key = buildSigningKey();
|
||||||
|
String token = Jwts.builder()
|
||||||
|
.id(String.valueOf(principal.getId()))
|
||||||
|
.subject(JSONObject.toJSONString(principal))
|
||||||
|
.issuedAt(new Date())
|
||||||
|
.issuer(ISSUER)
|
||||||
|
.expiration(new Date(System.currentTimeMillis() + jwtExpiration))
|
||||||
|
.signWith(key)
|
||||||
|
.compact();
|
||||||
|
return jwtTokenPrefix + token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 Token 过期时间(毫秒)。
|
||||||
|
*/
|
||||||
|
public long getJwtExpiration() {
|
||||||
|
return jwtExpiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成用于邮箱变更的简化 Token。
|
||||||
|
* @param userId 用户 ID
|
||||||
|
* @param mailbox 新邮箱
|
||||||
|
* @return token(不含 prefix)
|
||||||
|
*/
|
||||||
|
public String createMailboxToken(Long userId, String mailbox) {
|
||||||
|
SecretKey key = buildSigningKey();
|
||||||
|
return Jwts.builder()
|
||||||
|
.id(String.valueOf(userId))
|
||||||
|
.subject(mailbox + "_" + userId)
|
||||||
|
.issuedAt(new Date())
|
||||||
|
.issuer(ISSUER)
|
||||||
|
.expiration(new Date(System.currentTimeMillis() + CommonConstant.CHANGE_MAILBOX_LINK_VALIDITY))
|
||||||
|
.signWith(key)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证 Token 是否有效(签名和有效期)。
|
||||||
|
*/
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
Claims claims = parseTokenBody(token);
|
||||||
|
return claims != null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 Token 中解析用户信息。
|
||||||
|
*/
|
||||||
|
public AuthPrincipalVo parserToUser(String token) {
|
||||||
|
try {
|
||||||
|
String subject = parseTokenBody(token).getSubject();
|
||||||
|
if (StrUtil.isNotEmpty(subject)) {
|
||||||
|
return JSONObject.parseObject(subject, AuthPrincipalVo.class);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("JWT解析用户信息失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析邮箱变更 Token,返回 "email_id" 格式字符串。
|
||||||
|
*/
|
||||||
|
public String parseMailboxToken(String token) {
|
||||||
|
return parseTokenBody(token).getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Claims parseTokenBody(String token) {
|
||||||
|
SecretKey key = buildSigningKey();
|
||||||
|
return Jwts.parser()
|
||||||
|
.verifyWith(key)
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(token)
|
||||||
|
.getPayload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecretKey buildSigningKey() {
|
||||||
|
byte[] raw = jwtSecret.getBytes(StandardCharsets.UTF_8);
|
||||||
|
if (raw.length < 32) {
|
||||||
|
raw = DigestUtil.sha256(raw);
|
||||||
|
}
|
||||||
|
return Keys.hmacShaKeyFor(raw);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,16 +15,16 @@ import com.ai.da.model.vo.PersonalHomepageVO;
|
|||||||
import com.ai.da.service.AccountService;
|
import com.ai.da.service.AccountService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -139,21 +139,21 @@ public class AccountController {
|
|||||||
@Operation(summary = "aws状态检测")
|
@Operation(summary = "aws状态检测")
|
||||||
@GetMapping("/healthy")
|
@GetMapping("/healthy")
|
||||||
@ResponseStatus(HttpStatus.OK)
|
@ResponseStatus(HttpStatus.OK)
|
||||||
public Response<Map<String,Integer>> checkStatus(){
|
public Response<Map<String, Integer>> checkStatus() {
|
||||||
Map<String,Integer> returnMap = new HashMap<>();
|
Map<String, Integer> returnMap = new HashMap<>();
|
||||||
returnMap.put("code",200);
|
returnMap.put("code", 200);
|
||||||
return Response.success(returnMap);
|
return Response.success(returnMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "查询账号到期时间")
|
@Operation(summary = "查询账号到期时间")
|
||||||
@PostMapping("/getExpiredTime")
|
@PostMapping("/getExpiredTime")
|
||||||
public Response<Long> getExpiredTime(){
|
public Response<Long> getExpiredTime() {
|
||||||
return Response.success(accountService.getExpiredTime());
|
return Response.success(accountService.getExpiredTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "免密登录")
|
@Operation(summary = "免密登录")
|
||||||
@PostMapping("/noLoginRequired")
|
@PostMapping("/noLoginRequired")
|
||||||
public Response<AccountLoginVO> noLoginRequired(@RequestBody NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request){
|
public Response<AccountLoginVO> noLoginRequired(@RequestBody NoLoginRequiredDTO noLoginRequiredDTO, HttpServletRequest request) {
|
||||||
return Response.success(accountService.noLoginRequired(noLoginRequiredDTO, request));
|
return Response.success(accountService.noLoginRequired(noLoginRequiredDTO, request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +191,7 @@ public class AccountController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 参与活动 获取福利
|
* 参与活动 获取福利
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
/* @Operation(summary = "参与活动 获取福利")
|
/* @Operation(summary = "参与活动 获取福利")
|
||||||
@@ -201,7 +202,7 @@ public class AccountController {
|
|||||||
|
|
||||||
@Operation(summary = "将用户账号过期时间设置为过期当天的23:59:59")
|
@Operation(summary = "将用户账号过期时间设置为过期当天的23:59:59")
|
||||||
@GetMapping("/setUserValidToDayEnd")
|
@GetMapping("/setUserValidToDayEnd")
|
||||||
public Response<List<Long>> setUserValidToDayEnd(){
|
public Response<List<Long>> setUserValidToDayEnd() {
|
||||||
return Response.success(accountService.setUserValidToDayEnd());
|
return Response.success(accountService.setUserValidToDayEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,19 +224,19 @@ public class AccountController {
|
|||||||
|
|
||||||
@Operation(summary = "获取个人主页信息")
|
@Operation(summary = "获取个人主页信息")
|
||||||
@GetMapping("/personalHomepage")
|
@GetMapping("/personalHomepage")
|
||||||
public Response<PersonalHomepageVO> getPersonalHomepage(@RequestParam("id") Long id){
|
public Response<PersonalHomepageVO> getPersonalHomepage(@RequestParam("id") Long id) {
|
||||||
return Response.success(accountService.getPersonalHomepage(id));
|
return Response.success(accountService.getPersonalHomepage(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "getUsernameModifyTimes")
|
@Operation(summary = "getUsernameModifyTimes")
|
||||||
@GetMapping("/getNicknameModifyTimes")
|
@GetMapping("/getNicknameModifyTimes")
|
||||||
public Response<Long> getNicknameModifyTimes(){
|
public Response<Long> getNicknameModifyTimes() {
|
||||||
return Response.success(accountService.getNicknameModifyTimes());
|
return Response.success(accountService.getNicknameModifyTimes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "editUserName")
|
@Operation(summary = "editUserName")
|
||||||
@GetMapping("/editUserName")
|
@GetMapping("/editUserName")
|
||||||
public Response<String> editUserName(@RequestParam("newUserName") String newUserName){
|
public Response<String> editUserName(@RequestParam("newUserName") String newUserName) {
|
||||||
accountService.editUserName(newUserName);
|
accountService.editUserName(newUserName);
|
||||||
return Response.success("success");
|
return Response.success("success");
|
||||||
}
|
}
|
||||||
@@ -289,7 +290,7 @@ public class AccountController {
|
|||||||
|
|
||||||
@PostMapping("organizationNameSearch")
|
@PostMapping("organizationNameSearch")
|
||||||
@Operation(summary = "组织名模糊查询")
|
@Operation(summary = "组织名模糊查询")
|
||||||
public Response<Set<String>> organizationNameSearch(@RequestParam("type") String type, @RequestParam("name") String name) {
|
public Response<Set<String>> organizationNameSearch(@RequestParam("type") String type, @RequestParam(value = "name", required = false) String name) {
|
||||||
return Response.success(accountService.organizationNameSearch(type, name));
|
return Response.success(accountService.organizationNameSearch(type, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class ConvenientInquiryController {
|
|||||||
@GetMapping("/recentNewUserChart")
|
@GetMapping("/recentNewUserChart")
|
||||||
public Response<Map<String, Object>> recentNewUserChart(@Parameter(description = "startTime") @RequestParam @Nullable String startTime,
|
public Response<Map<String, Object>> recentNewUserChart(@Parameter(description = "startTime") @RequestParam @Nullable String startTime,
|
||||||
@Parameter(description = "endTime") @RequestParam @Nullable String endTime,
|
@Parameter(description = "endTime") @RequestParam @Nullable String endTime,
|
||||||
@Parameter(description = "userType") @RequestParam Integer userType) {
|
@Parameter(description = "userType") @RequestParam @Nullable Integer userType) {
|
||||||
return Response.success(convenientInquiryService.recentNewUserChart(startTime, endTime, userType));
|
return Response.success(convenientInquiryService.recentNewUserChart(startTime, endTime, userType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +179,10 @@ public class ConvenientInquiryController {
|
|||||||
|
|
||||||
@Operation(summary = "获取所有用户id")
|
@Operation(summary = "获取所有用户id")
|
||||||
@GetMapping("/getAllUserId")
|
@GetMapping("/getAllUserId")
|
||||||
public Response<List<Map<String, Object>>> getAllUsrIdList() {
|
public Response<IPage<Map<String, Object>>> getAllUserIdList(@Parameter(description = "page") @RequestParam Integer page,
|
||||||
return Response.success(convenientInquiryService.getAllUserIdList());
|
@Parameter(description = "size") @RequestParam Integer size,
|
||||||
|
@Parameter(description = "email 模糊查询") @RequestParam(required = false) String email) {
|
||||||
|
return Response.success(convenientInquiryService.getAllUserIdList(page, size, email));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "获取所有交易信息")
|
@Operation(summary = "获取所有交易信息")
|
||||||
|
|||||||
203
src/main/java/com/ai/da/controller/GlobalAwardController.java
Normal file
203
src/main/java/com/ai/da/controller/GlobalAwardController.java
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
package com.ai.da.controller;
|
||||||
|
|
||||||
|
import com.ai.da.common.response.Response;
|
||||||
|
import com.ai.da.model.dto.*;
|
||||||
|
import com.ai.da.model.dto.ContestantDTO;
|
||||||
|
import com.ai.da.model.vo.CheckOTPVO;
|
||||||
|
import com.ai.da.model.vo.ContestantCountVO;
|
||||||
|
import com.ai.da.service.GlobalAwardService;
|
||||||
|
import com.ai.da.service.upload.UploadService;
|
||||||
|
import com.ai.da.service.upload.UploadTask;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import io.swagger.annotations.ApiParam;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/global-award")
|
||||||
|
@Api(tags = "全球奖项API", description = "全球奖项大赛管理和文件上传")
|
||||||
|
public class GlobalAwardController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private GlobalAwardService globalAwardService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UploadService uploadService;
|
||||||
|
|
||||||
|
// @PostMapping("/uploads/pdf")
|
||||||
|
// public Response<String> uploadPdf(@RequestParam("file") MultipartFile file,
|
||||||
|
// @RequestParam(value = "email", required = false) String email) throws Exception {
|
||||||
|
// return Response.success(globalAwardService.uploadPdf(file, email));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @PostMapping("/uploads/video")
|
||||||
|
// public Response<String> uploadVideo(@RequestParam("file") MultipartFile file,
|
||||||
|
// @RequestParam(value = "email", required = false) String email) throws Exception {
|
||||||
|
// return Response.success(globalAwardService.uploadVideo(file, email));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ===== 新增分片上传接口 =====
|
||||||
|
|
||||||
|
// ===== PDF分片上传接口 =====
|
||||||
|
|
||||||
|
/** 初始化PDF上传任务 */
|
||||||
|
@PostMapping("/uploads/pdf/init")
|
||||||
|
@ApiOperation(value = "初始化PDF上传", notes = "创建新的PDF上传任务并返回上传参数")
|
||||||
|
public Response<UploadInitResponse> initPdfUpload(@ApiParam(value = "PDF上传初始化请求", required = true) @RequestBody UploadInitRequest request) {
|
||||||
|
UploadTask uploadTask = uploadService.initPdfUpload(request);
|
||||||
|
return Response.success(UploadInitResponse.builder()
|
||||||
|
.uploadId(uploadTask.getUploadId())
|
||||||
|
.chunkSize(uploadTask.getChunkSize())
|
||||||
|
.totalChunks(uploadTask.getTotalChunks())
|
||||||
|
.expiresAt(uploadTask.getExpiresAt())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上传PDF分片 */
|
||||||
|
@PostMapping("/uploads/pdf/chunk")
|
||||||
|
@ApiOperation(value = "上传PDF分片", notes = "上传PDF文件的单个分片")
|
||||||
|
public Response<UploadChunkResponse> uploadPdfChunk(
|
||||||
|
@ApiParam(value = "PDF文件分片", required = true) @RequestParam("chunk") MultipartFile chunk,
|
||||||
|
@ApiParam(value = "上传任务ID", required = true) @RequestParam("uploadId") String uploadId,
|
||||||
|
@ApiParam(value = "分片索引(从0开始)", required = true) @RequestParam("chunkIndex") int chunkIndex,
|
||||||
|
@ApiParam(value = "分片总数", required = true) @RequestParam("totalChunks") int totalChunks) {
|
||||||
|
|
||||||
|
UploadChunkResponse uploadChunkResponse = uploadService.uploadPdfChunk(uploadId, chunk, chunkIndex, totalChunks);
|
||||||
|
return Response.success(uploadChunkResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 完成PDF上传 */
|
||||||
|
@PostMapping("/uploads/pdf/complete")
|
||||||
|
@ApiOperation(value = "完成PDF上传", notes = "完成PDF上传并合并所有分片")
|
||||||
|
public Response<UploadCompleteResponse> completePdfUpload(@ApiParam(value = "PDF上传完成请求", required = true) @RequestBody UploadCompleteRequest request) {
|
||||||
|
UploadCompleteResponse uploadCompleteResponse = uploadService.completePdfUpload(
|
||||||
|
request.getUploadId(),
|
||||||
|
request.getFileName(),
|
||||||
|
request.getTotalSize(),
|
||||||
|
request.getEmail(),
|
||||||
|
request.getSecureToken());
|
||||||
|
return Response.success(uploadCompleteResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询PDF上传状态 */
|
||||||
|
@GetMapping("/uploads/pdf/status/{uploadId}")
|
||||||
|
@ApiOperation(value = "查询PDF上传状态", notes = "获取PDF上传任务的当前状态")
|
||||||
|
public Response<UploadStatusResponse> getPdfUploadStatus(@ApiParam(value = "上传任务ID", required = true) @PathVariable String uploadId) {
|
||||||
|
UploadStatusResponse pdfUploadStatus = uploadService.getPdfUploadStatus(uploadId);
|
||||||
|
return Response.success(pdfUploadStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 视频分片上传接口 =====
|
||||||
|
|
||||||
|
/** 初始化视频上传任务 */
|
||||||
|
@PostMapping("/uploads/video/init")
|
||||||
|
@ApiOperation(value = "初始化视频上传", notes = "创建新的视频上传任务并返回上传参数")
|
||||||
|
public Response<UploadInitResponse> initVideoUpload(@ApiParam(value = "视频上传初始化请求", required = true) @RequestBody UploadInitRequest request) {
|
||||||
|
UploadTask uploadTask = uploadService.initVideoUpload(request);
|
||||||
|
return Response.success(UploadInitResponse.builder()
|
||||||
|
.uploadId(uploadTask.getUploadId())
|
||||||
|
.chunkSize(uploadTask.getChunkSize())
|
||||||
|
.totalChunks(uploadTask.getTotalChunks())
|
||||||
|
.expiresAt(uploadTask.getExpiresAt())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上传视频分片 */
|
||||||
|
@PostMapping("/uploads/video/chunk")
|
||||||
|
@ApiOperation(value = "上传视频分片", notes = "上传视频文件的单个分片")
|
||||||
|
public Response<UploadChunkResponse> uploadVideoChunk(
|
||||||
|
@ApiParam(value = "视频文件分片", required = true) @RequestParam("chunk") MultipartFile chunk,
|
||||||
|
@ApiParam(value = "上传任务ID", required = true) @RequestParam("uploadId") String uploadId,
|
||||||
|
@ApiParam(value = "分片索引(从0开始)", required = true) @RequestParam("chunkIndex") int chunkIndex,
|
||||||
|
@ApiParam(value = "分片总数", required = true) @RequestParam("totalChunks") int totalChunks) {
|
||||||
|
|
||||||
|
UploadChunkResponse uploadChunkResponse = uploadService.uploadVideoChunk(uploadId, chunk, chunkIndex, totalChunks);
|
||||||
|
return Response.success(uploadChunkResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 完成视频上传 */
|
||||||
|
@PostMapping("/uploads/video/complete")
|
||||||
|
@ApiOperation(value = "完成视频上传", notes = "完成视频上传并合并所有分片")
|
||||||
|
public Response<UploadCompleteResponse> completeVideoUpload(@ApiParam(value = "视频上传完成请求", required = true) @RequestBody UploadCompleteRequest request) {
|
||||||
|
UploadCompleteResponse uploadCompleteResponse = uploadService.completeVideoUpload(
|
||||||
|
request.getUploadId(),
|
||||||
|
request.getFileName(),
|
||||||
|
request.getTotalSize(),
|
||||||
|
request.getEmail(),
|
||||||
|
request.getSecureToken());
|
||||||
|
return Response.success(uploadCompleteResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询视频上传状态 */
|
||||||
|
@GetMapping("/uploads/video/status/{uploadId}")
|
||||||
|
@ApiOperation(value = "查询视频上传状态", notes = "获取视频上传任务的当前状态")
|
||||||
|
public Response<UploadStatusResponse> getVideoUploadStatus(@ApiParam(value = "上传任务ID", required = true) @PathVariable String uploadId) {
|
||||||
|
UploadStatusResponse videoUploadStatus = uploadService.getVideoUploadStatus(uploadId);
|
||||||
|
return Response.success(videoUploadStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/contestants/save")
|
||||||
|
@ApiOperation(value = "保存参赛者信息", notes = "保存或更新参赛者信息及已上传的文件")
|
||||||
|
public Response<Map<String,Object>> submit(@ApiParam(value = "参赛者信息", required = true) @RequestBody ContestantDTO request) {
|
||||||
|
return Response.success(globalAwardService.saveContestant(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/contestants/{id}")
|
||||||
|
@ApiOperation(value = "根据id查询参赛者", notes = "根据id获取参赛者信息")
|
||||||
|
public Response<ContestantDTO> getContestantByID(@ApiParam(value = "参赛者id", required = true) @PathVariable("id") String id) {
|
||||||
|
ContestantDTO dto = globalAwardService.getContestantByID(id);
|
||||||
|
return Response.success(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/checkEmail")
|
||||||
|
public Response<String> checkEmail(@RequestParam("email") String email) {
|
||||||
|
globalAwardService.checkEmail(email);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/checkCode")
|
||||||
|
public Response<CheckOTPVO> checkCode(@RequestParam("email") String email, @RequestParam("code") String code) {
|
||||||
|
return Response.success(globalAwardService.checkCode(email, code));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/contestants/export")
|
||||||
|
@ApiOperation(value = "导出参赛者列表为Excel", notes = "导出所有参赛者信息为xlsx并触发下载")
|
||||||
|
public void exportContestants(HttpServletResponse response) throws Exception {
|
||||||
|
byte[] data = globalAwardService.exportContestants();
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=\"contestants.xlsx\"");
|
||||||
|
response.setContentLength(data.length);
|
||||||
|
response.getOutputStream().write(data);
|
||||||
|
response.getOutputStream().flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/contestants/export/files")
|
||||||
|
@ApiOperation(value = "导出参赛者文件为ZIP", notes = "根据参赛者编号范围导出PDF、视频和信息文件为ZIP,直接响应给浏览器")
|
||||||
|
public void exportContestantFiles(@ApiParam(value = "参赛者文件导出请求", required = true) @RequestBody ContestantExportRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
byte[] zipData = globalAwardService.exportContestantFilesAsZip(request.getMinContestantNumber(), request.getMaxContestantNumber());
|
||||||
|
if (zipData.length == 0) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
response.getWriter().write("No contestants found in the specified range.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.setContentType("application/zip");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=\"contestants.zip\"");
|
||||||
|
response.setContentLength(zipData.length);
|
||||||
|
response.getOutputStream().write(zipData);
|
||||||
|
response.getOutputStream().flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/contestants/count")
|
||||||
|
@ApiOperation(value = "查询参赛者总数", notes = "查询数据库中参赛者的总数量和最大参赛者编号")
|
||||||
|
public Response<ContestantCountVO> getContestantCount() {
|
||||||
|
return Response.success(globalAwardService.getContestantCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -23,6 +23,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -119,4 +122,14 @@ public class PythonController {
|
|||||||
return Response.success(superResolutionService.prepareForSR(superResolutionDTO));
|
return Response.success(superResolutionService.prepareForSR(superResolutionDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CrossOrigin
|
||||||
|
@Operation(summary = "Seg Anything 转发接口")
|
||||||
|
@PostMapping("/segAnything")
|
||||||
|
public Response<String> segAnything(@RequestBody Map<String, Object> payload) {
|
||||||
|
// 将前端传来的 Map 转为 fastjson JSONObject 并转发给 python 服务
|
||||||
|
JSONObject requestJson = (JSONObject) JSON.toJSON(payload);
|
||||||
|
String url = pythonService.segAnything(requestJson);
|
||||||
|
return Response.success(url);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class StripeController {
|
|||||||
Long size = redisUtil.getSize(key_1);
|
Long size = redisUtil.getSize(key_1);
|
||||||
// 给我发送邮件
|
// 给我发送邮件
|
||||||
if (webhookReminderFlag.equals("1") && size == 3){
|
if (webhookReminderFlag.equals("1") && size == 3){
|
||||||
SendEmailUtil.commonExceptionReminder("Stripe Webhook 回调", new String[]{"xupei3360@163.com"});
|
SendEmailUtil.commonExceptionReminder("Stripe Webhook 回调处理出现异常", new String[]{"xupei3360@163.com"});
|
||||||
}
|
}
|
||||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package com.ai.da.controller;
|
||||||
|
|
||||||
|
import com.ai.da.common.response.Response;
|
||||||
|
import com.ai.da.common.task.SubscriptionReminderTask;
|
||||||
|
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
||||||
|
import com.ai.da.model.dto.SubscriptionPlanDTO;
|
||||||
|
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
|
||||||
|
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
|
||||||
|
import com.ai.da.model.vo.SubscriptionPlanVO;
|
||||||
|
import com.ai.da.service.SubscriptionPlanService;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Tag(name = "订阅计划模块")
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/subscription_plan")
|
||||||
|
public class SubscriptionPlanController {
|
||||||
|
|
||||||
|
private final SubscriptionPlanService subscriptionPlanService;
|
||||||
|
|
||||||
|
private final SubscriptionReminderTask subscriptionReminderTask;
|
||||||
|
|
||||||
|
@Operation(summary = "创建订阅计划")
|
||||||
|
@PostMapping("/createPlan")
|
||||||
|
public Response<String> createPlan(@Valid @RequestBody SubscriptionPlanDTO subscriptionPlanDTO) {
|
||||||
|
subscriptionPlanService.createPlan(subscriptionPlanDTO);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "更新订阅计划")
|
||||||
|
@PostMapping("/updatePlan")
|
||||||
|
public Response<String> updatePlan(@Valid @RequestBody UpdateSubscriptionPlanDTO updateDTO) {
|
||||||
|
subscriptionPlanService.updatePlan(updateDTO);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "搜索订阅计划")
|
||||||
|
@PostMapping("/searchByOrganizationIdAndStatus")
|
||||||
|
public Response<List<SubscriptionPlan>> searchByOrganizationIdAndStatus(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||||
|
return Response.success(subscriptionPlanService.searchByOrganizationIdAndStatus(subscriptionPlanPageQuery));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "分页搜索订阅计划")
|
||||||
|
@PostMapping("/searchByPage")
|
||||||
|
public Response<IPage<SubscriptionPlanVO>> searchByPage(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||||
|
IPage<SubscriptionPlanVO> subscriptionPlanVOIPage = subscriptionPlanService.searchByPage(subscriptionPlanPageQuery);
|
||||||
|
return Response.success(subscriptionPlanVOIPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除订阅计划")
|
||||||
|
@GetMapping("/deletePlan")
|
||||||
|
public Response<String> deletePlan(@RequestParam Long id) {
|
||||||
|
subscriptionPlanService.deletePlan(id);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "管理员切换订阅计划")
|
||||||
|
@GetMapping("/switchSubscriptionPlan")
|
||||||
|
public Response<String> switchSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam(required = false) Long adminAccId) {
|
||||||
|
subscriptionPlanService.switchSubscriptionPlan(targetSubscriptionPlanId, adminAccId);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "子账号切换订阅计划")
|
||||||
|
@GetMapping("/switchSubAccSubscriptionPlan")
|
||||||
|
public Response<String> switchSubAccSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam Long subAccId) {
|
||||||
|
subscriptionPlanService.switchSubAccSubscriptionPlan(targetSubscriptionPlanId, subAccId);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Hidden
|
||||||
|
@Operation(summary = "activeSubscriptionPlan")
|
||||||
|
@GetMapping("/activeSubscriptionPlan")
|
||||||
|
public Response<String> activeSubscriptionPlan() {
|
||||||
|
subscriptionPlanService.activeSubscriptionPlan(null);
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Hidden
|
||||||
|
@Operation(summary = "expireSubscription")
|
||||||
|
@GetMapping("/expireSubscription")
|
||||||
|
public Response<String> expireSubscription() {
|
||||||
|
subscriptionPlanService.expireSubscription();
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "subscriptionReminder")
|
||||||
|
@GetMapping("/subscriptionReminder")
|
||||||
|
public Response<String> subscriptionReminder() {
|
||||||
|
subscriptionReminderTask.subscriptionReminder();
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "trialReminder")
|
||||||
|
@GetMapping("/trialReminder")
|
||||||
|
public Response<String> trialReminder() {
|
||||||
|
subscriptionReminderTask.trialReminder();
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.ai.da.feign.gateway;
|
||||||
|
|
||||||
|
import com.ai.da.common.response.Response;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用 Gateway 黑名单接口,将指定用户的 token 加入黑名单。
|
||||||
|
* 替代原来的 SellerFeignClient.clearTokenCache。
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "aida-gateway", path = "/internal")
|
||||||
|
public interface GatewayFeignClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将用户 token 加入黑名单。
|
||||||
|
* 后续 Gateway 会拒绝携带该用户 token 的请求。
|
||||||
|
*/
|
||||||
|
@PostMapping("/logout")
|
||||||
|
Response<Void> logout(@RequestParam("userId") Long userId);
|
||||||
|
}
|
||||||
20
src/main/java/com/ai/da/feign/seller/SellerFeignClient.java
Normal file
20
src/main/java/com/ai/da/feign/seller/SellerFeignClient.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package com.ai.da.feign.seller;
|
||||||
|
|
||||||
|
import com.ai.da.common.response.Response;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用 aida-seller 设计师相关接口的 Feign 客户端
|
||||||
|
*/
|
||||||
|
@FeignClient(name = "aida-seller", path = "/api/designer")
|
||||||
|
public interface SellerFeignClient {
|
||||||
|
|
||||||
|
@GetMapping("/check")
|
||||||
|
Response<Boolean> checkDesignerQualification(@RequestParam("userId") Long userId);
|
||||||
|
|
||||||
|
@PostMapping("/cache/clear")
|
||||||
|
Response<Void> clearTokenCache(@RequestParam("userId") Long userId);
|
||||||
|
}
|
||||||
12
src/main/java/com/ai/da/mapper/primary/ContestantMapper.java
Normal file
12
src/main/java/com/ai/da/mapper/primary/ContestantMapper.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package com.ai.da.mapper.primary;
|
||||||
|
|
||||||
|
import com.ai.da.mapper.primary.entity.Contestant;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ContestantMapper extends BaseMapper<Contestant> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ public interface DesignMapper extends CommonMapper<Design> {
|
|||||||
Long insertDesign(Design design);
|
Long insertDesign(Design design);
|
||||||
|
|
||||||
List<UserDesignStatisticDTO> getDesignStatistic(String startTime, String endTime, List<Long> ids, String email,
|
List<UserDesignStatisticDTO> getDesignStatistic(String startTime, String endTime, List<Long> ids, String email,
|
||||||
String role, String organizationName);
|
String role, String organizationName, boolean filterBySecond);
|
||||||
|
|
||||||
List<Design> selectDeleteList();
|
List<Design> selectDeleteList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
|||||||
import com.ai.da.mapper.primary.entity.Notification;
|
import com.ai.da.mapper.primary.entity.Notification;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -20,5 +21,5 @@ public interface NotificationMapper extends CommonMapper<Notification> {
|
|||||||
|
|
||||||
void setPersonalNotificationAllRead(String type, Long receiverId, LocalDateTime time);
|
void setPersonalNotificationAllRead(String type, Long receiverId, LocalDateTime time);
|
||||||
|
|
||||||
List<Long> getUnreadSysNotification(Long accountId);
|
List<Long> getUnreadSysNotification(Long accountId, Date createTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.ai.da.mapper.primary;
|
||||||
|
|
||||||
|
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
||||||
|
import com.ai.da.model.vo.SubscriptionPlanVO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
public interface SubscriptionPlanMapper extends BaseMapper<SubscriptionPlan> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联查询订阅计划信息(包含管理员邮箱)- 分页
|
||||||
|
*/
|
||||||
|
@Select("""
|
||||||
|
SELECT sp.*,
|
||||||
|
a.user_email AS adminAccEmail,
|
||||||
|
a.user_name AS adminAccName,
|
||||||
|
o.name AS organizationName
|
||||||
|
FROM t_subscription_plan sp
|
||||||
|
LEFT JOIN t_account a ON sp.admin_acc_id = a.id
|
||||||
|
LEFT JOIN t_organization o on sp.organization_id = o.id
|
||||||
|
${ew.customSqlSegment}
|
||||||
|
""")
|
||||||
|
Page<SubscriptionPlanVO> selectWithEmailPage(Page<SubscriptionPlanVO> page,
|
||||||
|
@Param(Constants.WRAPPER) Wrapper<?> wrapper);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.ai.da.mapper.primary;
|
||||||
|
|
||||||
|
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||||
|
import com.ai.da.mapper.primary.entity.UserPreference;
|
||||||
|
|
||||||
|
public interface UserPreferenceMapper extends CommonMapper<UserPreference> {
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ package com.ai.da.mapper.primary;
|
|||||||
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
import com.ai.da.common.config.mybatis.plus.CommonMapper;
|
||||||
import com.ai.da.mapper.primary.entity.WorkspaceRelStyle;
|
import com.ai.da.mapper.primary.entity.WorkspaceRelStyle;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper 接口
|
* Mapper 接口
|
||||||
*
|
*
|
||||||
@@ -11,5 +13,11 @@ import com.ai.da.mapper.primary.entity.WorkspaceRelStyle;
|
|||||||
*/
|
*/
|
||||||
public interface WorkspaceRelStyleMapper extends CommonMapper<WorkspaceRelStyle> {
|
public interface WorkspaceRelStyleMapper extends CommonMapper<WorkspaceRelStyle> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据projectId查询workspaceRelStyles
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @return workspaceRelStyles列表
|
||||||
|
*/
|
||||||
|
List<WorkspaceRelStyle> selectByProjectId(Long projectId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@TableName("t_api_generate")
|
@TableName("t_api_generate")
|
||||||
@ApiModel("调用第三方api的所有记录")
|
@Schema(description = "调用第三方api的所有记录")
|
||||||
public class APIGenerate extends BaseEntity{
|
public class APIGenerate extends BaseEntity{
|
||||||
// 用户id
|
// 用户id
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -76,13 +77,13 @@ public class Account implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date createDate;
|
private Date createDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date updateDate;
|
private Date updateDate;
|
||||||
|
|
||||||
private Integer isTrial;
|
private Integer isTrial;
|
||||||
@@ -132,12 +133,36 @@ public class Account implements Serializable {
|
|||||||
|
|
||||||
private String invitationCode;
|
private String invitationCode;
|
||||||
|
|
||||||
@ApiModelProperty("title")
|
@Schema(description = "title")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@ApiModelProperty("surname")
|
@Schema(description = "surname")
|
||||||
private String surname;
|
private String surname;
|
||||||
|
|
||||||
@ApiModelProperty("givenName")
|
@Schema(description = "givenName")
|
||||||
private String givenName;
|
private String givenName;
|
||||||
|
|
||||||
|
private Long subscriptionPlanId;
|
||||||
|
|
||||||
|
// 在类内部定义的枚举
|
||||||
|
@Getter
|
||||||
|
public enum SystemRole {
|
||||||
|
VISITOR("游客", 0),
|
||||||
|
YEARLY("年付用户", 1),
|
||||||
|
MONTHLY("月付用户", 2),
|
||||||
|
TRIAL("试用用户", 3),
|
||||||
|
EVENT_USER("参加活动获取30天有效期和6000个积分的用户", 4),
|
||||||
|
ENTERPRISE_ADMIN("企业管理员账号", 5),
|
||||||
|
ENTERPRISE_SUB("企业子账号", 6),
|
||||||
|
EDUCATION_ADMIN("学校管理员", 7),
|
||||||
|
EDUCATION_SUB("学校子账号", 8);
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
SystemRole(String desc, int code) {
|
||||||
|
this.desc = desc;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -27,16 +27,16 @@ public class Canvas implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty("ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty("url")
|
@Schema(description = "url")
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
@ApiModelProperty("accountId")
|
@Schema(description = "accountId")
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
|
|
||||||
@ApiModelProperty("createTime")
|
@Schema(description = "createTime")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -22,22 +22,22 @@ public class ChatMessage implements Serializable {
|
|||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty("项目ID")
|
@Schema(description = "项目ID")
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|
||||||
@ApiModelProperty("角色system/user")
|
@Schema(description = "角色system/user")
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
@ApiModelProperty("排序")
|
@Schema(description = "排序")
|
||||||
private Integer seq;
|
private Integer seq;
|
||||||
|
|
||||||
@ApiModelProperty("内容")
|
@Schema(description = "内容")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
@ApiModelProperty("用户ID")
|
@Schema(description = "用户ID")
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
|
|
||||||
@ApiModelProperty("0对话内容1颜色2图片")
|
@Schema(description = "0对话内容1颜色2图片")
|
||||||
private Integer isImage;
|
private Integer isImage;
|
||||||
/**
|
/**
|
||||||
* 输入
|
* 输入
|
||||||
@@ -56,6 +56,6 @@ public class ChatMessage implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String totalCost;
|
private String totalCost;
|
||||||
|
|
||||||
@ApiModelProperty("创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -20,7 +20,7 @@ public class ChatRobot implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty("ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -18,22 +18,22 @@ import java.time.LocalDateTime;
|
|||||||
public class Classification implements Serializable {
|
public class Classification implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
@ApiModelProperty(value = "分类名称")
|
@Schema(description = "分类名称")
|
||||||
private String classificationName;
|
private String classificationName;
|
||||||
@ApiModelProperty(value = "分类类型")
|
@Schema(description = "分类类型")
|
||||||
private String type;
|
private String type;
|
||||||
@ApiModelProperty(value = "父菜单ID")
|
@Schema(description = "父菜单ID")
|
||||||
private Long parentId;
|
private Long parentId;
|
||||||
@ApiModelProperty(value = "用户ID")
|
@Schema(description = "用户ID")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
@ApiModelProperty(value = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
@ApiModelProperty(value = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
@ApiModelProperty(value = "是否删除1:是0:否")
|
@Schema(description = "是否删除1:是0:否")
|
||||||
private Integer isDeleted = 0;
|
private Integer isDeleted = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -18,20 +18,20 @@ import java.time.LocalDateTime;
|
|||||||
public class ClassificationRelLibrary implements Serializable {
|
public class ClassificationRelLibrary implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
@ApiModelProperty(value = "分类名称")
|
@Schema(description = "分类名称")
|
||||||
private Long classificationId;
|
private Long classificationId;
|
||||||
@ApiModelProperty(value = "分类名称")
|
@Schema(description = "分类名称")
|
||||||
private Long libraryId;
|
private Long libraryId;
|
||||||
@ApiModelProperty(value = "用户ID")
|
@Schema(description = "用户ID")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
@ApiModelProperty(value = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
@ApiModelProperty(value = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
@ApiModelProperty(value = "是否删除1:是0:否")
|
@Schema(description = "是否删除1:是0:否")
|
||||||
private Integer isDeleted;
|
private Integer isDeleted;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -19,52 +19,52 @@ import java.time.LocalDateTime;
|
|||||||
public class CloudTask implements Serializable {
|
public class CloudTask implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty("任务名")
|
@Schema(description = "任务名")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("项目ID")
|
@Schema(description = "项目ID")
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|
||||||
@ApiModelProperty("collectionId")
|
@Schema(description = "collectionId")
|
||||||
private Long collectionId;
|
private Long collectionId;
|
||||||
|
|
||||||
@ApiModelProperty("designId")
|
@Schema(description = "designId")
|
||||||
private Long designId;
|
private Long designId;
|
||||||
|
|
||||||
@ApiModelProperty("任务类型")
|
@Schema(description = "任务类型")
|
||||||
private String buildType;
|
private String buildType;
|
||||||
|
|
||||||
@ApiModelProperty("生成数量")
|
@Schema(description = "生成数量")
|
||||||
private Integer nums;
|
private Integer nums;
|
||||||
|
|
||||||
@ApiModelProperty("完成数量")
|
@Schema(description = "完成数量")
|
||||||
private Integer completedNum;
|
private Integer completedNum;
|
||||||
|
|
||||||
@ApiModelProperty("消耗积分")
|
@Schema(description = "消耗积分")
|
||||||
private Integer costCredits;
|
private Integer costCredits;
|
||||||
|
|
||||||
@ApiModelProperty("状态1完成0未完成")
|
@Schema(description = "状态1完成0未完成")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@ApiModelProperty("批处理ID")
|
@Schema(description = "批处理ID")
|
||||||
private String taskId;
|
private String taskId;
|
||||||
|
|
||||||
@ApiModelProperty("创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
@ApiModelProperty("任务开始时间")
|
@Schema(description = "任务开始时间")
|
||||||
private LocalDateTime startTime;
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
@ApiModelProperty("任务更新时间")
|
@Schema(description = "任务更新时间")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
@ApiModelProperty("用户ID")
|
@Schema(description = "用户ID")
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
|
|
||||||
@ApiModelProperty("任务序号")
|
@Schema(description = "任务序号")
|
||||||
private Long sequence;
|
private Long sequence;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* submissions 表对应实体 — 参赛选手信息 (Contestant)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@TableName("contestants")
|
||||||
|
public class Contestant {
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@TableField("contestant_number")
|
||||||
|
private Integer contestantNumber;
|
||||||
|
|
||||||
|
@TableField("first_name")
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
@TableField("last_name")
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
private String gender;
|
||||||
|
|
||||||
|
private String occupation;
|
||||||
|
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
@TableField("country_region_city")
|
||||||
|
private String countryRegionCity;
|
||||||
|
|
||||||
|
@TableField("phone_number")
|
||||||
|
private String phoneNumber;
|
||||||
|
|
||||||
|
@TableField("design_title")
|
||||||
|
private String designTitle;
|
||||||
|
|
||||||
|
@TableField("design_description")
|
||||||
|
private String designDescription;
|
||||||
|
|
||||||
|
@TableField("pdf_path")
|
||||||
|
private String pdfPath;
|
||||||
|
|
||||||
|
@TableField("video_path")
|
||||||
|
private String videoPath;
|
||||||
|
|
||||||
|
@TableField("video_duration")
|
||||||
|
private Integer videoDuration;
|
||||||
|
|
||||||
|
@TableField("video_size")
|
||||||
|
private Long videoSize;
|
||||||
|
|
||||||
|
@TableField("pdf_size")
|
||||||
|
private Long pdfSize;
|
||||||
|
|
||||||
|
@TableField("portfolio_url")
|
||||||
|
private String portfolioUrl;
|
||||||
|
|
||||||
|
@TableField("created_at")
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@TableField("updated_at")
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -62,4 +62,9 @@ public class DesignItemDetailPrint {
|
|||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
private LocalDateTime updateDate;
|
private LocalDateTime updateDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象信息(JSON格式)
|
||||||
|
*/
|
||||||
|
private String object;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,50 +3,49 @@ package com.ai.da.mapper.primary.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@Data
|
@Data
|
||||||
@ApiModel(value = "Portfolio对象", description = "作品集")
|
@Schema(description = "作品集")
|
||||||
@TableName("portfolio")
|
@TableName("portfolio")
|
||||||
public class Portfolio implements Serializable {
|
public class Portfolio implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "collection ID")
|
@Schema(description = "collection ID")
|
||||||
private Long collectionId;
|
private Long collectionId;
|
||||||
|
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "userLikeGroup源")
|
@Schema(description = "userLikeGroup源")
|
||||||
private Long userLikeGroupSourceId;
|
private Long userLikeGroupSourceId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "作品名称")
|
@Schema(description = "作品名称")
|
||||||
private String portfolioName;
|
private String portfolioName;
|
||||||
|
|
||||||
@ApiModelProperty(value = "作品描述")
|
@Schema(description = "作品描述")
|
||||||
private String portfolioDes;
|
private String portfolioDes;
|
||||||
|
|
||||||
@ApiModelProperty(value = "作品类型")
|
@Schema(description = "作品类型")
|
||||||
private String portfolioType;
|
private String portfolioType;
|
||||||
|
|
||||||
@ApiModelProperty(value = "画布ID")
|
@Schema(description = "画布ID")
|
||||||
private Long canvasId;
|
private Long canvasId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "封面ID")
|
@Schema(description = "封面ID")
|
||||||
private Long coverId;
|
private Long coverId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "作品状态1公开0隐藏")
|
@Schema(description = "作品状态1公开0隐藏")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@ApiModelProperty(value = "是否允许二次创作1允许0不允许")
|
@Schema(description = "是否允许二次创作1允许0不允许")
|
||||||
private Integer openSource;
|
private Integer openSource;
|
||||||
|
|
||||||
private Integer original;
|
private Integer original;
|
||||||
@@ -57,7 +56,7 @@ public class Portfolio implements Serializable {
|
|||||||
|
|
||||||
private String snapshot;
|
private String snapshot;
|
||||||
|
|
||||||
@ApiModelProperty(value = "作品集作者ID")
|
@Schema(description = "作品集作者ID")
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
|
|
||||||
// 学校/企业id
|
// 学校/企业id
|
||||||
@@ -66,12 +65,12 @@ public class Portfolio implements Serializable {
|
|||||||
// 该条作品是否在该组织公开 默认公开 1(0为不公开)
|
// 该条作品是否在该组织公开 默认公开 1(0为不公开)
|
||||||
private Integer isPublic;
|
private Integer isPublic;
|
||||||
|
|
||||||
@ApiModelProperty(value = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createDate;
|
private LocalDateTime createDate;
|
||||||
|
|
||||||
@ApiModelProperty(value = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updateDate;
|
private LocalDateTime updateDate;
|
||||||
|
|
||||||
@ApiModelProperty(value = "是否删除")
|
@Schema(description = "是否删除")
|
||||||
private Integer isDeleted;
|
private Integer isDeleted;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("t_subscription_plan")
|
||||||
|
public class SubscriptionPlan extends BaseEntity{
|
||||||
|
/**
|
||||||
|
* 组织id
|
||||||
|
*/
|
||||||
|
private Long organizationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅命名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅开始时间
|
||||||
|
*/
|
||||||
|
private Long currentPeriodStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅结束时间
|
||||||
|
*/
|
||||||
|
private Long currentPeriodEnd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅总的子账号数量
|
||||||
|
*/
|
||||||
|
private Integer accountNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅可用积分上限
|
||||||
|
*/
|
||||||
|
private BigDecimal creditLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅已使用积分
|
||||||
|
*/
|
||||||
|
private BigDecimal creditUsage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员账户id
|
||||||
|
*/
|
||||||
|
private Long adminAccId;
|
||||||
|
|
||||||
|
@TableLogic(value = "0", delval = "1")
|
||||||
|
private Integer isDeleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除人的用户id
|
||||||
|
*/
|
||||||
|
private Long deleteBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 国家或地区
|
||||||
|
*/
|
||||||
|
private String countryOrRegion;
|
||||||
|
|
||||||
|
// 在类内部定义的枚举
|
||||||
|
@Getter
|
||||||
|
public enum SubscriptionStatus {
|
||||||
|
PENDING("待激活", 0),
|
||||||
|
ACTIVE("已激活", 1),
|
||||||
|
EXPIRED("已过期", 2),
|
||||||
|
CANCELLED("已取消", 3);
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
SubscriptionStatus(String desc, int code) {
|
||||||
|
this.desc = desc;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -25,22 +24,22 @@ import java.util.Date;
|
|||||||
@Setter
|
@Setter
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@TableName("t_collection_element_relation")
|
@TableName("t_collection_element_relation")
|
||||||
@ApiModel(value = "TCollectionElementRelation对象", description = "collection和element的关联表")
|
@Schema(description = "collection和element的关联表")
|
||||||
public class TCollectionElementRelation implements Serializable {
|
public class TCollectionElementRelation implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty("ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty("element ID")
|
@Schema(description = "element ID")
|
||||||
private Long elementId;
|
private Long elementId;
|
||||||
|
|
||||||
@ApiModelProperty("colletion ID class类型为COLLECTION 存 其他默认是0")
|
@Schema(description = "colletion ID class类型为COLLECTION 存 其他默认是0")
|
||||||
private Long collectionId;
|
private Long collectionId;
|
||||||
|
|
||||||
@ApiModelProperty("创建时间")
|
@Schema(description = "创建时间")
|
||||||
private Date createDate;
|
private Date createDate;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -9,9 +10,6 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* design item表 存对应design的8张图片实体类
|
* design item表 存对应design的8张图片实体类
|
||||||
*
|
*
|
||||||
@@ -20,7 +18,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("t_design_python_outfit")
|
@TableName("t_design_python_outfit")
|
||||||
@ApiModel(value = "TDesignPythonOutfit对象", description = "design item表 存对应design的8张图片")
|
@Schema(description = "design item表 存对应design的8张图片")
|
||||||
public class TDesignPythonOutfit implements Serializable {
|
public class TDesignPythonOutfit implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@@ -28,48 +26,48 @@ public class TDesignPythonOutfit implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* ID
|
* ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* designItemId
|
* designItemId
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "designItemId")
|
@Schema(description = "designItemId")
|
||||||
private Long designItemId;
|
private Long designItemId;
|
||||||
/**
|
/**
|
||||||
* 关联的design ID
|
* 关联的design ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "关联的design ID")
|
@Schema(description = "关联的design ID")
|
||||||
private Long designId;
|
private Long designId;
|
||||||
/**
|
/**
|
||||||
* 关联的collection ID
|
* 关联的collection ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "关联的collection ID")
|
@Schema(description = "关联的collection ID")
|
||||||
private Long collectionId;
|
private Long collectionId;
|
||||||
/**
|
/**
|
||||||
* design后的用户文件地址(python 返回)
|
* design后的用户文件地址(python 返回)
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "design后的用户文件地址(python 返回)")
|
@Schema(description = "design后的用户文件地址(python 返回)")
|
||||||
private String designUrl;
|
private String designUrl;
|
||||||
/**
|
/**
|
||||||
* 保存用户ID
|
* 保存用户ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "保存用户ID")
|
@Schema(description = "保存用户ID")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createDate;
|
private LocalDateTime createDate;
|
||||||
/**
|
/**
|
||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updateDate;
|
private LocalDateTime updateDate;
|
||||||
/**
|
/**
|
||||||
* 是否删除
|
* 是否删除
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "是否删除")
|
@Schema(description = "是否删除")
|
||||||
private String isDeleted;
|
private String isDeleted;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -9,9 +10,6 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* design item详情表实体类
|
* design item详情表实体类
|
||||||
*
|
*
|
||||||
@@ -20,7 +18,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("t_design_python_outfit_detail")
|
@TableName("t_design_python_outfit_detail")
|
||||||
@ApiModel(value = "TDesignPythonOutfitDetail对象", description = "design item详情表")
|
@Schema(description = "design item详情表")
|
||||||
public class TDesignPythonOutfitDetail implements Serializable {
|
public class TDesignPythonOutfitDetail implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@@ -28,84 +26,97 @@ public class TDesignPythonOutfitDetail implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* ID
|
* ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 关联的design ID
|
* 关联的design ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "关联的design ID")
|
@Schema(description = "关联的design ID")
|
||||||
private Long designId;
|
private Long designId;
|
||||||
/**
|
/**
|
||||||
* 关联的design_item ID
|
* 关联的design_item ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "关联的design_item ID")
|
@Schema(description = "关联的design_item ID")
|
||||||
private Long designPythonOutfitId;
|
private Long designPythonOutfitId;
|
||||||
/**
|
/**
|
||||||
* 关联的elementId 没有为null
|
* 关联的elementId 没有为null
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "关联的elementId 没有为null")
|
@Schema(description = "关联的elementId 没有为null")
|
||||||
private Long collectionElementId;
|
private Long collectionElementId;
|
||||||
/**
|
/**
|
||||||
* 图层
|
* 图层
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "图层")
|
@Schema(description = "图层")
|
||||||
private String imageCategory;
|
private String imageCategory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* imageSize
|
* imageSize
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "imageSize")
|
@Schema(description = "imageSize")
|
||||||
private String imageSize;
|
private String imageSize;
|
||||||
/**
|
/**
|
||||||
* 对应的图片的绝对路径
|
* 对应的图片的绝对路径
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "对应的图片的绝对路径")
|
@Schema(description = "对应的图片的绝对路径")
|
||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
/**
|
/**
|
||||||
* mask_url
|
* mask_url
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "mask_url")
|
@Schema(description = "mask_url")
|
||||||
private String maskUrl;
|
private String maskUrl;
|
||||||
/**
|
/**
|
||||||
* 位置
|
* 位置
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "位置")
|
@Schema(description = "位置")
|
||||||
private String position;
|
private String position;
|
||||||
/**
|
/**
|
||||||
* 偏移量
|
* 偏移量
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "偏移量")
|
@Schema(description = "偏移量")
|
||||||
private String offset;
|
private String offset;
|
||||||
/**
|
/**
|
||||||
* 图层缩放大小
|
* 图层缩放大小
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "图层缩放大小")
|
@Schema(description = "图层缩放大小")
|
||||||
private String scale;
|
private String scale;
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "用户ID")
|
@Schema(description = "用户ID")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
/**
|
/**
|
||||||
* 图层优先级
|
* 图层优先级
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "图层优先级")
|
@Schema(description = "图层优先级")
|
||||||
private Integer priority;
|
private Integer priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 镜像模式
|
||||||
|
*/
|
||||||
|
@Schema(description = "镜像模式")
|
||||||
|
private String transpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旋转角度
|
||||||
|
*/
|
||||||
|
@Schema(description = "旋转角度")
|
||||||
|
private Double rotate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createDate;
|
private LocalDateTime createDate;
|
||||||
/**
|
/**
|
||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updateDate;
|
private LocalDateTime updateDate;
|
||||||
/**
|
/**
|
||||||
* 是否删除
|
* 是否删除
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "是否删除")
|
@Schema(description = "是否删除")
|
||||||
private Integer isDeleted;
|
private Integer isDeleted;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -12,22 +12,22 @@ import java.time.LocalDateTime;
|
|||||||
public class ToProductElement implements Serializable {
|
public class ToProductElement implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "userLikeGroupId")
|
@Schema(description = "userLikeGroupId")
|
||||||
private Long userLikeGroupId;
|
private Long userLikeGroupId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "项目id")
|
@Schema(description = "项目id")
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "url")
|
@Schema(description = "url")
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
@ApiModelProperty(value = "首尾帧 first | last")
|
@Schema(description = "首尾帧 first | last")
|
||||||
private String frameType;
|
private String frameType;
|
||||||
|
|
||||||
@ApiModelProperty(value = "createTime")
|
@Schema(description = "createTime")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -12,18 +12,18 @@ import java.time.LocalDateTime;
|
|||||||
public class ToProductImageRecord implements Serializable {
|
public class ToProductImageRecord implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "userLikeGroupId")
|
@Schema(description = "userLikeGroupId")
|
||||||
private Long userLikeGroupId;
|
private Long userLikeGroupId;
|
||||||
|
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "prompt")
|
@Schema(description = "prompt")
|
||||||
private String prompt;
|
private String prompt;
|
||||||
|
|
||||||
@ApiModelProperty(value = "createTime")
|
@Schema(description = "createTime")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -14,11 +14,11 @@ import java.time.LocalDateTime;
|
|||||||
public class ToProductImageResult implements Serializable {
|
public class ToProductImageResult implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "elementId")
|
@Schema(description = "elementId")
|
||||||
private Long elementId;
|
private Long elementId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,28 +26,28 @@ public class ToProductImageResult implements Serializable {
|
|||||||
* ProductElement 上传的图片
|
* ProductElement 上传的图片
|
||||||
* ToProductImage 以to product image的结果作为图片来源(relight)
|
* ToProductImage 以to product image的结果作为图片来源(relight)
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "elementType 图片来源:DesignOutfit(design的结果) | ProductElement(上传的图片) | ToProductImage(生成的结果)")
|
@Schema(description = "elementType 图片来源:DesignOutfit(design的结果) | ProductElement(上传的图片) | ToProductImage(生成的结果)")
|
||||||
private String elementType;
|
private String elementType;
|
||||||
|
|
||||||
@ApiModelProperty(value = "url")
|
@Schema(description = "url")
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
@ApiModelProperty(value = "isLike 1是0否")
|
@Schema(description = "isLike 1是0否")
|
||||||
private Integer isLike;
|
private Integer isLike;
|
||||||
|
|
||||||
@ApiModelProperty(value = "createTime")
|
@Schema(description = "createTime")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
@ApiModelProperty(value = "toProductImageRecordId")
|
@Schema(description = "toProductImageRecordId")
|
||||||
private Long toProductImageRecordId;
|
private Long toProductImageRecordId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "taskId")
|
@Schema(description = "taskId")
|
||||||
private String taskId;
|
private String taskId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "userLikeGroupId")
|
@Schema(description = "userLikeGroupId")
|
||||||
private Long userLikeGroupId;
|
private Long userLikeGroupId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "generate 结果类型")
|
@Schema(description = "generate 结果类型")
|
||||||
private String resultType;
|
private String resultType;
|
||||||
|
|
||||||
private Double brightenValue;
|
private Double brightenValue;
|
||||||
@@ -64,7 +64,7 @@ public class ToProductImageResult implements Serializable {
|
|||||||
|
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
@ApiModelProperty(value = "是否删除1:是 0:否")
|
@Schema(description = "是否删除1:是 0:否")
|
||||||
@TableField
|
@TableField
|
||||||
private byte isDeleted = 0;
|
private byte isDeleted = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.ai.da.mapper.primary.entity;
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@@ -26,25 +26,25 @@ public class TrialOrder implements Serializable {
|
|||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty("title")
|
@Schema(description = "title")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@ApiModelProperty("surname")
|
@Schema(description = "surname")
|
||||||
private String surname;
|
private String surname;
|
||||||
|
|
||||||
@ApiModelProperty("givenName")
|
@Schema(description = "givenName")
|
||||||
private String givenName;
|
private String givenName;
|
||||||
|
|
||||||
@ApiModelProperty("userName")
|
@Schema(description = "userName")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
@ApiModelProperty("email")
|
@Schema(description = "email")
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@ApiModelProperty("country")
|
@Schema(description = "country")
|
||||||
private String country;
|
private String country;
|
||||||
|
|
||||||
@ApiModelProperty("occupation")
|
@Schema(description = "occupation")
|
||||||
private String occupation;
|
private String occupation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.ai.da.mapper.primary.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("user_preference")
|
||||||
|
public class UserPreference implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private Long accountId;
|
||||||
|
private String path;
|
||||||
|
private LocalDateTime dataTime;
|
||||||
|
private String category;
|
||||||
|
private String style;
|
||||||
|
private Long workspaceRelStyleId;
|
||||||
|
private Long projectId;
|
||||||
|
private Long designItemId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,5 +23,8 @@ public class UserPreferenceLogTest implements Serializable {
|
|||||||
private Long accountId;
|
private Long accountId;
|
||||||
private String path;
|
private String path;
|
||||||
private LocalDateTime dataTime;
|
private LocalDateTime dataTime;
|
||||||
|
private String category;
|
||||||
|
private String style;
|
||||||
|
private Long sysFileId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体类
|
* 实体类
|
||||||
@@ -17,7 +16,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
* @since 2023-08-01
|
* @since 2023-08-01
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ApiModel(value = "Workspace对象", description = "Workspace对象")
|
@Schema(description = "Workspace对象")
|
||||||
@TableName("workspace")
|
@TableName("workspace")
|
||||||
public class Workspace implements Serializable {
|
public class Workspace implements Serializable {
|
||||||
|
|
||||||
@@ -26,23 +25,23 @@ public class Workspace implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* ID
|
* ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "ID")
|
@Schema(description = "ID")
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 工作空间名称
|
* 工作空间名称
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "工作空间名称")
|
@Schema(description = "工作空间名称")
|
||||||
private String workSpaceName;
|
private String workSpaceName;
|
||||||
/**
|
/**
|
||||||
* 用户名
|
* 用户名
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "用户名")
|
@Schema(description = "用户名")
|
||||||
private String userName;
|
private String userName;
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "用户ID")
|
@Schema(description = "用户ID")
|
||||||
private Long accountId;
|
private Long accountId;
|
||||||
/**
|
/**
|
||||||
* 年龄段 Adult || Child
|
* 年龄段 Adult || Child
|
||||||
@@ -51,54 +50,54 @@ public class Workspace implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 性别
|
* 性别
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "性别")
|
@Schema(description = "性别")
|
||||||
private String sex;
|
private String sex;
|
||||||
/**
|
/**
|
||||||
* 服装部位
|
* 服装部位
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "服装部位")
|
@Schema(description = "服装部位")
|
||||||
private String position;
|
private String position;
|
||||||
/**
|
/**
|
||||||
* SYSTEM_DESIGNER占比
|
* SYSTEM_DESIGNER占比
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "SYSTEM_DESIGNER占比")
|
@Schema(description = "SYSTEM_DESIGNER占比")
|
||||||
private Integer systemDesignerPercentage;
|
private Integer systemDesignerPercentage;
|
||||||
/**
|
/**
|
||||||
* 人体模型
|
* 人体模型
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "人体模型ID")
|
@Schema(description = "人体模型ID")
|
||||||
private Long mannequinFemaleId;
|
private Long mannequinFemaleId;
|
||||||
private Long mannequinMaleId;
|
private Long mannequinMaleId;
|
||||||
private Long mannequinChildId;
|
private Long mannequinChildId;
|
||||||
/**
|
/**
|
||||||
* 人体模型
|
* 人体模型
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "人体模型类型")
|
@Schema(description = "人体模型类型")
|
||||||
private String mannequinFemaleType;
|
private String mannequinFemaleType;
|
||||||
private String mannequinMaleType;
|
private String mannequinMaleType;
|
||||||
private String mannequinChildType;
|
private String mannequinChildType;
|
||||||
/**
|
/**
|
||||||
* 最后使用的工作空间标识
|
* 最后使用的工作空间标识
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "最后使用的工作空间标识")
|
@Schema(description = "最后使用的工作空间标识")
|
||||||
private Integer isLastIndex;
|
private Integer isLastIndex;
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField(fill = FieldFill.INSERT)
|
@TableField(fill = FieldFill.INSERT)
|
||||||
@ApiModelProperty(value = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
/**
|
/**
|
||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
@ApiModelProperty(value = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
/**
|
/**
|
||||||
* 是否删除
|
* 是否删除
|
||||||
*/
|
*/
|
||||||
@TableLogic
|
@TableLogic
|
||||||
@ApiModelProperty(value = "是否删除")
|
@Schema(description = "是否删除")
|
||||||
private Integer isDeleted;
|
private Integer isDeleted;
|
||||||
|
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -10,42 +10,42 @@ import jakarta.validation.constraints.NotBlank;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("AccountAddDTO")
|
@Schema(description = "AccountAddDTO")
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class AccountAddDTO {
|
public class AccountAddDTO {
|
||||||
|
|
||||||
@NotBlank(message = "email.cannot.be.empty")
|
@NotBlank(message = "email.cannot.be.empty")
|
||||||
@ApiModelProperty("userEmail")
|
@Schema(description = "userEmail")
|
||||||
private String userEmail;
|
private String userEmail;
|
||||||
|
|
||||||
@NotBlank(message = "userName.cannot.be.empty")
|
@NotBlank(message = "userName.cannot.be.empty")
|
||||||
@ApiModelProperty("userName")
|
@Schema(description = "userName")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
private String country;
|
private String country;
|
||||||
|
|
||||||
@NotBlank(message = "validStartTime.cannot.be.empty")
|
@NotBlank(message = "validStartTime.cannot.be.empty")
|
||||||
@ApiModelProperty("Start time of account validity ")
|
@Schema(description = "Start time of account validity ")
|
||||||
private String validStartTime;
|
private String validStartTime;
|
||||||
|
|
||||||
@NotBlank(message = "validEndTime.cannot.be.empty")
|
@NotBlank(message = "validEndTime.cannot.be.empty")
|
||||||
@ApiModelProperty("End time of account validity ")
|
@Schema(description = "End time of account validity ")
|
||||||
private String validEndTime;
|
private String validEndTime;
|
||||||
|
|
||||||
@ApiModelProperty("是否是试用用户 0 否 | 1 是")
|
@Schema(description = "是否是试用用户 0 否 | 1 是")
|
||||||
private Integer isTrial;
|
private Integer isTrial;
|
||||||
|
|
||||||
@ApiModelProperty("分配积分")
|
@Schema(description = "分配积分")
|
||||||
private BigDecimal credits;
|
private BigDecimal credits;
|
||||||
|
|
||||||
@ApiModelProperty("用户角色")
|
@Schema(description = "用户角色")
|
||||||
private Integer systemUser;
|
private Integer systemUser;
|
||||||
|
|
||||||
@ApiModelProperty("学校名称 | 企业名称")
|
@Schema(description = "学校名称 | 企业名称")
|
||||||
private String organizationName;
|
private String organizationName;
|
||||||
|
|
||||||
@ApiModelProperty("可分配子账号总数(仅适用于学校或教育管理员)")
|
@Schema(description = "可分配子账号总数(仅适用于学校或教育管理员)")
|
||||||
private Integer subAccountNum;
|
private Integer subAccountNum;
|
||||||
|
|
||||||
public AccountAddDTO(String userEmail, String userName, String country, String validStartTime, String validEndTime, Integer isTrial, BigDecimal credits, Integer systemUser) {
|
public AccountAddDTO(String userEmail, String userName, String country, String validStartTime, String validEndTime, Integer isTrial, BigDecimal credits, Integer systemUser) {
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("绑定邮箱")
|
@Schema(description = "绑定邮箱")
|
||||||
public class AccountBindEmailDTO {
|
public class AccountBindEmailDTO {
|
||||||
|
|
||||||
// @NotNull(message = "userId.cannot.be.empty")
|
// @NotNull(message = "userId.cannot.be.empty")
|
||||||
// @ApiModelProperty("用户id")
|
// @Schema(description = "用户id")
|
||||||
// private Long userId;
|
// private Long userId;
|
||||||
|
|
||||||
@NotBlank(message = "email.cannot.be.empty")
|
@NotBlank(message = "email.cannot.be.empty")
|
||||||
@ApiModelProperty("邮箱")
|
@Schema(description = "邮箱")
|
||||||
private String userEmail;
|
private String userEmail;
|
||||||
|
|
||||||
@NotBlank(message = "emailVerifyCode.cannot.be.empty")
|
@NotBlank(message = "emailVerifyCode.cannot.be.empty")
|
||||||
@ApiModelProperty("邮箱验证码")
|
@Schema(description = "邮箱验证码")
|
||||||
private String emailVerifyCode;
|
private String emailVerifyCode;
|
||||||
|
|
||||||
// @ApiModelProperty("国家")
|
// @Schema(description = "国家")
|
||||||
// private String country;
|
// private String country;
|
||||||
//
|
//
|
||||||
// @ApiModelProperty("职业")
|
// @Schema(description = "职业")
|
||||||
// private String occupation;
|
// private String occupation;
|
||||||
//
|
//
|
||||||
// @ApiModelProperty("title")
|
// @Schema(description = "title")
|
||||||
// private String title;
|
// private String title;
|
||||||
//
|
//
|
||||||
// @ApiModelProperty("surname")
|
// @Schema(description = "surname")
|
||||||
// private String surname;
|
// private String surname;
|
||||||
//
|
//
|
||||||
// @ApiModelProperty("givenName")
|
// @Schema(description = "givenName")
|
||||||
// private String givenName;
|
// private String givenName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("AccountEdit")
|
@Schema(description = "AccountEdit")
|
||||||
public class AccountEditDTO {
|
public class AccountEditDTO {
|
||||||
|
|
||||||
@ApiModelProperty("Old user email")
|
@Schema(description = "Old user email")
|
||||||
private String oldEmail;
|
private String oldEmail;
|
||||||
|
|
||||||
@ApiModelProperty("New user email")
|
@Schema(description = "New user email")
|
||||||
private String newEmail;
|
private String newEmail;
|
||||||
|
|
||||||
@ApiModelProperty("Old user name")
|
@Schema(description = "Old user name")
|
||||||
private String oldUserName;
|
private String oldUserName;
|
||||||
|
|
||||||
@ApiModelProperty("New user name")
|
@Schema(description = "New user name")
|
||||||
private String newUserName;
|
private String newUserName;
|
||||||
|
|
||||||
@ApiModelProperty("Start time of the new account validity period")
|
@Schema(description = "Start time of the new account validity period")
|
||||||
private String newValidStartTime;
|
private String newValidStartTime;
|
||||||
|
|
||||||
@ApiModelProperty("Start time of the old account validity period")
|
@Schema(description = "Start time of the old account validity period")
|
||||||
private String oldValidStartTime;
|
private String oldValidStartTime;
|
||||||
|
|
||||||
@ApiModelProperty("End time of the new account validity period")
|
@Schema(description = "End time of the new account validity period")
|
||||||
private String newValidEndTime;
|
private String newValidEndTime;
|
||||||
|
|
||||||
@ApiModelProperty("End time of the old account validity period")
|
@Schema(description = "End time of the old account validity period")
|
||||||
private String oldValidEndTime;
|
private String oldValidEndTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("登入")
|
@Schema(description = "登入")
|
||||||
public class AccountLoginDTO {
|
public class AccountLoginDTO {
|
||||||
|
|
||||||
@ApiModelProperty("userId")
|
@Schema(description = "userId")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
@ApiModelProperty("邮箱")
|
@Schema(description = "邮箱")
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@ApiModelProperty("用户名")
|
@Schema(description = "用户名")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
@ApiModelProperty("密码")
|
@Schema(description = "密码")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@ApiModelProperty("登入类型 EMAIL - >邮箱 , PASSWORD ->密码")
|
@Schema(description = "登入类型 EMAIL - >邮箱 , PASSWORD ->密码")
|
||||||
private String loginType;
|
private String loginType;
|
||||||
|
|
||||||
@ApiModelProperty("邮箱验证码")
|
@Schema(description = "邮箱验证码")
|
||||||
private String emailVerifyCode;
|
private String emailVerifyCode;
|
||||||
|
|
||||||
@ApiModelProperty("组织名")
|
@Schema(description = "组织名")
|
||||||
private String organizationName;
|
private String organizationName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("登出")
|
@Schema(description = "登出")
|
||||||
public class AccountLogoutDTO {
|
public class AccountLogoutDTO {
|
||||||
|
|
||||||
@NotNull(message = "userId.cannot.be.empty")
|
@NotNull(message = "userId.cannot.be.empty")
|
||||||
@ApiModelProperty("userId")
|
@Schema(description = "userId")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,31 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("预先登入")
|
@Schema(description = "预先登入")
|
||||||
public class AccountPreLoginDTO {
|
public class AccountPreLoginDTO {
|
||||||
|
|
||||||
@NotBlank(message = "userName.cannot.be.empty")
|
@NotBlank(message = "userName.cannot.be.empty")
|
||||||
@ApiModelProperty("用户名")
|
@Schema(description = "用户名")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
/*新增字段*/
|
/*新增字段*/
|
||||||
@NotBlank(message = "email.cannot.be.empty")
|
@NotBlank(message = "email.cannot.be.empty")
|
||||||
@ApiModelProperty("邮箱")
|
@Schema(description = "邮箱")
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@NotBlank(message = "password.cannot.be.empty")
|
@NotBlank(message = "password.cannot.be.empty")
|
||||||
@ApiModelProperty("密码")
|
@Schema(description = "密码")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@NotBlank(message = "operationType.cannot.be.empty")
|
@NotBlank(message = "operationType.cannot.be.empty")
|
||||||
@ApiModelProperty("操作类型 LOGIN 注册 FORGET_PWD 忘记密码 BIND_MAILBOX 绑定邮箱")
|
@Schema(description = "操作类型 LOGIN 注册 FORGET_PWD 忘记密码 BIND_MAILBOX 绑定邮箱")
|
||||||
private String operationType;
|
private String operationType;
|
||||||
|
|
||||||
@ApiModelProperty("异常ip")
|
@Schema(description = "异常ip")
|
||||||
private String ip;
|
private String ip;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,25 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("账户")
|
@Schema(description = "账户")
|
||||||
public class AccountRegisterDTO {
|
public class AccountRegisterDTO {
|
||||||
|
|
||||||
@NotBlank(message = "email.cannot.be.empty")
|
@NotBlank(message = "email.cannot.be.empty")
|
||||||
@ApiModelProperty("邮箱")
|
@Schema(description = "邮箱")
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
private Boolean verifyEmail;
|
private Boolean verifyEmail;
|
||||||
// @NotBlank(message = "password.cannot.be.empty")
|
// @NotBlank(message = "password.cannot.be.empty")
|
||||||
@ApiModelProperty("密码")
|
@Schema(description = "密码")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@NotBlank(message = "emailVerifyCode.cannot.be.empty")
|
@NotBlank(message = "emailVerifyCode.cannot.be.empty")
|
||||||
@ApiModelProperty("邮箱验证码")
|
@Schema(description = "邮箱验证码")
|
||||||
private String emailVerifyCode;
|
private String emailVerifyCode;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import com.ai.da.mapper.primary.entity.TrialOrder;
|
import com.ai.da.mapper.primary.entity.TrialOrder;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("AccountTrial")
|
@Schema(description = "AccountTrial")
|
||||||
public class AccountTrialDTO extends TrialOrder {
|
public class AccountTrialDTO extends TrialOrder {
|
||||||
private String ref;
|
private String ref;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@@ -9,19 +8,19 @@ import jakarta.validation.constraints.Pattern;
|
|||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("查询affiliate列表")
|
@Schema(description = "查询affiliate列表")
|
||||||
public class AffiliateQueryDTO extends TimeQueryBaseDTO{
|
public class AffiliateQueryDTO extends TimeQueryBaseDTO{
|
||||||
@ApiModelProperty("Active(活跃) || Inactive(过期) || Pending(待审批) || Refused(拒绝)")
|
@Schema(description = "Active(活跃) || Inactive(过期) || Pending(待审批) || Refused(拒绝)")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
@ApiModelProperty("推广者id")
|
@Schema(description = "推广者id")
|
||||||
private Long affiliateId;
|
private Long affiliateId;
|
||||||
|
|
||||||
@Pattern(regexp = "id|createTime|totalIncome|", message = "允许排序字段只有id|createTime|totalIncome")
|
@Pattern(regexp = "id|createTime|totalIncome|", message = "允许排序字段只有id|createTime|totalIncome")
|
||||||
@ApiModelProperty("目前允许按id, createTime, totalIncome进行排序")
|
@Schema(description = "目前允许按id, createTime, totalIncome进行排序")
|
||||||
private String orderBy = "id";
|
private String orderBy = "id";
|
||||||
|
|
||||||
@ApiModelProperty("按时间 DESC 降序 || ASC 升序")
|
@Schema(description = "按时间 DESC 降序 || ASC 升序")
|
||||||
private String order = "ASC";
|
private String order = "ASC";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
@@ -17,11 +17,11 @@ import jakarta.validation.constraints.NotNull;
|
|||||||
@Data
|
@Data
|
||||||
public class ChatFlushDTO {
|
public class ChatFlushDTO {
|
||||||
@NotNull(message = "user_id.cannot.be.empty")
|
@NotNull(message = "user_id.cannot.be.empty")
|
||||||
@ApiModelProperty("用户id")
|
@Schema(description = "用户id")
|
||||||
private String user_id;
|
private String user_id;
|
||||||
|
|
||||||
@NotBlank(message = "session_id.cannot.be.empty")
|
@NotBlank(message = "session_id.cannot.be.empty")
|
||||||
@ApiModelProperty("会话ID")
|
@Schema(description = "会话ID")
|
||||||
private String session_id;
|
private String session_id;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
@@ -16,23 +15,23 @@ import jakarta.validation.constraints.NotNull;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("chatRobot 对话")
|
@Schema(description = "chatRobot 对话")
|
||||||
public class ChatSendDTO {
|
public class ChatSendDTO {
|
||||||
|
|
||||||
@NotNull(message = "userId.cannot.be.empty")
|
@NotNull(message = "userId.cannot.be.empty")
|
||||||
@ApiModelProperty("用户id")
|
@Schema(description = "用户id")
|
||||||
private Long user_id;
|
private Long user_id;
|
||||||
|
|
||||||
@NotBlank(message = "sessionId.cannot.be.empty")
|
@NotBlank(message = "sessionId.cannot.be.empty")
|
||||||
@ApiModelProperty("会话ID")
|
@Schema(description = "会话ID")
|
||||||
private String session_id;
|
private String session_id;
|
||||||
|
|
||||||
@NotBlank(message = "message.cannot.be.empty")
|
@NotBlank(message = "message.cannot.be.empty")
|
||||||
@ApiModelProperty("消息")
|
@Schema(description = "消息")
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
@NotBlank(message = "gender.cannot.be.empty")
|
@NotBlank(message = "gender.cannot.be.empty")
|
||||||
@ApiModelProperty("性别")
|
@Schema(description = "性别")
|
||||||
private String gender;
|
private String gender;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import com.ai.da.mapper.primary.entity.Classification;
|
import com.ai.da.mapper.primary.entity.Classification;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@@ -12,10 +13,10 @@ import java.util.List;
|
|||||||
public class ClassificationDTO extends Classification {
|
public class ClassificationDTO extends Classification {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty("分类ID列表")
|
@Schema(description = "分类ID列表")
|
||||||
private List<Long> classificationIdList;
|
private List<Long> classificationIdList;
|
||||||
@ApiModelProperty("LibraryID")
|
@Schema(description = "LibraryID")
|
||||||
private List<Long> libraryIdList;
|
private List<Long> libraryIdList;
|
||||||
@ApiModelProperty("分类删除校验1:校验0:不校验")
|
@Schema(description = "分类删除校验1:校验0:不校验")
|
||||||
private Integer deleteConfirm;
|
private Integer deleteConfirm;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import com.ai.da.mapper.primary.entity.CloudTask;
|
import com.ai.da.mapper.primary.entity.CloudTask;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class CloudTaskDTO extends CloudTask {
|
public class CloudTaskDTO extends CloudTask {
|
||||||
@ApiModelProperty("toProduct/relight入参")
|
@Schema(description = "toProduct/relight入参")
|
||||||
private ToProductImageDTO toProductImage;
|
private ToProductImageDTO toProductImage;
|
||||||
@ApiModelProperty("posetransfer入参")
|
@Schema(description = "posetransfer入参")
|
||||||
private List<PoseTransformBatchDTO> poseTransform;
|
private List<PoseTransformBatchDTO> poseTransform;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import com.ai.da.mapper.primary.entity.Gradient;
|
import com.ai.da.mapper.primary.entity.Gradient;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("设计Collection颜色板 入参")
|
@Schema(description = "设计Collection颜色板 入参")
|
||||||
public class CollectionColorDTO {
|
public class CollectionColorDTO {
|
||||||
|
|
||||||
@ApiModelProperty("潘通id")
|
@Schema(description = "潘通id")
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@ApiModelProperty("潘通名字")
|
@Schema(description = "潘通名字")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("tcx值")
|
@Schema(description = "tcx值")
|
||||||
private String tcx;
|
private String tcx;
|
||||||
|
|
||||||
@NotBlank(message = "rgbValue.cannot.be.empty")
|
@NotBlank(message = "rgbValue.cannot.be.empty")
|
||||||
@ApiModelProperty("潘通RGB值")
|
@Schema(description = "潘通RGB值")
|
||||||
private String rgbValue;
|
private String rgbValue;
|
||||||
|
|
||||||
private Gradient gradient;
|
private Gradient gradient;
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package com.ai.da.model.dto;
|
package com.ai.da.model.dto;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("删除文件")
|
@Schema(description = "删除文件")
|
||||||
public class CollectionDeleteFileDTO {
|
public class CollectionDeleteFileDTO {
|
||||||
|
|
||||||
@NotNull(message = "file id cannot be empty!")
|
@NotNull(message = "file id cannot be empty!")
|
||||||
@ApiModelProperty("文件id")
|
@Schema(description = "文件id")
|
||||||
private Long id;
|
private Long id;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user