282 Commits

Author SHA1 Message Date
litianxiang
921d2d956e minio缓存 2026-05-20 15:09:26 +08:00
litianxiang
d700f94f9d flux test 2026-05-14 16:36:55 +08:00
litianxiang
b277479e73 豆包模型更换 2026-05-13 20:52:28 +08:00
litianxiang
83cbd57dea 登录鉴权按照Source判断id来自于何处 2026-05-13 09:40:30 +08:00
litianxiang
4d3b22de82 买家端需要的获取商家主页和模糊搜索接口 2026-05-11 16:40:44 +08:00
litianxiang
6b5c2cfec0 日志
订单表字段改名
视频返回新增字段
2026-05-06 16:58:46 +08:00
litianxiang
b676de054a 新工作流 2026-05-06 14:37:42 +08:00
litianxiang
4c169ef67e seller产品图处加入视频 2026-05-06 13:30:21 +08:00
litianxiang
f2bce066b6 seller产品图编辑 2026-05-06 10:46:14 +08:00
litianxiang
6af442eb15 服务端口号与宿主机统一,方便本地调试不需要修改bootstrap 2026-05-04 14:21:35 +08:00
litianxiang
768df55309 服务端口号与宿主机统一,方便本地调试不需要修改bootstrap 2026-05-04 14:19:37 +08:00
litianxiang
f351277b73 nacos注册配置 2026-05-04 10:27:20 +08:00
litianxiang
a799162ea4 工作流 2026-04-28 16:40:56 +08:00
litianxiang
c035eb9d7d bootstrap配置 2026-04-28 14:38:00 +08:00
litianxiang
906a54b3c8 工作流配置 2026-04-28 13:58:46 +08:00
litianxiang
643799546b 工作流配置 2026-04-28 13:42:24 +08:00
litianxiang
f582464cd3 工作流配置 2026-04-28 13:37:47 +08:00
litianxiang
b864b393bc 1 2026-04-28 13:21:12 +08:00
litianxiang
c03a8762e7 商品bug 2026-04-28 09:39:26 +08:00
litianxiang
cb87ad1099 host配置 2026-04-27 16:43:18 +08:00
litianxiang
fb229764f8 host配置 2026-04-27 16:29:54 +08:00
litianxiang
8bec1f842d 工作流配置 2026-04-27 16:10:01 +08:00
litianxiang
b54bd04cff 端口号冲突 2026-04-27 15:00:28 +08:00
litianxiang
b4ccad6242 服务名修改 2026-04-27 14:30:29 +08:00
litianxiang
6068bf7d7d 微服务改造 2026-04-27 13:54:03 +08:00
litianxiang
d36baf747f 微服务改造 2026-04-27 11:47:15 +08:00
7c8f1bee6a 添加 .gitea/workflows/develop_3.1_MS_build_manual.yaml 2026-04-24 13:40:03 +08:00
litianxiang
62bd145e2c 微服务改造 2026-04-23 10:52:49 +08:00
litianxiang
23716984cc 微服务改造 2026-04-22 15:54:42 +08:00
litianxiang
d0b8b8d674 微服务改造 2026-04-22 11:16:03 +08:00
litianxiang
92e7dbf258 微服务改造 2026-04-22 11:15:34 +08:00
litianxiang
32a228485b token保持一致 2026-04-20 10:26:04 +08:00
litianxiang
560e47747a 微服务改造 2026-04-16 15:51:05 +08:00
litianxiang
c8dc38575a Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-04-15 14:52:35 +08:00
litianxiang
c00d906083 portfolioUrl 漏加fix 2026-04-15 14:52:18 +08:00
4df3f9cc53 BUGFIX:design印花scale与getDetail获取到的印花scale不一致 2026-04-15 14:43:59 +08:00
litianxiang
b0343be544 配置过滤器 2026-04-15 14:05:57 +08:00
litianxiang
d33cb9f0bf 配置过滤器 2026-04-15 13:47:28 +08:00
litianxiang
40f2735831 配置过滤器 2026-04-15 13:26:15 +08:00
01d3806d5f Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-04-13 17:52:35 +08:00
107e4e9771 BUGFIX:design 没有使用printboard中的元素 2026-04-13 17:51:15 +08:00
litianxiang
716d720782 GlobalAward返回最大的参赛者编号 2026-04-13 14:38:02 +08:00
litianxiang
6b5bacc49b GlobalAward返回最大的参赛者编号 2026-04-13 14:34:05 +08:00
litianxiang
409bc7b1fd 过滤器配置 2026-04-13 13:09:12 +08:00
litianxiang
ec6a5df8af TO DEV 2026-04-13 11:55:17 +08:00
litianxiang
029b96ae99 GlobalAward下载到浏览器 2026-04-13 11:47:20 +08:00
litianxiang
14002e7331 GlobalAward下载补充和数量接口 2026-04-13 10:22:43 +08:00
14dfe2806c merge dev 2026-04-10 23:27:37 +08:00
798c7b0592 Merge branch 'release/3.1' into dev/3.1_release_merge 2026-04-10 23:09:33 +08:00
9bd10581f4 BUGFIX:获取relight结果时删除了排序记录 2026-04-10 23:03:15 +08:00
1f288fe5e3 BUGFIX 2026-04-10 22:55:44 +08:00
72602eb245 BUGFIX 2026-04-10 22:51:00 +08:00
983d53268d DEBUG 2026-04-10 22:32:55 +08:00
f3aeeb3584 DEBUG 2026-04-10 22:21:56 +08:00
5d3692a204 BUGFIX:支付失败后的邮件通知类型错误(临时处理) 2026-04-08 13:52:38 +08:00
f2a074b2f6 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-03-31 15:19:56 +08:00
6a7a37dcec BUGFIX:只有Printboard时,首次design没有使用元素 2026-03-31 14:12:43 +08:00
litianxiang
c4d2780f0e TO DEV 2026-03-31 13:55:32 +08:00
litianxiang
1da6b7728c Merge remote-tracking branch 'origin/dev/3.1_release_merge' into release/3.1 2026-03-30 17:05:43 +08:00
litianxiang
0faf77899b fix:PRINTBOARD_HIGH_I2I与PRINTBOARD_ADVANCED_I2I使用模型一致导致积分扣除错误 2026-03-27 16:49:10 +08:00
litianxiang
e4940019bf 框选适配py 2026-03-27 15:19:38 +08:00
litianxiang
0da66ff210 print t2i模型替换 2026-03-27 15:16:33 +08:00
litianxiang
5dd862ff79 MOOD_BOARD high 去掉翻译 2026-03-26 16:13:43 +08:00
litianxiang
edaec9884d TO PROD 2026-03-25 22:28:44 +08:00
litianxiang
76eeb2be53 moodboard基础模型修改 2026-03-25 10:39:22 +08:00
litianxiang
cb6f94d2d4 py api fix 2026-03-25 10:19:06 +08:00
litianxiang
28656c44c8 FIX FLUX2 2026-03-24 16:24:43 +08:00
litianxiang
6757a89d04 Pattern模式参数fix 2026-03-24 15:54:53 +08:00
litianxiang
9be1a1e307 加锁解决不同线程读取前还未保存的问题 2026-03-24 15:49:16 +08:00
litianxiang
2168978f61 print pattern也改为flux2 2026-03-24 15:32:06 +08:00
litianxiang
54466b935d debug 2026-03-24 15:23:33 +08:00
litianxiang
c970ebe691 debug 2026-03-24 15:15:59 +08:00
litianxiang
1c5a3a12b9 debug 2026-03-24 15:04:40 +08:00
litianxiang
6e06000083 debug 2026-03-24 14:46:01 +08:00
litianxiang
dea2b3be42 debug 2026-03-24 14:29:08 +08:00
litianxiang
bcf51aea23 debug 2026-03-24 14:20:39 +08:00
litianxiang
0c9d5404c6 flux2失败状态判断 2026-03-24 14:05:27 +08:00
litianxiang
93429839c0 本地flux改为flux2 2026-03-24 13:39:38 +08:00
litianxiang
27859c3e28 Merge remote-tracking branch 'origin/release/3.1' into dev/3.1_release_merge 2026-03-23 14:11:33 +08:00
litianxiang
f02c0930a6 日志切面(controller层报错打印) 2026-03-23 13:56:47 +08:00
litianxiang
d57bb83b25 Merge remote-tracking branch 'origin/release/3.1' into release/3.1 2026-03-23 13:50:44 +08:00
731e34f133 TO DEV 2026-03-23 13:38:10 +08:00
75eca8d6ba Merge branch 'release/3.1' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/python/PythonService.java
2026-03-23 13:22:18 +08:00
3e53401f76 TASK:返回符合查询条件的金额总计 2026-03-23 11:55:07 +08:00
litianxiang
b6a068ebcd SKETCHBOARD传入的text改为获取第一个,为分割获取style的方式 2026-03-23 11:50:24 +08:00
litianxiang
dc291ea086 加入非空校验 2026-03-14 01:50:39 +08:00
litianxiang
2e846e671a romantic风格缺少下装fix 2026-03-13 10:06:26 +08:00
litianxiang
a5093311f9 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 19:06:54 +08:00
litianxiang
aed338a6d7 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:59:17 +08:00
litianxiang
8bdb49d25c 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:49:57 +08:00
litianxiang
5d53a8cd42 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:49:28 +08:00
litianxiang
61b7f3072f 当style为洛丽塔时无sketch和谷歌风控问题FIX 2026-03-12 18:36:21 +08:00
litianxiang
a1f489f3a1 比赛url修改 2026-03-12 17:39:05 +08:00
litianxiang
fc3fd877a8 transpose和rotate获取位置修改 2026-03-05 16:58:17 +08:00
litianxiang
fc72d2c430 transpose和rotate获取位置修改 2026-03-05 13:29:14 +08:00
litianxiang
1ac01dd090 测试token恢复 2026-02-25 16:36:06 +08:00
litianxiang
3bbdf7c672 fix:按编号导出参赛选手文件 2026-02-09 10:33:25 +08:00
litianxiang
0646484fba 按编号导出参赛选手文件 2026-02-09 10:21:40 +08:00
litianxiang
96b8613741 映射temp到服务器 2026-02-06 17:29:42 +08:00
litianxiang
cf30226a51 映射temp到服务器 2026-02-06 17:24:43 +08:00
litianxiang
3c15a3ff68 映射temp到服务器 2026-02-06 17:21:07 +08:00
litianxiang
0c904be227 测试临时token 2026-02-06 11:42:34 +08:00
litianxiang
7759b56123 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-02-05 17:39:15 +08:00
litianxiang
d5bfaa8822 fix:允许图生图不带提示词 2026-02-05 17:38:38 +08:00
967c0cbc01 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-02-05 16:55:24 +08:00
417e34b41a BUGFIX:1.首次design没有使用library和生成的印花2.design overall印花太小 2026-02-05 16:54:45 +08:00
litianxiang
d51aa84647 fix:参赛者根据链接返回文件参数 2026-02-05 09:41:10 +08:00
litianxiang
5895bc6ab6 Revert "fix:参赛者根据链接返回文件参数"
This reverts commit 3301869f20.
2026-02-05 09:40:35 +08:00
litianxiang
3301869f20 fix:参赛者根据链接返回文件参数 2026-02-05 09:40:15 +08:00
litianxiang
1ec42f4ad5 fix:参赛者id逻辑更改 2026-02-04 17:20:22 +08:00
cc506ff7e9 Merge branch 'dev/3.1_release_merge' into release/3.1 2026-02-04 17:05:59 +08:00
litianxiang
f2d43f06f4 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-02-04 15:28:08 +08:00
litianxiang
9251df49f8 比赛新增文件大小和视频时长 2026-02-04 15:27:51 +08:00
430156f4e8 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-02-04 14:48:38 +08:00
litianxiang
d1123aedcc fix:导出为页面下载 2026-02-04 14:45:11 +08:00
8c007077a3 BUGFIX: detail中的merge模式下没有存储partialDesign的图片 2026-02-04 14:43:29 +08:00
litianxiang
d63b4b4e63 fix:参赛选手加入编号 2026-02-04 14:03:30 +08:00
litianxiang
b826f0bf39 参赛选手加入编号,增加导出功能 2026-02-04 13:41:16 +08:00
litianxiang
1decd8e258 参赛选手加入编号,增加导出功能 2026-02-04 13:41:09 +08:00
litianxiang
1286e84488 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx 2026-02-04 13:21:19 +08:00
a252fdf7f9 BUGFIX: detail中的default模式报错 2026-02-03 16:56:15 +08:00
807d802178 TASK:motion 参数数据类型变更 2026-02-02 15:30:04 +08:00
53f1b548be CONFIG 2026-02-02 15:28:54 +08:00
45dd78032a BUGFIX: 1.token过期,重新登录无法解决 2.motion生成参数数据类型变更 2026-02-02 15:04:27 +08:00
c160da5132 BUGFIX: token过期,重新登录无法解决 2026-02-02 14:57:32 +08:00
b23faeeee2 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-02-02 13:32:55 +08:00
67789abca4 TASK:getAllPose id的数据类型改为整型 2026-02-02 13:32:27 +08:00
1c78d66aab Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-30 17:14:50 +08:00
528bc69923 BUGFIX: design single merge模式下取消传递print及elements等元素 2026-01-30 17:10:37 +08:00
litianxiang
22880d128d Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx 2026-01-30 15:40:25 +08:00
9c56a102cc Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-29 14:38:20 +08:00
2f59fe074f BUGFIX: 管理员修改用户身份为游客 2026-01-29 14:37:54 +08:00
9c61b1c8fe Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-29 10:12:47 +08:00
e30fdf7401 BUGFIX:模特上传,事务管理不统一导致library出现孤儿数据 2026-01-29 10:10:21 +08:00
ba2d10afbc paymentMethodConfiguration切换 2026-01-28 15:41:52 +08:00
6146112d04 TO PROD 2026-01-27 16:39:39 +08:00
412550df27 BUGFIX:管理员查design频次与chart中获取到的数量有区别 2026-01-27 14:59:39 +08:00
497421e7fe TO DEV 2026-01-27 10:15:36 +08:00
891527426c Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/service/impl/DesignServiceImpl.java
2026-01-26 14:49:38 +08:00
litianxiang
3e334d7956 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx 2026-01-26 11:16:46 +08:00
litianxiang
8f0d0953b2 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-01-26 11:15:38 +08:00
f5c3621a5d bugfix: design like 2026-01-23 22:45:40 +08:00
litianxiang
9a1a0045e0 fix:like报错 2026-01-23 22:40:30 +08:00
6223c8e994 brandDNA 2026-01-23 22:25:01 +08:00
67bbee49fd Merge branch 'dev/3.1_release_merge' into release/3.1 2026-01-23 21:20:26 +08:00
ad62ceb32a Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-23 21:02:04 +08:00
082afe9e94 gradiant 置空 2026-01-23 20:57:48 +08:00
49288c3a31 TO Prod 2026-01-23 16:10:55 +08:00
81624e36db Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-01-23 15:12:15 +08:00
a526b122d1 Merge branch 'release/3.1' into dev/3.1_release_merge 2026-01-23 15:11:45 +08:00
litianxiang
d882b2e817 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-23 15:05:22 +08:00
litianxiang
ebf6427d42 fix:用户特征存入逻辑错误 2026-01-23 15:04:59 +08:00
77fe03d361 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-23 11:46:31 +08:00
7a44d67dbf BUGFIX: 系统消息发布 广播时消息数量错误 2026-01-23 11:46:08 +08:00
55ce2c6c7e Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-23 10:54:35 +08:00
a426caaca3 BUGFIX: 系统消息发布 2026-01-23 10:54:03 +08:00
7cb7ce2836 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-22 16:56:11 +08:00
8e075f1da4 BUGFIX: 通过hsv批量获取潘通信息,替换rgb 2026-01-22 16:55:00 +08:00
litianxiang
0f0fde2a3e Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-22 14:28:37 +08:00
litianxiang
8c6389a1f6 删除不用的字段 2026-01-22 14:28:10 +08:00
652f82b6a4 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-22 13:56:44 +08:00
7ca2528dcf BUGFIX: design后未存储undivided layers 2026-01-22 13:56:07 +08:00
litianxiang
a7800913d2 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-22 13:51:42 +08:00
litianxiang
1eaec64ff4 fix:GlobalAward读取配置错误 2026-01-22 13:51:13 +08:00
e603952332 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-22 11:37:25 +08:00
2bc8b8ef96 BUGFIX: single design的渐变色未存储 2026-01-22 11:36:43 +08:00
0ce968b919 BUGFIX: 用户登录时的有效期验证异常抛出导致事务回滚,用户信息修改失败 2026-01-22 10:37:23 +08:00
litianxiang
dfc9ae4db2 GlobalAward站内信url修改 2026-01-21 16:50:01 +08:00
litianxiang
a3505c6d95 GlobalAward站内信url修改 2026-01-21 15:09:45 +08:00
litianxiang
6db0afd515 GlobalAward保存成功发送站内信,根据url可跳转且召回已填写资料 2026-01-21 14:59:41 +08:00
litianxiang
b1e6183dd1 GlobalAward接口token验证,id更换为uuid 2026-01-21 14:34:43 +08:00
30d08356c0 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-21 14:14:17 +08:00
64cc29f456 TASK:Global Award邮箱验证 2026-01-21 14:13:33 +08:00
litianxiang
2b3e12a11c GlobalAward MINIO配置 2026-01-21 11:38:38 +08:00
litianxiang
d4a4724f61 GlobalAward拦截器配置 2026-01-21 10:35:22 +08:00
litianxiang
ba6e2bd24c GlobalAward拦截器配置 2026-01-21 10:21:17 +08:00
litianxiang
a38895b028 GlobalAward拦截器配置 2026-01-21 10:13:11 +08:00
litianxiang
69a95e66ca GlobalAward上传文件 2026-01-20 16:37:46 +08:00
litianxiang
40518cab37 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev-ltx
# Conflicts:
#	src/main/java/com/ai/da/controller/GlobalAwardController.java
#	src/main/java/com/ai/da/model/dto/ContestantDTO.java
#	src/main/resources/application-dev.properties
#	src/main/resources/application-prod.properties
2026-01-20 16:20:41 +08:00
litianxiang
46d61cb73f GlobalAward上传文件 2026-01-20 15:58:27 +08:00
08f20fd1fe Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-20 13:24:49 +08:00
d7edc166b3 TASK:Global Award邮箱验证 2026-01-20 13:14:50 +08:00
litianxiang
79ad02f66b fix:style为all时,like报错 2026-01-19 16:50:14 +08:00
litianxiang
5e261b55c7 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-01-19 16:41:02 +08:00
litianxiang
bc92fcbaf4 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-19 16:40:58 +08:00
litianxiang
c6aec917c2 fix:style为all时,like报错 2026-01-19 16:40:28 +08:00
6bc500e78f Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-16 17:17:25 +08:00
4c43b98c02 TASK:DB中PartialDesign为空时,取undivided_layer作为merge_image_path 2026-01-16 17:17:04 +08:00
litianxiang
5bae785a9f Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-16 16:37:49 +08:00
litianxiang
7b619aa4cb GlobalAward首次提交 2026-01-16 16:37:03 +08:00
c93ad6daa9 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-16 16:24:38 +08:00
0047be7a03 BUGFIX:PartialDesign传空时,先从数据库获取原数据 2026-01-16 16:23:56 +08:00
4ef209cfd4 Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-16 14:28:27 +08:00
a19751b4b7 BUGFIX:designType参数校验;print数据验空 2026-01-16 14:28:04 +08:00
litianxiang
bb0e5a4263 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-16 11:04:52 +08:00
litianxiang
9e9df5367d fix:接口SegAnything返回值处理 2026-01-16 11:04:18 +08:00
ba8a2c52de Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2026-01-15 17:36:37 +08:00
39d8c7efcf TASK:取消存储/返回UndividedLayer和UndividedLayerWithSinglePrint字段 2026-01-15 17:35:55 +08:00
litianxiang
401910901a Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/python/PythonService.java
2026-01-15 17:21:30 +08:00
litianxiang
3f5ce6e0e7 接口SegAnything返回值处理 2026-01-15 17:17:08 +08:00
0787025151 TASK:merge 模式返回mask 2026-01-15 14:07:18 +08:00
08b26872ff Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2026-01-14 14:28:05 +08:00
5bbf1326bb TASK:design single部分cv操作前置,新增merge | default两种designType 2026-01-14 14:26:47 +08:00
litianxiang
c5e27cd220 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-14 13:55:01 +08:00
litianxiang
112e9c3bc9 对接前端和py接口SegAnything 2026-01-14 13:31:33 +08:00
litianxiang
ce95cb5080 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-12 14:42:02 +08:00
litianxiang
71211bfbc3 修改存入userPreference表的时间方式 2026-01-12 14:41:24 +08:00
72ad977dcb BUGFIX: 获取近期新用户图表数据允许userType为null 2026-01-12 11:55:43 +08:00
litianxiang
6400e79929 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2026-01-09 14:49:25 +08:00
litianxiang
dd8c72f7d7 切换用户sketch点赞记录存储方式;新增镜像和角度字段,存储前端需要的object 2026-01-09 10:14:46 +08:00
13151b65f5 TASK:限制同一个管理员不允许绑定不同组织的订阅计划 2026-01-07 15:24:38 +08:00
9f523d5953 TASK:分页获取所有用户id,添加按邮箱模糊查询 2026-01-07 11:26:39 +08:00
4879cfeb60 BUGFIX: 2026-01-07 09:53:58 +08:00
9e252b16ef BUGFIX: 2026-01-06 17:36:12 +08:00
e64add14af BUGFIX:更新订阅计划时根据业务需要对参数进行判断并在需要时更新管理员信息 2026-01-06 17:29:33 +08:00
3beb27e491 TASK:获取用户id信息做分页;订阅计划添加国家或地区字段 2026-01-06 09:56:21 +08:00
501032ef17 TASK:试用用户试用期延长至7天 2025-12-31 13:15:13 +08:00
litianxiang
cb25bdd2e0 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2025-12-29 14:57:41 +08:00
litianxiang
7a9fb0213b 适配新推荐接口 2025-12-29 13:49:31 +08:00
cd767dce6f BUGFIX:新用户不能获取历史系统通知 2025-12-24 11:47:11 +08:00
bf95b85841 to dev 2025-12-23 16:28:07 +08:00
9e58bd9e7d Merge branch 'release/3.1' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/common/utils/SendRequestUtil.java
2025-12-23 16:16:30 +08:00
d0ec5c5c26 BUGFIX:邮件发送失败 2025-12-23 16:03:48 +08:00
ab8aa5ea5c Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2025-12-23 14:07:53 +08:00
aefcd2fdb0 BUGFIX:邮件发送失败 2025-12-23 14:07:26 +08:00
e74eab1070 BUGFIX:邮件发送失败 2025-12-23 14:05:20 +08:00
litianxiang
34da437a26 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2025-12-22 11:36:23 +08:00
litianxiang
f84935d0bd 登录token存入redis 2025-12-22 11:35:38 +08:00
35edaa0f27 CONFIG: 拦截器配置 2025-12-19 21:43:02 +08:00
f43099e19e CONFIG: redis 配置修改 2025-12-19 21:21:21 +08:00
8079877734 CONFIG: TO DEV 2025-12-19 17:40:37 +08:00
ef686e38ac CONFIG: TO PROD 2025-12-19 17:33:51 +08:00
100019d2a4 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2025-12-19 16:00:55 +08:00
litianxiang
12af237d76 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2025-12-19 15:47:36 +08:00
litianxiang
44dbbb2a4b 更换Moodboard和Printboard提示词 2025-12-19 15:47:07 +08:00
9f42e153a4 Merge branch 'release/3.1' into dev/3.1_release_merge
# Conflicts:
#	.gitea/workflows/develop_build_manual.yaml
2025-12-19 15:01:32 +08:00
4fa70a1c90 BUGFIX:订阅计划创建不允许指定子账号为管理员 2025-12-18 18:03:03 +08:00
dfb34916e7 BUGFIX:订阅计划与子账号新增 2025-12-18 14:52:12 +08:00
9f7987306c BUGFIX:订阅计划 2025-12-18 13:38:38 +08:00
litianxiang
d3fc70fbf2 fix:edit产品图照成排序问题,恢复原逻辑 2025-12-17 16:08:49 +08:00
litianxiang
17645d17e5 关闭batch MQ监听 2025-12-17 16:02:49 +08:00
litianxiang
258eea5277 edit 产品图失败会导致sort不对试验5 2025-12-17 15:43:26 +08:00
litianxiang
bb1d3bd359 Revert "edit 产品图失败会导致sort不对试验5"
This reverts commit 6a8c87ed95.
2025-12-17 15:41:02 +08:00
litianxiang
6a8c87ed95 edit 产品图失败会导致sort不对试验5 2025-12-17 15:40:47 +08:00
litianxiang
eb3826927d edit 产品图失败会导致sort不对试验4 2025-12-17 15:33:14 +08:00
litianxiang
7720c8c771 edit 产品图失败会导致sort不对试验3 2025-12-17 14:12:20 +08:00
litianxiang
b459148d58 edit 产品图失败会导致sort不对试验2 2025-12-17 13:49:07 +08:00
litianxiang
eadda18d1e Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2025-12-17 13:28:12 +08:00
litianxiang
d403df51ec edit 产品图失败会导致sort不对试验 2025-12-17 13:28:04 +08:00
6903b98b60 Merge remote-tracking branch 'origin/dev/3.1_release_merge' into dev/3.1_release_merge 2025-12-17 13:20:34 +08:00
81bf65515c Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2025-12-17 13:19:54 +08:00
8e984eb283 BUGFIX:订阅计划 2025-12-17 13:18:24 +08:00
litianxiang
afc6041570 临时测试修改 2025-12-17 13:10:09 +08:00
bce368248c Merge branch 'dev/dev_xp' into dev/3.1_release_merge 2025-12-16 16:26:27 +08:00
ca7121dcda BUGFIX:订阅计划 2025-12-16 16:24:52 +08:00
litianxiang
9a206f9979 生产环境配置callbackUrl 2025-12-16 14:10:22 +08:00
litianxiang
eb7a46c7e8 fix:callbackUrl 2025-12-16 13:45:21 +08:00
litianxiang
95ef68a784 Merge remote-tracking branch 'origin/dev-ltx' into dev/3.1_release_merge 2025-12-16 13:20:31 +08:00
litianxiang
6429288fd9 dev环境加入design回调配置 2025-12-16 13:16:36 +08:00
c5af194876 BUGFIX 2025-12-16 10:42:31 +08:00
da84e1e4b4 注解修改 2025-12-15 18:39:16 +08:00
95a9c81a1b Merge branch 'dev/dev_xp' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/model/dto/SubscriptionPlanDTO.java
#	src/main/java/com/ai/da/model/vo/SubscriptionPlanVO.java
2025-12-15 18:34:30 +08:00
81c0d7eeac TASK:订阅计划相关 2025-12-15 18:30:28 +08:00
litianxiang
fbc473735c fix:对没有like的已发布作品进行二创,会不显示原作者名字 2025-12-15 15:41:58 +08:00
litianxiang
9f48a2ce09 fix:升级swagger注解 2025-12-15 13:38:44 +08:00
459c743ce4 CONFIG: 2025-12-11 16:58:24 +08:00
ce3516916d CONFIG: 2025-12-11 16:18:37 +08:00
0692b29065 Merge branch 'dev/dev_xp' into dev/3.1_release_merge
# Conflicts:
#	src/main/java/com/ai/da/controller/AccountController.java
2025-12-11 16:12:41 +08:00
94cafbd10c TASK:flux积分不足,邮件通知 2025-12-11 16:07:14 +08:00
5c2008ec4a TASK:订阅计划,测试修改 2025-12-11 15:26:20 +08:00
7f094265da TASK:新增订阅计划概念 2025-12-11 09:44:25 +08:00
22bc8750c8 Merge branch 'dev-ltx' into dev/dev_xp 2025-12-03 16:53:17 +08:00
6cd42b799a 删除 .gitea/workflows/prod_build_schedule.yaml 2025-12-01 10:22:29 +08:00
6e1ed7f9b8 删除 .gitea/workflows/prod_build_manual.yaml 2025-12-01 10:22:25 +08:00
b7be16738b 删除 .gitea/workflows/develop_build_manual.yaml 2025-12-01 10:22:21 +08:00
6da5e91ec1 删除 .gitea/workflows/develop_build_commit.yaml 2025-12-01 10:22:17 +08:00
a710fdd432 删除 docker-compose.yml 2025-11-30 11:01:12 +08:00
d598f53d3c Merge branch 'dev/3.1_release_merge' into release/3.1
# Conflicts:
#	.gitea/workflows/prod_build_schedule.yaml
2025-11-28 17:16:55 +08:00
96170a9956 更新 .gitea/workflows/prod_build_manual.yaml 2025-11-28 15:25:50 +08:00
8205fb5290 上传文件至「.gitea/workflows」 2025-11-28 15:25:41 +08:00
fcbe4762b3 TO prod 2025-11-27 17:38:24 +08:00
e750adcc94 TO prod 2025-11-27 17:35:47 +08:00
283 changed files with 17293 additions and 12401 deletions

View 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

View File

@@ -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
View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.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>

View File

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

View File

@@ -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);
} // }
} }

View File

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

View File

@@ -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");
} // }
} }

View File

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

View File

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

View 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 配置。
* 由于鉴权逻辑已迁移至 GatewayGlobalAuthWebFilter
* 后端服务 (aida-back) 默认放行所有请求,仅依赖网关传递的用户信息。
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 禁用 CSRF微服务通常不需要
.csrf(AbstractHttpConfigurer::disable)
// 允许所有请求,具体鉴权在网关层完成
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
)
// 禁用默认的表单登录和 HTTP Basic 认证,防止 302 重定向
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable);
return http.build();
}
}

View File

@@ -1,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)

View File

@@ -4,11 +4,13 @@ import com.ai.da.common.response.Response;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.ai.da.common.response.ResultEnum; import com.ai.da.common.response.ResultEnum;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/** /**
* @author: dangweijian * @author: dangweijian
@@ -36,6 +38,14 @@ public class ExceptionCatch {
return Response.error(e.getCode(), e.getMsg()); return Response.error(e.getCode(), e.getMsg());
} }
@ResponseBody
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(UnauthorizedException.class)
public Response<String> unauthorizedExceptionCatch(UnauthorizedException e) {
log.error("Unauthorized: {}", e.getMessage());
return Response.error(401, e.getMessage());
}
@ResponseBody @ResponseBody
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public Response<String> exceptionCatch(Exception e) { public Response<String> exceptionCatch(Exception e) {

View File

@@ -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;
}
}

View File

@@ -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");
}
}

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";
}

View File

@@ -3,17 +3,39 @@ 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 void setUserHolder(AuthPrincipalVo authPrincipalVo) {
userHolder.set(authPrincipalVo);
}
public static AuthPrincipalVo getUserHolder() { public static AuthPrincipalVo getUserHolder() {
return userHolder.get(); AuthPrincipalVo holder = userHolder.get();
if (holder == null) {
throw new RuntimeException("User not authenticated");
}
if (!"AIDA".equals(holder.getSource())) {
throw new RuntimeException("Access denied: source must be AIDA");
}
return holder;
} }
public static void delete() { public static void delete() {
userHolder.remove(); userHolder.remove();
} }
public static void setUserHolder(AuthPrincipalVo authPrincipalVo) { public static Long getUserId() {
userHolder.set(authPrincipalVo); 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();
} }
} }

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
} }

View File

@@ -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()){

View File

@@ -45,7 +45,7 @@ public class PaymentTask {
@Resource @Resource
private PayPalCheckoutService payPalCheckoutService; private PayPalCheckoutService payPalCheckoutService;
// @Scheduled(cron = "0/30 * * * * ?") // @Scheduled(cron = "0/30 * * * * ?")
public void orderConfirmForPaypal() throws SerializeException { public void orderConfirmForPaypal() throws SerializeException {
// log.info("PayPal orderConfirm 被执行......"); // log.info("PayPal orderConfirm 被执行......");
@@ -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();

View File

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

View File

@@ -3,7 +3,6 @@ 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;
@@ -35,7 +34,8 @@ public class MailUtil {
* 发送邮件 - 默认发件人 * 发送邮件 - 默认发件人
* *
* @param basicEmailParamDTO 发送邮件所需参数 * @param basicEmailParamDTO 发送邮件所需参数
* @param inputStreamSource 附件(如果有) * @param fileName 附件(如果有)
* @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);
@@ -62,36 +62,29 @@ public class MailUtil {
} }
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 // 配置连接属性
transport = (SMTPTransport) mimeMessage.getSession().getTransport("smtp"); java.util.Properties props = mimeMessage.getSession().getProperties();
// 连接到 SMTP 服务器 props.put("mail.smtp.auth", "true");
transport.connect(host, username, password); props.put("mail.smtp.host", host);
// 发送邮件 props.put("mail.user", username);
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); props.put("mail.password", password);
// 获取 SMTP 服务器的响应
String lastServerResponse = transport.getLastServerResponse();
int lastReturnCode = transport.getLastReturnCode();
log.info("SMTP 状态码: {}, SMTP 服务器响应: {}", lastReturnCode, lastServerResponse); // 使用 JavaMailSender 发送邮件Spring Boot 3.x 标准方式)
return lastReturnCode; javaMailSender.send(mimeMessage);
} catch (MailException | MessagingException e) { log.info("邮件发送成功至: {}", host);
// 记录日志或执行其他补偿逻辑 return 1;
} catch (MailException e) {
log.info("邮件发送失败:{}", e.getMessage()); log.info("邮件发送失败:{}", e.getMessage());
} finally { return 0;
// 关闭连接
assert transport != null;
transport.close();
} }
return 0;
} }
/** /**
* 创建一封邮件 * 创建一封邮件
* *
* @param basicEmailParamDTO 创建邮件需要的参数 * @param basicEmailParamDTO 创建邮件需要的参数
* @param inputStreamSource 附件(如果有) * @param inputStreamSource 附件(如果有)
* @return 一封邮件 * @return 一封邮件
*/ */
private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException { private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {

View File

@@ -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表示是预签名URLfalse表示不是
*/
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或逻辑路径");
}
}
} }

View File

@@ -34,6 +34,11 @@ public class RedisUtil {
private RedisTemplate<String, String> redisTemplate; private RedisTemplate<String, String> redisTemplate;
public final static String FLUX_POLLING_URL = "Flux:"; public final static String FLUX_POLLING_URL = "Flux:";
/**
* 登录 token 在 Redis 中的前缀:
* 最终 key 结构为 login:token:{userId}
*/
public final static String LOGIN_TOKEN_KEY = "login:token:";
public Boolean hasKey(String key){ public Boolean hasKey(String key){
return redisTemplate.hasKey(key); return redisTemplate.hasKey(key);
@@ -186,6 +191,40 @@ public class RedisUtil {
redisTemplate.delete(key); redisTemplate.delete(key);
} }
/**
* 保存登录 token
*
* @param userId 用户 ID
* @param token token 字符串
* @param expireMillis 过期时间(毫秒,通常与 JWT 保持一致)
*/
public void setLoginToken(Long userId, String token, long expireMillis) {
if (expireMillis <= 0) {
// 不设置过期时间,直到手动删除(不推荐)
addToString(LOGIN_TOKEN_KEY + userId, token);
return;
}
long expireSeconds = expireMillis / 1000;
if (expireSeconds <= 0) {
expireSeconds = 1;
}
addToString(LOGIN_TOKEN_KEY + userId, token, expireSeconds);
}
/**
* 获取登录 token
*/
public String getLoginToken(Long userId) {
return getFromString(LOGIN_TOKEN_KEY + userId);
}
/**
* 删除登录 token
*/
public void deleteLoginToken(Long userId) {
removeFromString(LOGIN_TOKEN_KEY + userId);
}
public final static String PORTFOLIO_LIKE_KEY = "portfolio:like:"; public final static String PORTFOLIO_LIKE_KEY = "portfolio:like:";
public void likePost(Long portfolioId, Long userId) { public void likePost(Long portfolioId, Long userId) {

View File

@@ -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;
}
}

View File

@@ -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");
} }
} }

View File

@@ -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){

View 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 生成工具类(仅负责生成,不负责鉴权)。
* 鉴权逻辑已迁移至 GatewayGlobalAuthWebFilter
*/
@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);
}
}

View File

@@ -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 = "将用户账号过期时间设置为过期当天的235959") @Operation(summary = "将用户账号过期时间设置为过期当天的235959")
@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));
} }

View File

@@ -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 = "获取所有交易信息")

View 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());
}
}

View File

@@ -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);
}
} }

View File

@@ -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);
} }

View File

@@ -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();
}
}

View File

@@ -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);
}

View 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);
}

View 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> {
}

View File

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

View File

@@ -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);
} }

View File

@@ -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);
}

View File

@@ -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> {
}

View File

@@ -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);
} }

View File

@@ -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;

View File

@@ -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;
}
}
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
}

View File

@@ -62,4 +62,9 @@ public class DesignItemDetailPrint {
* 更新时间 * 更新时间
*/ */
private LocalDateTime updateDate; private LocalDateTime updateDate;
/**
* 对象信息JSON格式
*/
private String object;
} }

View File

@@ -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 {
// 该条作品是否在该组织公开 默认公开 10为不公开 // 该条作品是否在该组织公开 默认公开 10为不公开
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;
} }

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
/** /**

View File

@@ -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;
}

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -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