Commit 5913ee0706279aafa91da20d42738e024ae9e91e

Authored by YunaiV
2 parents eeb8873b f088fdff

Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/mall_product

# Conflicts:
#	yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
#	yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityDetailRespVO.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityRespVO.java
#	yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
#	yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
#	yudao-server/src/main/resources/application-local.yaml
Showing 574 changed files with 2002 additions and 47715 deletions

Too many changes.

To preserve performance only 100 of 574 files are displayed.

README.md
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 * 启动文档:<https://doc.iocoder.cn/quick-start/> 15 * 启动文档:<https://doc.iocoder.cn/quick-start/>
16 * 视频教程:<https://doc.iocoder.cn/video/> 16 * 视频教程:<https://doc.iocoder.cn/video/>
17 17
  18 +已支持 Spring Boot 3.X + JDK 17 版本,可见 [master-boot3](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/README.md) 分支。
  19 +
18 ## 🐯 平台简介 20 ## 🐯 平台简介
19 21
20 **芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。 22 **芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
@@ -62,18 +64,18 @@ @@ -62,18 +64,18 @@
62 | [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 | 64 | [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 |
63 | [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 | 65 | [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 |
64 | [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | 66 | [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 |
65 -| [yudao-ui-app](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-app) | 基于 uni-app + uview 实现的用户 App | 67 +| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 |
66 68
67 ## 🐰 分支说明 69 ## 🐰 分支说明
68 70
69 | | JDK 8 完整版 | JDK 8 精简版 | JDK 17 完整版 | 71 | | JDK 8 完整版 | JDK 8 精简版 | JDK 17 完整版 |
70 |-------|-----------------------------------------------------------|--------------------------------------------------------------------|-----------------------------------------------------------------------------| 72 |-------|-----------------------------------------------------------|--------------------------------------------------------------------|-----------------------------------------------------------------------------|
71 -| 分支 | [`master`](https://gitee.com/zhijiantianya/ruoyi-vue-pro) | [`mini`](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/mini/) | [`boot-dev`](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/boot3-dev/) | 73 +| 分支 | [`master`](https://gitee.com/zhijiantianya/ruoyi-vue-pro) | [`mini`](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/mini/) | [`master-boot3`](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master-boot3/) |
72 | 说明 | 包括所有功能 | 只保留核心功能 | 适配 Spring Boot 3.X | 74 | 说明 | 包括所有功能 | 只保留核心功能 | 适配 Spring Boot 3.X |
73 | 系统功能 | √ | √ | √ | 75 | 系统功能 | √ | √ | √ |
74 | 基础设施 | √ | √ | √ | 76 | 基础设施 | √ | √ | √ |
75 | 会员中心 | √ | √ | √ | 77 | 会员中心 | √ | √ | √ |
76 -| 工作流程 | √ | x | 适配中 | 78 +| 工作流程 | √ | x | √ |
77 | 数据报表 | √ | x | 适配中 | 79 | 数据报表 | √ | x | 适配中 |
78 | 商城系统 | √ | x | √ | 80 | 商城系统 | √ | x | √ |
79 | 微信公众号 | √ | x | √ | 81 | 微信公众号 | √ | x | √ |
@@ -218,6 +220,10 @@ @@ -218,6 +220,10 @@
218 220
219 ![功能图](/.image/common/mall-preview.png) 221 ![功能图](/.image/common/mall-preview.png)
220 222
  223 +_前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋道快速开发平台_
  224 +
  225 +演示地址:<https://doc.iocoder.cn/mall-preview/>
  226 +
221 ### 会员中心 227 ### 会员中心
222 228
223 | | 功能 | 描述 | 229 | | 功能 | 描述 |
@@ -248,29 +254,29 @@ @@ -248,29 +254,29 @@
248 254
249 ### 框架 255 ### 框架
250 256
251 -| 框架 | 说明 | 版本 | 学习指南 |  
252 -|---------------------------------------------------------------------------------------------|------------------|-------------|----------------------------------------------------------------|  
253 -| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.14 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |  
254 -| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |  
255 -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.18 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |  
256 -| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |  
257 -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |  
258 -| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |  
259 -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |  
260 -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |  
261 -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.6 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |  
262 -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |  
263 -| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) |  
264 -| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |  
265 -| [Springdoc](https://springdoc.org/) | Swagger 文档 | 1.6.15 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |  
266 -| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |  
267 -| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |  
268 -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |  
269 -| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |  
270 -| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.5.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |  
271 -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.28 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |  
272 -| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |  
273 -| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - | 257 +| 框架 | 说明 | 版本 | 学习指南 |
  258 +|---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------|
  259 +| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.16 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
  260 +| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
  261 +| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.19 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
  262 +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
  263 +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
  264 +| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 /7.0 | |
  265 +| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
  266 +| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
  267 +| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.11 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
  268 +| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
  269 +| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) |
  270 +| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
  271 +| [Springdoc](https://springdoc.org/) | Swagger 文档 | 1.6.15 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
  272 +| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
  273 +| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
  274 +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
  275 +| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
  276 +| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.5.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
  277 +| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.30 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
  278 +| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
  279 +| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
274 280
275 ## 🐷 演示图 281 ## 🐷 演示图
276 282
@@ -19,8 +19,8 @@ @@ -19,8 +19,8 @@
19 <!-- <module>yudao-module-bpm</module>--> 19 <!-- <module>yudao-module-bpm</module>-->
20 <!-- <module>yudao-module-report</module>--> 20 <!-- <module>yudao-module-report</module>-->
21 <!-- <module>yudao-module-mp</module>--> 21 <!-- <module>yudao-module-mp</module>-->
22 - <module>yudao-module-pay</module>  
23 - <module>yudao-module-mall</module> 22 +<!-- <module>yudao-module-pay</module>-->
  23 +<!-- <module>yudao-module-mall</module>-->
24 <!-- 示例项目 --> 24 <!-- 示例项目 -->
25 <module>yudao-example</module> 25 <module>yudao-example</module>
26 </modules> 26 </modules>
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 30 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
31 31
32 <properties> 32 <properties>
33 - <revision>1.8.1-snapshot</revision> 33 + <revision>1.8.2-snapshot</revision>
34 <!-- Maven 相关 --> 34 <!-- Maven 相关 -->
35 <java.version>1.8</java.version> 35 <java.version>1.8</java.version>
36 <maven.compiler.source>${java.version}</maven.compiler.source> 36 <maven.compiler.source>${java.version}</maven.compiler.source>
@@ -39,8 +39,8 @@ @@ -39,8 +39,8 @@
39 <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> 39 <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
40 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> 40 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
41 <!-- 看看咋放到 bom 里 --> 41 <!-- 看看咋放到 bom 里 -->
42 - <lombok.version>1.18.28</lombok.version>  
43 - <spring.boot.version>2.7.14</spring.boot.version> 42 + <lombok.version>1.18.30</lombok.version>
  43 + <spring.boot.version>2.7.16</spring.boot.version>
44 <mapstruct.version>1.5.5.Final</mapstruct.version> 44 <mapstruct.version>1.5.5.Final</mapstruct.version>
45 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 45 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
46 </properties> 46 </properties>
sql/mysql/ruoyi-vue-pro.sql
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 Target Server Version : 80034 11 Target Server Version : 80034
12 File Encoding : 65001 12 File Encoding : 65001
13 13
14 - Date: 03/09/2023 19:13:55 14 + Date: 24/09/2023 23:23:06
15 */ 15 */
16 16
17 SET NAMES utf8mb4; 17 SET NAMES utf8mb4;
@@ -72,6 +72,7 @@ CREATE TABLE `QRTZ_CRON_TRIGGERS` ( @@ -72,6 +72,7 @@ CREATE TABLE `QRTZ_CRON_TRIGGERS` (
72 -- Records of QRTZ_CRON_TRIGGERS 72 -- Records of QRTZ_CRON_TRIGGERS
73 -- ---------------------------- 73 -- ----------------------------
74 BEGIN; 74 BEGIN;
  75 +INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'demoJob', 'DEFAULT', '0 0 0 * * ?', 'Asia/Shanghai');
75 INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai'); 76 INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
76 INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai'); 77 INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
77 INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai'); 78 INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai');
@@ -135,6 +136,7 @@ CREATE TABLE `QRTZ_JOB_DETAILS` ( @@ -135,6 +136,7 @@ CREATE TABLE `QRTZ_JOB_DETAILS` (
135 -- Records of QRTZ_JOB_DETAILS 136 -- Records of QRTZ_JOB_DETAILS
136 -- ---------------------------- 137 -- ----------------------------
137 BEGIN; 138 BEGIN;
  139 +INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'demoJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000147400104A4F425F48414E444C45525F4E414D4574000764656D6F4A6F627800);
138 INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800); 140 INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800);
139 INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000127400104A4F425F48414E444C45525F4E414D457400117061794F726465724578706972654A6F627800); 141 INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000127400104A4F425F48414E444C45525F4E414D457400117061794F726465724578706972654A6F627800);
140 INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000117400104A4F425F48414E444C45525F4E414D4574000F7061794F7264657253796E634A6F627800); 142 INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000117400104A4F425F48414E444C45525F4E414D4574000F7061794F7264657253796E634A6F627800);
@@ -191,7 +193,7 @@ CREATE TABLE `QRTZ_SCHEDULER_STATE` ( @@ -191,7 +193,7 @@ CREATE TABLE `QRTZ_SCHEDULER_STATE` (
191 -- Records of QRTZ_SCHEDULER_STATE 193 -- Records of QRTZ_SCHEDULER_STATE
192 -- ---------------------------- 194 -- ----------------------------
193 BEGIN; 195 BEGIN;
194 -INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai1690117495401', 1690119854263, 15000); 196 +INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai.local1694844151505', 1694844218609, 15000);
195 COMMIT; 197 COMMIT;
196 198
197 -- ---------------------------- 199 -- ----------------------------
@@ -285,6 +287,7 @@ CREATE TABLE `QRTZ_TRIGGERS` ( @@ -285,6 +287,7 @@ CREATE TABLE `QRTZ_TRIGGERS` (
285 -- Records of QRTZ_TRIGGERS 287 -- Records of QRTZ_TRIGGERS
286 -- ---------------------------- 288 -- ----------------------------
287 BEGIN; 289 BEGIN;
  290 +INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'demoJob', 'DEFAULT', 'demoJob', 'DEFAULT', NULL, 1694880000000, -1, 5, 'WAITING', 'CRON', 1694844083000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000A74000F4A4F425F52455452595F434F554E547371007E000A000000017800);
288 INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1688907102000, 1688907101000, 5, 'PAUSED', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); 291 INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1688907102000, 1688907101000, 5, 'PAUSED', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
289 INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', 'payOrderExpireJob', 'DEFAULT', NULL, 1690011600000, -1, 5, 'PAUSED', 'CRON', 1690011553000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); 292 INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', 'payOrderExpireJob', 'DEFAULT', NULL, 1690011600000, -1, 5, 'PAUSED', 'CRON', 1690011553000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
290 INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', 'payOrderSyncJob', 'DEFAULT', NULL, 1690011600000, 1690011540000, 5, 'PAUSED', 'CRON', 1690007785000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); 293 INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', 'payOrderSyncJob', 'DEFAULT', NULL, 1690011600000, 1690011540000, 5, 'PAUSED', 'CRON', 1690007785000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
@@ -360,7 +363,7 @@ CREATE TABLE `infra_api_error_log` ( @@ -360,7 +363,7 @@ CREATE TABLE `infra_api_error_log` (
360 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 363 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
361 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 364 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
362 PRIMARY KEY (`id`) USING BTREE 365 PRIMARY KEY (`id`) USING BTREE
363 -) ENGINE = InnoDB AUTO_INCREMENT = 1497 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; 366 +) ENGINE = InnoDB AUTO_INCREMENT = 1544 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
364 367
365 -- ---------------------------- 368 -- ----------------------------
366 -- Records of infra_api_error_log 369 -- Records of infra_api_error_log
@@ -398,7 +401,7 @@ CREATE TABLE `infra_codegen_column` ( @@ -398,7 +401,7 @@ CREATE TABLE `infra_codegen_column` (
398 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 401 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
399 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 402 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
400 PRIMARY KEY (`id`) USING BTREE 403 PRIMARY KEY (`id`) USING BTREE
401 -) ENGINE = InnoDB AUTO_INCREMENT = 1756 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; 404 +) ENGINE = InnoDB AUTO_INCREMENT = 1755 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
402 405
403 -- ---------------------------- 406 -- ----------------------------
404 -- Records of infra_codegen_column 407 -- Records of infra_codegen_column
@@ -514,7 +517,7 @@ CREATE TABLE `infra_file` ( @@ -514,7 +517,7 @@ CREATE TABLE `infra_file` (
514 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 517 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
515 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 518 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
516 PRIMARY KEY (`id`) USING BTREE 519 PRIMARY KEY (`id`) USING BTREE
517 -) ENGINE = InnoDB AUTO_INCREMENT = 1054 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; 520 +) ENGINE = InnoDB AUTO_INCREMENT = 1055 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
518 521
519 -- ---------------------------- 522 -- ----------------------------
520 -- Records of infra_file 523 -- Records of infra_file
@@ -545,12 +548,7 @@ CREATE TABLE `infra_file_config` ( @@ -545,12 +548,7 @@ CREATE TABLE `infra_file_config` (
545 -- Records of infra_file_config 548 -- Records of infra_file_config
546 -- ---------------------------- 549 -- ----------------------------
547 BEGIN; 550 BEGIN;
548 -INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '数据库', 1, '我是数据库', b'1', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.db.DBFileClientConfig\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2022-03-15 23:56:24', '1', '2023-04-08 09:44:47', b'0');  
549 -INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '本地磁盘', 10, '测试下本地存储', b'0', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.local.LocalFileClientConfig\",\"basePath\":\"/Users/yunai/file_test\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2022-03-15 23:57:00', '1', '2023-04-08 09:44:47', b'0');  
550 -INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (11, 'S3 - 七牛云', 20, NULL, b'0', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3-cn-south-1.qiniucs.com\",\"domain\":\"http://test.yudao.iocoder.cn\",\"bucket\":\"ruoyi-vue-pro\",\"accessKey\":\"b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8\",\"accessSecret\":\"kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP\"}', '1', '2022-03-19 18:00:03', '1', '2023-04-08 09:44:47', b'0');  
551 -INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (15, 'S3 - 七牛云', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3-cn-south-1.qiniucs.com\",\"domain\":\"http://test.yudao.iocoder.cn\",\"bucket\":\"ruoyi-vue-pro\",\"accessKey\":\"b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8\",\"accessSecret\":\"kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP\"}', '1', '2022-06-10 20:50:41', '1', '2023-04-08 09:44:47', b'0');  
552 -INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (16, 'S3 - 七牛云', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3-cn-south-1.qiniucs.com\",\"domain\":\"http://test.yudao.iocoder.cn\",\"bucket\":\"ruoyi-vue-pro\",\"accessKey\":\"b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8\",\"accessSecret\":\"kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP\"}', '1', '2022-06-11 20:32:08', '1', '2023-04-08 09:44:47', b'0');  
553 -INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (17, 'S3 - 七牛云', 20, '', b'0', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig\",\"endpoint\":\"s3-cn-south-1.qiniucs.com\",\"domain\":\"http://test.yudao.iocoder.cn\",\"bucket\":\"ruoyi-vue-pro\",\"accessKey\":\"b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8\",\"accessSecret\":\"kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP\"}', '1', '2022-06-11 20:32:47', '1', '2023-04-08 09:44:47', b'0'); 551 +INSERT INTO `infra_file_config` (`id`, `name`, `storage`, `remark`, `master`, `config`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '数据库', 1, '我是数据库', b'1', '{\"@class\":\"cn.iocoder.yudao.framework.file.core.client.db.DBFileClientConfig\",\"domain\":\"http://127.0.0.1:48080\"}', '1', '2022-03-15 23:56:24', '1', '2023-09-15 12:05:12', b'0');
554 COMMIT; 552 COMMIT;
555 553
556 -- ---------------------------- 554 -- ----------------------------
@@ -568,7 +566,7 @@ CREATE TABLE `infra_file_content` ( @@ -568,7 +566,7 @@ CREATE TABLE `infra_file_content` (
568 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 566 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
569 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 567 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
570 PRIMARY KEY (`id`) USING BTREE 568 PRIMARY KEY (`id`) USING BTREE
571 -) ENGINE = InnoDB AUTO_INCREMENT = 145 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; 569 +) ENGINE = InnoDB AUTO_INCREMENT = 149 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
572 570
573 -- ---------------------------- 571 -- ----------------------------
574 -- Records of infra_file_content 572 -- Records of infra_file_content
@@ -596,17 +594,17 @@ CREATE TABLE `infra_job` ( @@ -596,17 +594,17 @@ CREATE TABLE `infra_job` (
596 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 594 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
597 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 595 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
598 PRIMARY KEY (`id`) USING BTREE 596 PRIMARY KEY (`id`) USING BTREE
599 -) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表'; 597 +) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
600 598
601 -- ---------------------------- 599 -- ----------------------------
602 -- Records of infra_job 600 -- Records of infra_job
603 -- ---------------------------- 601 -- ----------------------------
604 BEGIN; 602 BEGIN;
605 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2023-07-09 20:51:41', b'0'); 603 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2023-07-09 20:51:41', b'0');
606 -INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (16, 'Job 示例', 1, 'demoJob', NULL, '* * * L * ?', 1, 1, 0, '1', '2022-09-24 22:31:41', '1', '2022-09-24 22:31:42', b'0');  
607 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (17, '支付订单同步 Job', 2, 'payOrderSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 14:36:26', '1', '2023-07-22 15:39:08', b'0'); 604 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (17, '支付订单同步 Job', 2, 'payOrderSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 14:36:26', '1', '2023-07-22 15:39:08', b'0');
608 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (18, '支付订单过期 Job', 2, 'payOrderExpireJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 15:36:23', '1', '2023-07-22 15:39:54', b'0'); 605 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (18, '支付订单过期 Job', 2, 'payOrderExpireJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 15:36:23', '1', '2023-07-22 15:39:54', b'0');
609 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (19, '退款订单的同步 Job', 2, 'payRefundSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-23 21:03:44', '1', '2023-07-23 21:09:00', b'0'); 606 INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (19, '退款订单的同步 Job', 2, 'payRefundSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-23 21:03:44', '1', '2023-07-23 21:09:00', b'0');
  607 +INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (20, 'Job 示例', 1, 'demoJob', '', '0 0 0 * * ?', 1, 10, 0, '1', '2023-09-16 14:01:23', '1', '2023-09-16 14:01:23', b'0');
610 COMMIT; 608 COMMIT;
611 609
612 -- ---------------------------- 610 -- ----------------------------
@@ -630,7 +628,7 @@ CREATE TABLE `infra_job_log` ( @@ -630,7 +628,7 @@ CREATE TABLE `infra_job_log` (
630 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 628 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
631 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 629 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
632 PRIMARY KEY (`id`) USING BTREE 630 PRIMARY KEY (`id`) USING BTREE
633 -) ENGINE = InnoDB AUTO_INCREMENT = 161 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; 631 +) ENGINE = InnoDB AUTO_INCREMENT = 163 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
634 632
635 -- ---------------------------- 633 -- ----------------------------
636 -- Records of infra_job_log 634 -- Records of infra_job_log
@@ -803,7 +801,7 @@ CREATE TABLE `member_level_record` ( @@ -803,7 +801,7 @@ CREATE TABLE `member_level_record` (
803 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 801 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
804 PRIMARY KEY (`id`) USING BTREE, 802 PRIMARY KEY (`id`) USING BTREE,
805 INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员等级记录-用户编号' 803 INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员等级记录-用户编号'
806 -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录'; 804 +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录';
807 805
808 -- ---------------------------- 806 -- ----------------------------
809 -- Records of member_level_record 807 -- Records of member_level_record
@@ -828,7 +826,7 @@ CREATE TABLE `member_point_config` ( @@ -828,7 +826,7 @@ CREATE TABLE `member_point_config` (
828 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 826 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
829 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 827 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
830 PRIMARY KEY (`id`) USING BTREE 828 PRIMARY KEY (`id`) USING BTREE
831 -) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '会员积分配置表'; 829 +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员积分配置表';
832 830
833 -- ---------------------------- 831 -- ----------------------------
834 -- Records of member_point_config 832 -- Records of member_point_config
@@ -844,10 +842,10 @@ DROP TABLE IF EXISTS `member_point_record`; @@ -844,10 +842,10 @@ DROP TABLE IF EXISTS `member_point_record`;
844 CREATE TABLE `member_point_record` ( 842 CREATE TABLE `member_point_record` (
845 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', 843 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
846 `user_id` bigint NOT NULL COMMENT '用户编号', 844 `user_id` bigint NOT NULL COMMENT '用户编号',
847 - `biz_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '业务编码', 845 + `biz_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '业务编码',
848 `biz_type` tinyint NOT NULL COMMENT '业务类型', 846 `biz_type` tinyint NOT NULL COMMENT '业务类型',
849 - `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '积分标题',  
850 - `description` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '积分描述', 847 + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '积分标题',
  848 + `description` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '积分描述',
851 `point` int NOT NULL COMMENT '积分', 849 `point` int NOT NULL COMMENT '积分',
852 `total_point` int NOT NULL COMMENT '变动后的积分', 850 `total_point` int NOT NULL COMMENT '变动后的积分',
853 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', 851 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
@@ -859,7 +857,7 @@ CREATE TABLE `member_point_record` ( @@ -859,7 +857,7 @@ CREATE TABLE `member_point_record` (
859 PRIMARY KEY (`id`) USING BTREE, 857 PRIMARY KEY (`id`) USING BTREE,
860 INDEX `index_userId`(`user_id` ASC) USING BTREE, 858 INDEX `index_userId`(`user_id` ASC) USING BTREE,
861 INDEX `index_title`(`title` ASC) USING BTREE 859 INDEX `index_title`(`title` ASC) USING BTREE
862 -) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户积分记录'; 860 +) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户积分记录';
863 861
864 -- ---------------------------- 862 -- ----------------------------
865 -- Records of member_point_record 863 -- Records of member_point_record
@@ -872,6 +870,15 @@ INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title @@ -872,6 +870,15 @@ INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title
872 INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 247, 'null', 11, '订单取消', '退单获得 -18 积分', -18, 73, NULL, '2023-08-31 19:56:21', NULL, '2023-08-31 19:56:21', b'0', 1); 870 INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 247, 'null', 11, '订单取消', '退单获得 -18 积分', -18, 73, NULL, '2023-08-31 19:56:21', NULL, '2023-08-31 19:56:21', b'0', 1);
873 INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 247, '80', 10, '订单消费', '下单获得 2099718 积分', 2099718, 2099791, NULL, '2023-08-31 23:43:29', NULL, '2023-08-31 23:43:29', b'0', 1); 871 INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 247, '80', 10, '订单消费', '下单获得 2099718 积分', 2099718, 2099791, NULL, '2023-08-31 23:43:29', NULL, '2023-08-31 23:43:29', b'0', 1);
874 INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 247, '81', 10, '订单消费', '下单获得 8398818 积分', 8398818, 10498609, NULL, '2023-08-31 23:46:17', NULL, '2023-08-31 23:46:17', b'0', 1); 872 INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 247, '81', 10, '订单消费', '下单获得 8398818 积分', 8398818, 10498609, NULL, '2023-08-31 23:46:17', NULL, '2023-08-31 23:46:17', b'0', 1);
  873 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 247, '85', 12, '订单使用', '下单使用 -30 积分', -30, 10498579, '247', '2023-09-20 17:11:36', '247', '2023-09-20 17:11:36', b'0', 1);
  874 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 247, '86', 12, '订单使用', '下单使用 -30 积分', -30, 10498549, '247', '2023-09-20 19:32:59', '247', '2023-09-20 19:32:59', b'0', 1);
  875 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 247, '87', 12, '订单使用', '下单使用 -30 积分', -30, 10498519, '247', '2023-09-20 23:11:21', '247', '2023-09-20 23:11:21', b'0', 1);
  876 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 247, '88', 12, '订单使用', '下单使用 -30 积分', -30, 10498489, '247', '2023-09-20 23:20:21', '247', '2023-09-20 23:20:21', b'0', 1);
  877 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 247, '89', 12, '订单使用', '下单使用 -30 积分', -30, 10498459, '247', '2023-09-23 23:51:40', '247', '2023-09-23 23:51:40', b'0', 1);
  878 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (13, 247, '90', 12, '订单使用', '下单使用 -30 积分', -30, 10498429, '247', '2023-09-23 23:52:34', '247', '2023-09-23 23:52:34', b'0', 1);
  879 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (14, 247, '91', 12, '订单使用', '下单使用 -30 积分', -30, 10498399, '247', '2023-09-23 23:54:18', '247', '2023-09-23 23:54:18', b'0', 1);
  880 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (15, 247, '92', 12, '订单使用', '下单使用 -30 积分', -30, 10498369, '247', '2023-09-23 23:55:33', '247', '2023-09-23 23:55:33', b'0', 1);
  881 +INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `point`, `total_point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (16, 247, '93', 12, '订单使用', '下单使用 -30 积分', -30, 10498339, '247', '2023-09-23 23:56:53', '247', '2023-09-23 23:56:53', b'0', 1);
875 COMMIT; 882 COMMIT;
876 883
877 -- ---------------------------- 884 -- ----------------------------
@@ -890,7 +897,7 @@ CREATE TABLE `member_sign_in_config` ( @@ -890,7 +897,7 @@ CREATE TABLE `member_sign_in_config` (
890 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 897 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
891 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 898 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
892 PRIMARY KEY (`id`) USING BTREE 899 PRIMARY KEY (`id`) USING BTREE
893 -) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '签到规则'; 900 +) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '签到规则';
894 901
895 -- ---------------------------- 902 -- ----------------------------
896 -- Records of member_sign_in_config 903 -- Records of member_sign_in_config
@@ -919,20 +926,23 @@ CREATE TABLE `member_sign_in_record` ( @@ -919,20 +926,23 @@ CREATE TABLE `member_sign_in_record` (
919 `user_id` int NULL DEFAULT NULL COMMENT '签到用户', 926 `user_id` int NULL DEFAULT NULL COMMENT '签到用户',
920 `day` int NULL DEFAULT NULL COMMENT '第几天签到', 927 `day` int NULL DEFAULT NULL COMMENT '第几天签到',
921 `point` int NULL DEFAULT NULL COMMENT '签到的分数', 928 `point` int NULL DEFAULT NULL COMMENT '签到的分数',
922 - `create_time` datetime NULL DEFAULT NULL COMMENT '签到时间',  
923 - `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',  
924 - `tenant_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '租户id',  
925 - `deleted` int NULL DEFAULT 0 COMMENT '是否删除',  
926 - `creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人',  
927 - `updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新人', 929 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  930 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  931 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  932 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  933 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  934 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
928 PRIMARY KEY (`id`) USING BTREE 935 PRIMARY KEY (`id`) USING BTREE
929 -) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '签到记录'; 936 +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '签到记录';
930 937
931 -- ---------------------------- 938 -- ----------------------------
932 -- Records of member_sign_in_record 939 -- Records of member_sign_in_record
933 -- ---------------------------- 940 -- ----------------------------
934 BEGIN; 941 BEGIN;
935 -INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `create_time`, `update_time`, `tenant_id`, `deleted`, `creator`, `updater`) VALUES (4, 247, 12, 1212, '2023-06-10 20:01:27', '2023-08-20 11:29:50', '1', 0, '1', '1'); 942 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 247, 1, 123, '', '2023-09-24 01:23:47', '', '2023-09-24 01:23:47', b'0', 0);
  943 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 247, 12, 12, '', '2023-09-24 01:23:47', '', '2023-09-24 01:23:47', b'0', 0);
  944 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 247, 12, 1212, '', '2023-09-24 01:23:47', '', '2023-09-24 01:23:47', b'0', 0);
  945 +INSERT INTO `member_sign_in_record` (`id`, `user_id`, `day`, `point`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 247, 12, 1212, '', '2023-09-24 01:23:47', '', '2023-09-24 01:23:47', b'0', 0);
936 COMMIT; 946 COMMIT;
937 947
938 -- ---------------------------- 948 -- ----------------------------
@@ -972,7 +982,7 @@ CREATE TABLE `member_user` ( @@ -972,7 +982,7 @@ CREATE TABLE `member_user` (
972 `login_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '最后登录IP', 982 `login_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '最后登录IP',
973 `login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间', 983 `login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间',
974 `nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称', 984 `nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
975 - `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像', 985 + `avatar` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像',
976 `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '真实名字', 986 `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '真实名字',
977 `sex` tinyint NULL DEFAULT 0 COMMENT '用户性别', 987 `sex` tinyint NULL DEFAULT 0 COMMENT '用户性别',
978 `area_id` bigint NULL DEFAULT NULL COMMENT '所在地', 988 `area_id` bigint NULL DEFAULT NULL COMMENT '所在地',
@@ -989,9 +999,8 @@ CREATE TABLE `member_user` ( @@ -989,9 +999,8 @@ CREATE TABLE `member_user` (
989 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 999 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
990 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1000 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
991 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 1001 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
992 - PRIMARY KEY (`id`) USING BTREE,  
993 - UNIQUE INDEX `uk_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'  
994 -) ENGINE = InnoDB AUTO_INCREMENT = 248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员用户'; 1002 + PRIMARY KEY (`id`) USING BTREE
  1003 +) ENGINE = InnoDB AUTO_INCREMENT = 249 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员用户';
995 1004
996 -- ---------------------------- 1005 -- ----------------------------
997 -- Records of member_user 1006 -- Records of member_user
@@ -1305,7 +1314,7 @@ CREATE TABLE `system_dict_type` ( @@ -1305,7 +1314,7 @@ CREATE TABLE `system_dict_type` (
1305 `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', 1314 `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
1306 PRIMARY KEY (`id`) USING BTREE, 1315 PRIMARY KEY (`id`) USING BTREE,
1307 UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE 1316 UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
1308 -) ENGINE = InnoDB AUTO_INCREMENT = 176 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; 1317 +) ENGINE = InnoDB AUTO_INCREMENT = 175 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
1309 1318
1310 -- ---------------------------- 1319 -- ----------------------------
1311 -- Records of system_dict_type 1320 -- Records of system_dict_type
@@ -1389,7 +1398,7 @@ CREATE TABLE `system_error_code` ( @@ -1389,7 +1398,7 @@ CREATE TABLE `system_error_code` (
1389 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 1398 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
1390 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1399 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1391 PRIMARY KEY (`id`) USING BTREE 1400 PRIMARY KEY (`id`) USING BTREE
1392 -) ENGINE = InnoDB AUTO_INCREMENT = 5933 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表'; 1401 +) ENGINE = InnoDB AUTO_INCREMENT = 5932 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
1393 1402
1394 -- ---------------------------- 1403 -- ----------------------------
1395 -- Records of system_error_code 1404 -- Records of system_error_code
@@ -1418,7 +1427,7 @@ CREATE TABLE `system_login_log` ( @@ -1418,7 +1427,7 @@ CREATE TABLE `system_login_log` (
1418 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1427 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1419 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 1428 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
1420 PRIMARY KEY (`id`) USING BTREE 1429 PRIMARY KEY (`id`) USING BTREE
1421 -) ENGINE = InnoDB AUTO_INCREMENT = 2375 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; 1430 +) ENGINE = InnoDB AUTO_INCREMENT = 2482 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
1422 1431
1423 -- ---------------------------- 1432 -- ----------------------------
1424 -- Records of system_login_log 1433 -- Records of system_login_log
@@ -1483,7 +1492,7 @@ CREATE TABLE `system_mail_log` ( @@ -1483,7 +1492,7 @@ CREATE TABLE `system_mail_log` (
1483 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 1492 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
1484 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1493 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1485 PRIMARY KEY (`id`) USING BTREE 1494 PRIMARY KEY (`id`) USING BTREE
1486 -) ENGINE = InnoDB AUTO_INCREMENT = 354 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表'; 1495 +) ENGINE = InnoDB AUTO_INCREMENT = 355 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表';
1487 1496
1488 -- ---------------------------- 1497 -- ----------------------------
1489 -- Records of system_mail_log 1498 -- Records of system_mail_log
@@ -2116,7 +2125,7 @@ CREATE TABLE `system_oauth2_access_token` ( @@ -2116,7 +2125,7 @@ CREATE TABLE `system_oauth2_access_token` (
2116 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2125 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2117 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 2126 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
2118 PRIMARY KEY (`id`) USING BTREE 2127 PRIMARY KEY (`id`) USING BTREE
2119 -) ENGINE = InnoDB AUTO_INCREMENT = 2597 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; 2128 +) ENGINE = InnoDB AUTO_INCREMENT = 2721 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
2120 2129
2121 -- ---------------------------- 2130 -- ----------------------------
2122 -- Records of system_oauth2_access_token 2131 -- Records of system_oauth2_access_token
@@ -2238,7 +2247,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( @@ -2238,7 +2247,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
2238 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2247 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2239 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 2248 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
2240 PRIMARY KEY (`id`) USING BTREE 2249 PRIMARY KEY (`id`) USING BTREE
2241 -) ENGINE = InnoDB AUTO_INCREMENT = 896 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; 2250 +) ENGINE = InnoDB AUTO_INCREMENT = 991 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
2242 2251
2243 -- ---------------------------- 2252 -- ----------------------------
2244 -- Records of system_oauth2_refresh_token 2253 -- Records of system_oauth2_refresh_token
@@ -2278,7 +2287,7 @@ CREATE TABLE `system_operate_log` ( @@ -2278,7 +2287,7 @@ CREATE TABLE `system_operate_log` (
2278 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2287 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2279 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 2288 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
2280 PRIMARY KEY (`id`) USING BTREE 2289 PRIMARY KEY (`id`) USING BTREE
2281 -) ENGINE = InnoDB AUTO_INCREMENT = 8321 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; 2290 +) ENGINE = InnoDB AUTO_INCREMENT = 8338 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
2282 2291
2283 -- ---------------------------- 2292 -- ----------------------------
2284 -- Records of system_operate_log 2293 -- Records of system_operate_log
@@ -3286,7 +3295,7 @@ CREATE TABLE `system_sms_code` ( @@ -3286,7 +3295,7 @@ CREATE TABLE `system_sms_code` (
3286 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3295 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3287 PRIMARY KEY (`id`) USING BTREE, 3296 PRIMARY KEY (`id`) USING BTREE,
3288 INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号' 3297 INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
3289 -) ENGINE = InnoDB AUTO_INCREMENT = 501 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; 3298 +) ENGINE = InnoDB AUTO_INCREMENT = 513 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
3290 3299
3291 -- ---------------------------- 3300 -- ----------------------------
3292 -- Records of system_sms_code 3301 -- Records of system_sms_code
@@ -3329,7 +3338,7 @@ CREATE TABLE `system_sms_log` ( @@ -3329,7 +3338,7 @@ CREATE TABLE `system_sms_log` (
3329 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 3338 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
3330 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3339 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3331 PRIMARY KEY (`id`) USING BTREE 3340 PRIMARY KEY (`id`) USING BTREE
3332 -) ENGINE = InnoDB AUTO_INCREMENT = 365 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; 3341 +) ENGINE = InnoDB AUTO_INCREMENT = 381 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
3333 3342
3334 -- ---------------------------- 3343 -- ----------------------------
3335 -- Records of system_sms_log 3344 -- Records of system_sms_log
@@ -3401,7 +3410,7 @@ CREATE TABLE `system_social_user` ( @@ -3401,7 +3410,7 @@ CREATE TABLE `system_social_user` (
3401 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3410 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3402 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3411 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3403 PRIMARY KEY (`id`) USING BTREE 3412 PRIMARY KEY (`id`) USING BTREE
3404 -) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; 3413 +) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
3405 3414
3406 -- ---------------------------- 3415 -- ----------------------------
3407 -- Records of system_social_user 3416 -- Records of system_social_user
@@ -3426,7 +3435,7 @@ CREATE TABLE `system_social_user_bind` ( @@ -3426,7 +3435,7 @@ CREATE TABLE `system_social_user_bind` (
3426 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3435 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3427 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3436 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3428 PRIMARY KEY (`id`) USING BTREE 3437 PRIMARY KEY (`id`) USING BTREE
3429 -) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; 3438 +) ENGINE = InnoDB AUTO_INCREMENT = 76 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
3430 3439
3431 -- ---------------------------- 3440 -- ----------------------------
3432 -- Records of system_social_user_bind 3441 -- Records of system_social_user_bind
@@ -3462,8 +3471,8 @@ CREATE TABLE `system_tenant` ( @@ -3462,8 +3471,8 @@ CREATE TABLE `system_tenant` (
3462 -- ---------------------------- 3471 -- ----------------------------
3463 BEGIN; 3472 BEGIN;
3464 INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'https://www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2022-02-23 12:15:11', b'0'); 3473 INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'https://www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2022-02-23 12:15:11', b'0');
3465 -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'http://www.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-07-25 23:05:38', b'0');  
3466 -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-07-25 23:53:16', b'0'); 3474 +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'http://www.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-09-16 16:59:42', b'0');
  3475 +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-09-16 16:59:27', b'0');
3467 COMMIT; 3476 COMMIT;
3468 3477
3469 -- ---------------------------- 3478 -- ----------------------------
@@ -3602,10 +3611,10 @@ CREATE TABLE `system_users` ( @@ -3602,10 +3611,10 @@ CREATE TABLE `system_users` (
3602 -- Records of system_users 3611 -- Records of system_users
3603 -- ---------------------------- 3612 -- ----------------------------
3604 BEGIN; 3613 BEGIN;
3605 -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://test.yudao.iocoder.cn/e1fdd7271685ec143a0900681606406621717a666ad0b2798b096df41422b32f.png', 0, '0:0:0:0:0:0:0:1', '2023-09-02 00:03:37', 'admin', '2021-01-05 17:03:47', NULL, '2023-09-02 00:03:37', b'0', 1); 3614 +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://test.yudao.iocoder.cn/e1fdd7271685ec143a0900681606406621717a666ad0b2798b096df41422b32f.png', 0, '0:0:0:0:0:0:0:1', '2023-09-24 12:03:56', 'admin', '2021-01-05 17:03:47', NULL, '2023-09-24 12:03:56', b'0', 1);
3606 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); 3615 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1);
3607 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1); 3616 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1);
3608 -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '127.0.0.1', '2022-05-28 15:43:17', '', '2021-01-21 02:13:53', NULL, '2022-07-09 09:00:33', b'0', 1); 3617 +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2023-09-24 18:21:19', '', '2021-01-21 02:13:53', NULL, '2023-09-24 18:21:19', b'0', 1);
3609 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (107, 'admin107', '$2a$10$dYOOBKMO93v/.ReCqzyFg.o67Tqk.bbc2bhrpyBGkIw9aypCtr2pm', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 22:59:33', '1', '2022-02-27 08:26:51', b'0', 118); 3618 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (107, 'admin107', '$2a$10$dYOOBKMO93v/.ReCqzyFg.o67Tqk.bbc2bhrpyBGkIw9aypCtr2pm', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 22:59:33', '1', '2022-02-27 08:26:51', b'0', 118);
3610 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (108, 'admin108', '$2a$10$y6mfvKoNYL1GXWak8nYwVOH.kCWqjactkzdoIDgiKl93WN3Ejg.Lu', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:00:50', '1', '2022-02-27 08:26:53', b'0', 119); 3619 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (108, 'admin108', '$2a$10$y6mfvKoNYL1GXWak8nYwVOH.kCWqjactkzdoIDgiKl93WN3Ejg.Lu', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:00:50', '1', '2022-02-27 08:26:53', b'0', 119);
3611 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, 'admin109', '$2a$10$JAqvH0tEc0I7dfDVBI7zyuB4E3j.uH6daIjV53.vUS6PknFkDJkuK', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:11:50', '1', '2022-02-27 08:26:56', b'0', 120); 3620 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, 'admin109', '$2a$10$JAqvH0tEc0I7dfDVBI7zyuB4E3j.uH6daIjV53.vUS6PknFkDJkuK', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:11:50', '1', '2022-02-27 08:26:56', b'0', 120);
sql/sqlserver/ruoyi-vue-pro.sql
@@ -5815,8 +5815,7 @@ GO @@ -5815,8 +5815,7 @@ GO
5815 5815
5816 CREATE TABLE [dbo].[system_dict_type] 5816 CREATE TABLE [dbo].[system_dict_type]
5817 ( 5817 (
5818 - [  
5819 - id] 5818 + [id]
5820 bigint 5819 bigint
5821 IDENTITY 5820 IDENTITY
5822 ( 5821 (
yudao-dependencies/pom.xml
@@ -14,16 +14,16 @@ @@ -14,16 +14,16 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.8.1-snapshot</revision> 17 + <revision>1.8.2-snapshot</revision>
18 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> 18 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
19 <!-- 统一依赖管理 --> 19 <!-- 统一依赖管理 -->
20 - <spring.boot.version>2.7.14</spring.boot.version> 20 + <spring.boot.version>2.7.16</spring.boot.version>
21 <!-- Web 相关 --> 21 <!-- Web 相关 -->
22 - <springdoc.version>1.6.15</springdoc.version>  
23 - <knife4j.version>4.1.0</knife4j.version> 22 + <springdoc.version>1.7.0</springdoc.version>
  23 + <knife4j.version>4.3.0</knife4j.version>
24 <servlet.versoin>2.5</servlet.versoin> 24 <servlet.versoin>2.5</servlet.versoin>
25 <!-- DB 相关 --> 25 <!-- DB 相关 -->
26 - <druid.version>1.2.18</druid.version> 26 + <druid.version>1.2.19</druid.version>
27 <mybatis-plus.version>3.5.3.2</mybatis-plus.version> 27 <mybatis-plus.version>3.5.3.2</mybatis-plus.version>
28 <mybatis-plus-generator.version>3.5.3.2</mybatis-plus-generator.version> 28 <mybatis-plus-generator.version>3.5.3.2</mybatis-plus-generator.version>
29 <dynamic-datasource.version>3.6.1</dynamic-datasource.version> 29 <dynamic-datasource.version>3.6.1</dynamic-datasource.version>
@@ -44,33 +44,32 @@ @@ -44,33 +44,32 @@
44 <!-- Bpm 工作流相关 --> 44 <!-- Bpm 工作流相关 -->
45 <flowable.version>6.8.0</flowable.version> 45 <flowable.version>6.8.0</flowable.version>
46 <!-- 工具类相关 --> 46 <!-- 工具类相关 -->
47 - <captcha-plus.version>1.0.6</captcha-plus.version>  
48 - <jsoup.version>1.15.4</jsoup.version>  
49 - <lombok.version>1.18.28</lombok.version> 47 + <captcha-plus.version>1.0.8</captcha-plus.version>
  48 + <jsoup.version>1.16.1</jsoup.version>
  49 + <lombok.version>1.18.30</lombok.version>
50 <mapstruct.version>1.5.5.Final</mapstruct.version> 50 <mapstruct.version>1.5.5.Final</mapstruct.version>
51 - <hutool.version>5.8.20</hutool.version> 51 + <hutool.version>5.8.22</hutool.version>
52 <easyexcel.verion>3.3.2</easyexcel.verion> 52 <easyexcel.verion>3.3.2</easyexcel.verion>
53 <velocity.version>2.3</velocity.version> 53 <velocity.version>2.3</velocity.version>
54 <screw.version>1.0.5</screw.version> 54 <screw.version>1.0.5</screw.version>
55 <fastjson.version>1.2.83</fastjson.version> 55 <fastjson.version>1.2.83</fastjson.version>
56 - <guava.version>32.0.1-jre</guava.version> 56 + <guava.version>32.1.2-jre</guava.version>
57 <guice.version>5.1.0</guice.version> 57 <guice.version>5.1.0</guice.version>
58 <transmittable-thread-local.version>2.14.2</transmittable-thread-local.version> 58 <transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
59 <commons-net.version>3.9.0</commons-net.version> 59 <commons-net.version>3.9.0</commons-net.version>
60 <jsch.version>0.1.55</jsch.version> 60 <jsch.version>0.1.55</jsch.version>
61 <tika-core.version>2.7.0</tika-core.version> 61 <tika-core.version>2.7.0</tika-core.version>
62 - <netty-all.version>4.1.90.Final</netty-all.version>  
63 <ip2region.version>2.7.0</ip2region.version> 62 <ip2region.version>2.7.0</ip2region.version>
64 <!-- 三方云服务相关 --> 63 <!-- 三方云服务相关 -->
65 - <okio.version>3.0.0</okio.version>  
66 - <okhttp3.version>4.10.0</okhttp3.version> 64 + <okio.version>3.5.0</okio.version>
  65 + <okhttp3.version>4.11.0</okhttp3.version>
67 <commons-io.version>2.11.0</commons-io.version> 66 <commons-io.version>2.11.0</commons-io.version>
68 - <minio.version>8.5.4</minio.version>  
69 - <aliyun-java-sdk-core.version>4.6.3</aliyun-java-sdk-core.version> 67 + <minio.version>8.5.6</minio.version>
  68 + <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version>
70 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version> 69 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
71 - <tencentcloud-sdk-java.version>3.1.758</tencentcloud-sdk-java.version>  
72 - <justauth.version>1.0.3</justauth.version>  
73 - <jimureport.version>1.5.8</jimureport.version> 70 + <tencentcloud-sdk-java.version>3.1.853</tencentcloud-sdk-java.version>
  71 + <justauth.version>1.0.5</justauth.version>
  72 + <jimureport.version>1.6.1</jimureport.version>
74 <xercesImpl.version>2.12.2</xercesImpl.version> 73 <xercesImpl.version>2.12.2</xercesImpl.version>
75 <weixin-java.version>4.5.0</weixin-java.version> 74 <weixin-java.version>4.5.0</weixin-java.version>
76 </properties> 75 </properties>
@@ -233,6 +232,12 @@ @@ -233,6 +232,12 @@
233 <groupId>org.redisson</groupId> 232 <groupId>org.redisson</groupId>
234 <artifactId>redisson-spring-boot-starter</artifactId> 233 <artifactId>redisson-spring-boot-starter</artifactId>
235 <version>${redisson.version}</version> 234 <version>${redisson.version}</version>
  235 + <exclusions>
  236 + <exclusion>
  237 + <groupId>org.springframework.boot</groupId>
  238 + <artifactId>spring-boot-starter-actuator</artifactId>
  239 + </exclusion>
  240 + </exclusions>
236 </dependency> 241 </dependency>
237 242
238 <dependency> 243 <dependency>
@@ -337,6 +342,12 @@ @@ -337,6 +342,12 @@
337 <groupId>de.codecentric</groupId> 342 <groupId>de.codecentric</groupId>
338 <artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 --> 343 <artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
339 <version>${spring-boot-admin.version}</version> 344 <version>${spring-boot-admin.version}</version>
  345 + <exclusions>
  346 + <exclusion>
  347 + <groupId>de.codecentric</groupId>
  348 + <artifactId>spring-boot-admin-server-cloud</artifactId>
  349 + </exclusion>
  350 + </exclusions>
340 </dependency> 351 </dependency>
341 <dependency> 352 <dependency>
342 <groupId>de.codecentric</groupId> 353 <groupId>de.codecentric</groupId>
@@ -520,12 +531,6 @@ @@ -520,12 +531,6 @@
520 </dependency> 531 </dependency>
521 532
522 <dependency> 533 <dependency>
523 - <groupId>io.netty</groupId>  
524 - <artifactId>netty-all</artifactId>  
525 - <version>${netty-all.version}</version>  
526 - </dependency>  
527 -  
528 - <dependency>  
529 <groupId>com.xingyuv</groupId> 534 <groupId>com.xingyuv</groupId>
530 <artifactId>spring-boot-starter-captcha-plus</artifactId> 535 <artifactId>spring-boot-starter-captcha-plus</artifactId>
531 <version>${captcha-plus.version}</version> 536 <version>${captcha-plus.version}</version>
yudao-example/yudao-sso-demo-by-code/pom.xml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <maven.compiler.target>8</maven.compiler.target> 21 <maven.compiler.target>8</maven.compiler.target>
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <!-- 统一依赖管理 --> 23 <!-- 统一依赖管理 -->
24 - <spring.boot.version>2.7.14</spring.boot.version> 24 + <spring.boot.version>2.7.16</spring.boot.version>
25 </properties> 25 </properties>
26 26
27 <dependencyManagement> 27 <dependencyManagement>
@@ -52,7 +52,7 @@ @@ -52,7 +52,7 @@
52 <dependency> 52 <dependency>
53 <groupId>cn.hutool</groupId> 53 <groupId>cn.hutool</groupId>
54 <artifactId>hutool-all</artifactId> 54 <artifactId>hutool-all</artifactId>
55 - <version>5.8.20</version> 55 + <version>5.8.22</version>
56 </dependency> 56 </dependency>
57 57
58 <dependency> 58 <dependency>
yudao-example/yudao-sso-demo-by-password/pom.xml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <maven.compiler.target>8</maven.compiler.target> 21 <maven.compiler.target>8</maven.compiler.target>
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <!-- 统一依赖管理 --> 23 <!-- 统一依赖管理 -->
24 - <spring.boot.version>2.7.14</spring.boot.version> 24 + <spring.boot.version>2.7.16</spring.boot.version>
25 </properties> 25 </properties>
26 26
27 <dependencyManagement> 27 <dependencyManagement>
@@ -52,7 +52,7 @@ @@ -52,7 +52,7 @@
52 <dependency> 52 <dependency>
53 <groupId>cn.hutool</groupId> 53 <groupId>cn.hutool</groupId>
54 <artifactId>hutool-all</artifactId> 54 <artifactId>hutool-all</artifactId>
55 - <version>5.8.20</version> 55 + <version>5.8.22</version>
56 </dependency> 56 </dependency>
57 57
58 <dependency> 58 <dependency>
yudao-framework/yudao-common/pom.xml
@@ -137,6 +137,7 @@ @@ -137,6 +137,7 @@
137 <dependency> 137 <dependency>
138 <groupId>org.springframework.boot</groupId> 138 <groupId>org.springframework.boot</groupId>
139 <artifactId>spring-boot-starter-test</artifactId> 139 <artifactId>spring-boot-starter-test</artifactId>
  140 + <scope>test</scope>
140 </dependency> 141 </dependency>
141 </dependencies> 142 </dependencies>
142 143
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java
@@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; @@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
10 import com.fasterxml.jackson.databind.SerializationFeature; 10 import com.fasterxml.jackson.databind.SerializationFeature;
11 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 11 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
12 import lombok.SneakyThrows; 12 import lombok.SneakyThrows;
13 -import lombok.experimental.UtilityClass;  
14 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
15 14
16 import java.io.IOException; 15 import java.io.IOException;
@@ -23,7 +22,6 @@ import java.util.List; @@ -23,7 +22,6 @@ import java.util.List;
23 * 22 *
24 * @author 芋道源码 23 * @author 芋道源码
25 */ 24 */
26 -@UtilityClass  
27 @Slf4j 25 @Slf4j
28 public class JsonUtils { 26 public class JsonUtils {
29 27
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
@@ -50,7 +50,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -50,7 +50,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
50 */ 50 */
51 public final void init() { 51 public final void init() {
52 doInit(); 52 doInit();
53 - log.info("[init][客户端({}) 初始化完成]", getId()); 53 + log.debug("[init][客户端({}) 初始化完成]", getId());
54 } 54 }
55 55
56 /** 56 /**
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java
@@ -40,7 +40,7 @@ public abstract class AbstractSmsClient implements SmsClient { @@ -40,7 +40,7 @@ public abstract class AbstractSmsClient implements SmsClient {
40 */ 40 */
41 public final void init() { 41 public final void init() {
42 doInit(); 42 doInit();
43 - log.info("[init][配置({}) 初始化完成]", properties); 43 + log.debug("[init][配置({}) 初始化完成]", properties);
44 } 44 }
45 45
46 /** 46 /**
yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java
1 -package cn.iocoder.yudao.framework.social.config;  
2 -  
3 -import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;  
4 -import com.xingyuv.http.HttpUtil;  
5 -import com.xingyuv.http.support.hutool.HutoolImpl;  
6 -import com.xingyuv.jushauth.cache.AuthStateCache;  
7 -import com.xingyuv.justauth.autoconfigure.JustAuthProperties;  
8 -import lombok.extern.slf4j.Slf4j;  
9 -import org.springframework.boot.autoconfigure.AutoConfiguration;  
10 -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
11 -import org.springframework.boot.context.properties.EnableConfigurationProperties;  
12 -import org.springframework.context.annotation.Bean;  
13 -import org.springframework.context.annotation.Primary;  
14 -  
15 -/**  
16 - * 社交自动装配类  
17 - *  
18 - * @author timfruit  
19 - * @date 2021-10-30  
20 - */  
21 -@Slf4j  
22 -@AutoConfiguration  
23 -@EnableConfigurationProperties(JustAuthProperties.class)  
24 -public class YudaoSocialAutoConfiguration {  
25 -  
26 - @Bean  
27 - @Primary  
28 - @ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)  
29 - public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {  
30 - // 需要修改 HttpUtil 使用的实现,避免类报错  
31 - HttpUtil.setHttp(new HutoolImpl());  
32 - // 创建 YudaoAuthRequestFactory  
33 - return new YudaoAuthRequestFactory(properties, authStateCache);  
34 - }  
35 -  
36 -} 1 +package cn.iocoder.yudao.framework.social.config;
  2 +
  3 +import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
  4 +import com.xingyuv.http.HttpUtil;
  5 +import com.xingyuv.http.support.hutool.HutoolImpl;
  6 +import com.xingyuv.jushauth.cache.AuthStateCache;
  7 +import com.xingyuv.justauth.autoconfigure.JustAuthProperties;
  8 +import lombok.extern.slf4j.Slf4j;
  9 +import org.springframework.boot.autoconfigure.AutoConfiguration;
  10 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  11 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  12 +import org.springframework.context.annotation.Bean;
  13 +import org.springframework.context.annotation.Primary;
  14 +
  15 +/**
  16 + * 社交自动装配类
  17 + *
  18 + * @author timfruit
  19 + * @date 2021-10-30
  20 + */
  21 +@Slf4j
  22 +@AutoConfiguration
  23 +@EnableConfigurationProperties(JustAuthProperties.class)
  24 +public class YudaoSocialAutoConfiguration {
  25 +
  26 + @Bean
  27 + @Primary
  28 + @ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)
  29 + public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
  30 + // 需要修改 HttpUtil 使用的实现,避免类报错
  31 + HttpUtil.setHttp(new HutoolImpl());
  32 + // 创建 YudaoAuthRequestFactory
  33 + return new YudaoAuthRequestFactory(properties, authStateCache);
  34 + }
  35 +
  36 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
1 package cn.iocoder.yudao.framework.tenant.config; 1 package cn.iocoder.yudao.framework.tenant.config;
2 2
3 -import cn.hutool.core.annotation.AnnotationUtil;  
4 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; 3 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
5 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; 4 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
6 -import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;  
7 import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties; 5 import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
8 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect; 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
9 import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; 7 import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
10 -import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;  
11 -import cn.iocoder.yudao.framework.tenant.core.job.TenantJobHandlerDecorator; 8 +import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
12 import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor; 9 import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor;
13 import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager; 10 import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager;
14 import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; 11 import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
@@ -20,8 +17,6 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; @@ -20,8 +17,6 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
20 import cn.iocoder.yudao.module.system.api.tenant.TenantApi; 17 import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
21 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 18 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
22 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; 19 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
23 -import org.springframework.beans.BeansException;  
24 -import org.springframework.beans.factory.config.BeanPostProcessor;  
25 import org.springframework.boot.autoconfigure.AutoConfiguration; 20 import org.springframework.boot.autoconfigure.AutoConfiguration;
26 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 21 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
27 import org.springframework.boot.context.properties.EnableConfigurationProperties; 22 import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -100,25 +95,8 @@ public class YudaoTenantAutoConfiguration { @@ -100,25 +95,8 @@ public class YudaoTenantAutoConfiguration {
100 // ========== Job ========== 95 // ========== Job ==========
101 96
102 @Bean 97 @Bean
103 - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")  
104 - public BeanPostProcessor jobHandlerBeanPostProcessor(TenantFrameworkService tenantFrameworkService) {  
105 - return new BeanPostProcessor() {  
106 -  
107 - @Override  
108 - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
109 - if (!(bean instanceof JobHandler)) {  
110 - return bean;  
111 - }  
112 - // 有 TenantJob 注解的情况下,才会进行处理  
113 - if (!AnnotationUtil.hasAnnotation(bean.getClass(), TenantJob.class)) {  
114 - return bean;  
115 - }  
116 -  
117 - // 使用 TenantJobHandlerDecorator 装饰  
118 - return new TenantJobHandlerDecorator(tenantFrameworkService, (JobHandler) bean);  
119 - }  
120 -  
121 - }; 98 + public TenantJobAspect tenantJobAspect(TenantFrameworkService tenantFrameworkService) {
  99 + return new TenantJobAspect(tenantFrameworkService);
122 } 100 }
123 101
124 // ========== Redis ========== 102 // ========== Redis ==========
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJob.java
@@ -8,7 +8,7 @@ import java.lang.annotation.Target; @@ -8,7 +8,7 @@ import java.lang.annotation.Target;
8 /** 8 /**
9 * 多租户 Job 注解 9 * 多租户 Job 注解
10 */ 10 */
11 -@Target({ElementType.TYPE}) 11 +@Target({ElementType.METHOD})
12 @Retention(RetentionPolicy.RUNTIME) 12 @Retention(RetentionPolicy.RUNTIME)
13 public @interface TenantJob { 13 public @interface TenantJob {
14 } 14 }
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobHandlerDecorator.java renamed to yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java
1 package cn.iocoder.yudao.framework.tenant.core.job; 1 package cn.iocoder.yudao.framework.tenant.core.job;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.exceptions.ExceptionUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 -import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;  
6 -import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;  
7 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; 6 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
8 -import lombok.AllArgsConstructor; 7 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
  8 +import lombok.RequiredArgsConstructor;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.aspectj.lang.ProceedingJoinPoint;
  11 +import org.aspectj.lang.annotation.Around;
  12 +import org.aspectj.lang.annotation.Aspect;
9 13
10 import java.util.List; 14 import java.util.List;
11 import java.util.Map; 15 import java.util.Map;
12 import java.util.concurrent.ConcurrentHashMap; 16 import java.util.concurrent.ConcurrentHashMap;
13 17
14 /** 18 /**
15 - * 多租户 JobHandler 装饰器 19 + * 多租户 JobHandler AOP
16 * 任务执行时,会按照租户逐个执行 Job 的逻辑 20 * 任务执行时,会按照租户逐个执行 Job 的逻辑
17 * 21 *
18 * 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。 22 * 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。
19 * 23 *
20 * @author 芋道源码 24 * @author 芋道源码
21 */ 25 */
22 -@AllArgsConstructor  
23 -public class TenantJobHandlerDecorator implements JobHandler { 26 +@Aspect
  27 +@RequiredArgsConstructor
  28 +@Slf4j
  29 +public class TenantJobAspect {
24 30
25 private final TenantFrameworkService tenantFrameworkService; 31 private final TenantFrameworkService tenantFrameworkService;
26 - /**  
27 - * 被装饰的 Job  
28 - */  
29 - private final JobHandler jobHandler;  
30 32
31 - @Override  
32 - public final String execute(String param) throws Exception { 33 + @Around("@annotation(tenantJob)")
  34 + public String around(ProceedingJoinPoint joinPoint, TenantJob tenantJob) {
33 // 获得租户列表 35 // 获得租户列表
34 List<Long> tenantIds = tenantFrameworkService.getTenantIds(); 36 List<Long> tenantIds = tenantFrameworkService.getTenantIds();
35 if (CollUtil.isEmpty(tenantIds)) { 37 if (CollUtil.isEmpty(tenantIds)) {
@@ -38,19 +40,15 @@ public class TenantJobHandlerDecorator implements JobHandler { @@ -38,19 +40,15 @@ public class TenantJobHandlerDecorator implements JobHandler {
38 40
39 // 逐个租户,执行 Job 41 // 逐个租户,执行 Job
40 Map<Long, String> results = new ConcurrentHashMap<>(); 42 Map<Long, String> results = new ConcurrentHashMap<>();
41 - tenantIds.parallelStream().forEach(tenantId -> { // TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况  
42 - try {  
43 - // 设置租户  
44 - TenantContextHolder.setTenantId(tenantId);  
45 - // 执行 Job  
46 - String result = jobHandler.execute(param);  
47 - // 添加结果  
48 - results.put(tenantId, result);  
49 - } catch (Exception e) {  
50 - throw new RuntimeException(e);  
51 - } finally {  
52 - TenantContextHolder.clear();  
53 - } 43 + tenantIds.parallelStream().forEach(tenantId -> {
  44 + // TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况
  45 + TenantUtils.execute(tenantId, () -> {
  46 + try {
  47 + joinPoint.proceed();
  48 + } catch (Throwable e) {
  49 + results.put(tenantId, ExceptionUtil.getRootCauseMessage(e));
  50 + }
  51 + });
54 }); 52 });
55 return JsonUtils.toJsonString(results); 53 return JsonUtils.toJsonString(results);
56 } 54 }
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java
1 package cn.iocoder.yudao.framework.tenant.core.redis; 1 package cn.iocoder.yudao.framework.tenant.core.redis;
2 2
  3 +import cn.iocoder.yudao.framework.redis.core.TimeoutRedisCacheManager;
3 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; 4 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
4 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
5 import org.springframework.cache.Cache; 6 import org.springframework.cache.Cache;
@@ -15,7 +16,7 @@ import org.springframework.data.redis.cache.RedisCacheWriter; @@ -15,7 +16,7 @@ import org.springframework.data.redis.cache.RedisCacheWriter;
15 * @author airhead 16 * @author airhead
16 */ 17 */
17 @Slf4j 18 @Slf4j
18 -public class TenantRedisCacheManager extends RedisCacheManager { 19 +public class TenantRedisCacheManager extends TimeoutRedisCacheManager {
19 20
20 public TenantRedisCacheManager(RedisCacheWriter cacheWriter, 21 public TenantRedisCacheManager(RedisCacheWriter cacheWriter,
21 RedisCacheConfiguration defaultCacheConfiguration) { 22 RedisCacheConfiguration defaultCacheConfiguration) {
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/test/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobTest.java deleted
1 -package cn.iocoder.yudao.framework.tenant.core.job;  
2 -  
3 -import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;  
4 -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;  
5 -import com.google.common.collect.Lists;  
6 -import org.junit.jupiter.api.Test;  
7 -import org.mockito.Mock;  
8 -import org.mockito.Mockito;  
9 -  
10 -import java.util.List;  
11 -  
12 -import static org.junit.jupiter.api.Assertions.assertEquals;  
13 -  
14 -/**  
15 - * 验证 job 租户逻辑  
16 - * {@link TenantJobHandlerDecorator}  
17 - *  
18 - * @author gaibu  
19 - */  
20 -public class TenantJobTest extends BaseMockitoUnitTest {  
21 -  
22 - @Mock  
23 - TenantFrameworkService tenantFrameworkService;  
24 -  
25 - @Test  
26 - public void test() throws Exception {  
27 - // 准备测试租户 id  
28 - List<Long> tenantIds = Lists.newArrayList(1L, 2L, 3L);  
29 - // mock 数据  
30 - Mockito.doReturn(tenantIds).when(tenantFrameworkService).getTenantIds();  
31 - // 准备测试任务  
32 - TestJob testJob = new TestJob();  
33 - // 创建任务装饰器  
34 - TenantJobHandlerDecorator tenantJobHandlerDecorator = new TenantJobHandlerDecorator(tenantFrameworkService, testJob);  
35 -  
36 - // 执行任务  
37 - tenantJobHandlerDecorator.execute(null);  
38 -  
39 - // 断言返回值  
40 - assertEquals(testJob.getTenantIds(), tenantIds);  
41 - }  
42 -}  
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/test/java/cn/iocoder/yudao/framework/tenant/core/job/TestJob.java
@@ -9,12 +9,12 @@ import java.util.List; @@ -9,12 +9,12 @@ import java.util.List;
9 import java.util.concurrent.CopyOnWriteArrayList; 9 import java.util.concurrent.CopyOnWriteArrayList;
10 10
11 @Component 11 @Component
12 -@TenantJob // 标记多租户  
13 public class TestJob implements JobHandler { 12 public class TestJob implements JobHandler {
14 13
15 private final List<Long> tenantIds = new CopyOnWriteArrayList<>(); 14 private final List<Long> tenantIds = new CopyOnWriteArrayList<>();
16 15
17 @Override 16 @Override
  17 + @TenantJob // 标记多租户
18 public String execute(String param) throws Exception { 18 public String execute(String param) throws Exception {
19 tenantIds.add(TenantContextHolder.getTenantId()); 19 tenantIds.add(TenantContextHolder.getTenantId());
20 return "success"; 20 return "success";
@@ -24,4 +24,5 @@ public class TestJob implements JobHandler { @@ -24,4 +24,5 @@ public class TestJob implements JobHandler {
24 CollUtil.sort(tenantIds, Long::compareTo); 24 CollUtil.sort(tenantIds, Long::compareTo);
25 return tenantIds; 25 return tenantIds;
26 } 26 }
  27 +
27 } 28 }
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java
@@ -30,7 +30,7 @@ public abstract class AbstractFileClient&lt;Config extends FileClientConfig&gt; implem @@ -30,7 +30,7 @@ public abstract class AbstractFileClient&lt;Config extends FileClientConfig&gt; implem
30 */ 30 */
31 public final void init() { 31 public final void init() {
32 doInit(); 32 doInit();
33 - log.info("[init][配置({}) 初始化完成]", config); 33 + log.debug("[init][配置({}) 初始化完成]", config);
34 } 34 }
35 35
36 /** 36 /**
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/BpmnModelUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.flowable.core.util;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import org.flowable.bpmn.converter.BpmnXMLConverter;
  5 +import org.flowable.bpmn.model.Process;
  6 +import org.flowable.bpmn.model.*;
  7 +
  8 +import java.util.*;
  9 +
  10 +/**
  11 + * 流程模型转操作工具类
  12 + */
  13 +public class BpmnModelUtils {
  14 +
  15 + /**
  16 + * 根据节点,获取入口连线
  17 + *
  18 + * @param source 起始节点
  19 + * @return 入口连线列表
  20 + */
  21 + public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) {
  22 + if (source instanceof FlowNode) {
  23 + return ((FlowNode) source).getIncomingFlows();
  24 + }
  25 + return new ArrayList<>();
  26 + }
  27 +
  28 + /**
  29 + * 根据节点,获取出口连线
  30 + *
  31 + * @param source 起始节点
  32 + * @return 出口连线列表
  33 + */
  34 + public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) {
  35 + if (source instanceof FlowNode) {
  36 + return ((FlowNode) source).getOutgoingFlows();
  37 + }
  38 + return new ArrayList<>();
  39 + }
  40 +
  41 + /**
  42 + * 获取流程元素信息
  43 + *
  44 + * @param model bpmnModel 对象
  45 + * @param flowElementId 元素 ID
  46 + * @return 元素信息
  47 + */
  48 + public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) {
  49 + Process process = model.getMainProcess();
  50 + return process.getFlowElement(flowElementId);
  51 + }
  52 +
  53 + /**
  54 + * 获得 BPMN 流程中,指定的元素们
  55 + *
  56 + * @param model
  57 + * @param clazz 指定元素。例如说,{@link UserTask}、{@link Gateway} 等等
  58 + * @return 元素们
  59 + */
  60 + public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
  61 + List<T> result = new ArrayList<>();
  62 + model.getProcesses().forEach(process -> {
  63 + process.getFlowElements().forEach(flowElement -> {
  64 + if (flowElement.getClass().isAssignableFrom(clazz)) {
  65 + result.add((T) flowElement);
  66 + }
  67 + });
  68 + });
  69 + return result;
  70 + }
  71 +
  72 + /**
  73 + * 比较 两个bpmnModel 是否相同
  74 + * @param oldModel 老的bpmn model
  75 + * @param newModel 新的bpmn model
  76 + */
  77 + public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
  78 + // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
  79 + return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
  80 + }
  81 +
  82 + /**
  83 + * 把 bpmnModel 转换成 byte[]
  84 + * @param model bpmnModel
  85 + */
  86 + public static byte[] getBpmnBytes(BpmnModel model) {
  87 + if (model == null) {
  88 + return new byte[0];
  89 + }
  90 + BpmnXMLConverter converter = new BpmnXMLConverter();
  91 + return converter.convertToXML(model);
  92 + }
  93 +
  94 + // ========== 遍历相关的方法 ==========
  95 +
  96 + /**
  97 + * 找到 source 节点之前的所有用户任务节点
  98 + *
  99 + * @param source 起始节点
  100 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复
  101 + * @param userTaskList 已找到的用户任务节点
  102 + * @return 用户任务节点 数组
  103 + */
  104 + public static List<UserTask> getPreviousUserTaskList(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
  105 + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
  106 + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
  107 + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代
  108 + if (source instanceof StartEvent && source.getSubProcess() != null) {
  109 + userTaskList = getPreviousUserTaskList(source.getSubProcess(), hasSequenceFlow, userTaskList);
  110 + }
  111 +
  112 + // 根据类型,获取入口连线
  113 + List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
  114 + if (sequenceFlows == null) {
  115 + return userTaskList;
  116 + }
  117 + // 循环找到目标元素
  118 + for (SequenceFlow sequenceFlow : sequenceFlows) {
  119 + // 如果发现连线重复,说明循环了,跳过这个循环
  120 + if (hasSequenceFlow.contains(sequenceFlow.getId())) {
  121 + continue;
  122 + }
  123 + // 添加已经走过的连线
  124 + hasSequenceFlow.add(sequenceFlow.getId());
  125 + // 类型为用户节点,则新增父级节点
  126 + if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
  127 + userTaskList.add((UserTask) sequenceFlow.getSourceFlowElement());
  128 + }
  129 + // 类型为子流程,则添加子流程开始节点出口处相连的节点
  130 + if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) {
  131 + // 获取子流程用户任务节点
  132 + List<UserTask> childUserTaskList = findChildProcessUserTaskList((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, null);
  133 + // 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续
  134 + if (CollUtil.isNotEmpty(childUserTaskList)) {
  135 + userTaskList.addAll(childUserTaskList);
  136 + }
  137 + }
  138 + // 继续迭代
  139 + userTaskList = getPreviousUserTaskList(sequenceFlow.getSourceFlowElement(), hasSequenceFlow, userTaskList);
  140 + }
  141 + return userTaskList;
  142 + }
  143 +
  144 + /**
  145 + * 迭代获取子流程用户任务节点
  146 + *
  147 + * @param source 起始节点
  148 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复
  149 + * @param userTaskList 需要撤回的用户任务列表
  150 + * @return 用户任务节点
  151 + */
  152 + public static List<UserTask> findChildProcessUserTaskList(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
  153 + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
  154 + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
  155 +
  156 + // 根据类型,获取出口连线
  157 + List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
  158 + if (sequenceFlows == null) {
  159 + return userTaskList;
  160 + }
  161 + // 循环找到目标元素
  162 + for (SequenceFlow sequenceFlow : sequenceFlows) {
  163 + // 如果发现连线重复,说明循环了,跳过这个循环
  164 + if (hasSequenceFlow.contains(sequenceFlow.getId())) {
  165 + continue;
  166 + }
  167 + // 添加已经走过的连线
  168 + hasSequenceFlow.add(sequenceFlow.getId());
  169 + // 如果为用户任务类型,且任务节点的 Key 正在运行的任务中存在,添加
  170 + if (sequenceFlow.getTargetFlowElement() instanceof UserTask) {
  171 + userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement());
  172 + continue;
  173 + }
  174 + // 如果节点为子流程节点情况,则从节点中的第一个节点开始获取
  175 + if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
  176 + List<UserTask> childUserTaskList = findChildProcessUserTaskList((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, null);
  177 + // 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续
  178 + if (CollUtil.isNotEmpty(childUserTaskList)) {
  179 + userTaskList.addAll(childUserTaskList);
  180 + continue;
  181 + }
  182 + }
  183 + // 继续迭代
  184 + userTaskList = findChildProcessUserTaskList(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, userTaskList);
  185 + }
  186 + return userTaskList;
  187 + }
  188 +
  189 +
  190 + /**
  191 + * 迭代从后向前扫描,判断目标节点相对于当前节点是否是串行
  192 + * 不存在直接回退到子流程中的情况,但存在从子流程出去到父流程情况
  193 + *
  194 + * @param source 起始节点
  195 + * @param target 目标节点
  196 + * @param visitedElements 已经经过的连线的 ID,用于判断线路是否重复
  197 + * @return 结果
  198 + */
  199 + public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) {
  200 + visitedElements = visitedElements == null ? new HashSet<>() : visitedElements;
  201 + // 不能是开始事件和子流程
  202 + if (source instanceof StartEvent && isInEventSubprocess(source)) {
  203 + return false;
  204 + }
  205 +
  206 + // 根据类型,获取入口连线
  207 + List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
  208 + if (CollUtil.isEmpty(sequenceFlows)) {
  209 + return true;
  210 + }
  211 + // 循环找到目标元素
  212 + for (SequenceFlow sequenceFlow : sequenceFlows) {
  213 + // 如果发现连线重复,说明循环了,跳过这个循环
  214 + if (visitedElements.contains(sequenceFlow.getId())) {
  215 + continue;
  216 + }
  217 + // 添加已经走过的连线
  218 + visitedElements.add(sequenceFlow.getId());
  219 + // 这条线路存在目标节点,这条线路完成,进入下个线路
  220 + FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
  221 + if (target.getId().equals(sourceFlowElement.getId())) {
  222 + continue;
  223 + }
  224 + // 如果目标节点为并行网关,则不继续
  225 + if (sourceFlowElement instanceof ParallelGateway) {
  226 + return false;
  227 + }
  228 + // 否则就继续迭代
  229 + if (!isSequentialReachable(sourceFlowElement, target, visitedElements)) {
  230 + return false;
  231 + }
  232 + }
  233 + return true;
  234 + }
  235 +
  236 + /**
  237 + * 判断当前节点是否属于不同的子流程
  238 + *
  239 + * @param flowElement 被判断的节点
  240 + * @return true 表示属于子流程
  241 + */
  242 + private static boolean isInEventSubprocess(FlowElement flowElement) {
  243 + FlowElementsContainer flowElementsContainer = flowElement.getParentContainer();
  244 + while (flowElementsContainer != null) {
  245 + if (flowElementsContainer instanceof EventSubProcess) {
  246 + return true;
  247 + }
  248 +
  249 + if (flowElementsContainer instanceof FlowElement) {
  250 + flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
  251 + } else {
  252 + flowElementsContainer = null;
  253 + }
  254 + }
  255 + return false;
  256 + }
  257 +
  258 + /**
  259 + * 根据正在运行的任务节点,迭代获取子级任务节点列表,向后找
  260 + *
  261 + * @param source 起始节点
  262 + * @param runTaskKeyList 正在运行的任务 Key,用于校验任务节点是否是正在运行的节点
  263 + * @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复
  264 + * @param userTaskList 需要撤回的用户任务列表
  265 + * @return 子级任务节点列表
  266 + */
  267 + public static List<UserTask> iteratorFindChildUserTasks(FlowElement source, List<String> runTaskKeyList,
  268 + Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
  269 + hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
  270 + userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
  271 + // 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代
  272 + if (source instanceof StartEvent && source.getSubProcess() != null) {
  273 + userTaskList = iteratorFindChildUserTasks(source.getSubProcess(), runTaskKeyList, hasSequenceFlow, userTaskList);
  274 + }
  275 +
  276 + // 根据类型,获取出口连线
  277 + List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
  278 + if (sequenceFlows == null) {
  279 + return userTaskList;
  280 + }
  281 + // 循环找到目标元素
  282 + for (SequenceFlow sequenceFlow : sequenceFlows) {
  283 + // 如果发现连线重复,说明循环了,跳过这个循环
  284 + if (hasSequenceFlow.contains(sequenceFlow.getId())) {
  285 + continue;
  286 + }
  287 + // 添加已经走过的连线
  288 + hasSequenceFlow.add(sequenceFlow.getId());
  289 + // 如果为用户任务类型,且任务节点的 Key 正在运行的任务中存在,添加
  290 + if (sequenceFlow.getTargetFlowElement() instanceof UserTask && runTaskKeyList.contains((sequenceFlow.getTargetFlowElement()).getId())) {
  291 + userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement());
  292 + continue;
  293 + }
  294 + // 如果节点为子流程节点情况,则从节点中的第一个节点开始获取
  295 + if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
  296 + List<UserTask> childUserTaskList = iteratorFindChildUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), runTaskKeyList, hasSequenceFlow, null);
  297 + // 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续
  298 + if (CollUtil.isNotEmpty(childUserTaskList)) {
  299 + userTaskList.addAll(childUserTaskList);
  300 + continue;
  301 + }
  302 + }
  303 + // 继续迭代
  304 + userTaskList = iteratorFindChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, hasSequenceFlow, userTaskList);
  305 + }
  306 + return userTaskList;
  307 + }
  308 +
  309 +}
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
1 package cn.iocoder.yudao.framework.flowable.core.util; 1 package cn.iocoder.yudao.framework.flowable.core.util;
2 2
3 -import org.flowable.bpmn.converter.BpmnXMLConverter;  
4 -import org.flowable.bpmn.model.BpmnModel;  
5 -import org.flowable.bpmn.model.FlowElement;  
6 import org.flowable.common.engine.impl.identity.Authentication; 3 import org.flowable.common.engine.impl.identity.Authentication;
7 4
8 -import java.util.ArrayList;  
9 -import java.util.Arrays;  
10 -import java.util.List;  
11 -  
12 /** 5 /**
13 * Flowable 相关的工具方法 6 * Flowable 相关的工具方法
14 * 7 *
@@ -26,49 +19,6 @@ public class FlowableUtils { @@ -26,49 +19,6 @@ public class FlowableUtils {
26 Authentication.setAuthenticatedUserId(null); 19 Authentication.setAuthenticatedUserId(null);
27 } 20 }
28 21
29 - // ========== BPMN 相关的工具方法 ==========  
30 -  
31 - /**  
32 - * 获得 BPMN 流程中,指定的元素们  
33 - *  
34 - * @param model  
35 - * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等  
36 - * @return 元素们  
37 - */  
38 - public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {  
39 - List<T> result = new ArrayList<>();  
40 - model.getProcesses().forEach(process -> {  
41 - process.getFlowElements().forEach(flowElement -> {  
42 - if (flowElement.getClass().isAssignableFrom(clazz)) {  
43 - result.add((T) flowElement);  
44 - }  
45 - });  
46 - });  
47 - return result;  
48 - }  
49 -  
50 - /**  
51 - * 比较 两个bpmnModel 是否相同  
52 - * @param oldModel 老的bpmn model  
53 - * @param newModel 新的bpmn model  
54 - */  
55 - public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {  
56 - // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较  
57 - return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));  
58 - }  
59 -  
60 - /**  
61 - * 把 bpmnModel 转换成 byte[]  
62 - * @param model bpmnModel  
63 - */  
64 - public static byte[] getBpmnBytes(BpmnModel model) {  
65 - if (model == null) {  
66 - return new byte[0];  
67 - }  
68 - BpmnXMLConverter converter = new BpmnXMLConverter();  
69 - return converter.convertToXML(model);  
70 - }  
71 -  
72 // ========== Execution 相关的工具方法 ========== 22 // ========== Execution 相关的工具方法 ==========
73 23
74 public static String formatCollectionVariable(String activityId) { 24 public static String formatCollectionVariable(String activityId) {
yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java
1 package cn.iocoder.yudao.framework.quartz.config; 1 package cn.iocoder.yudao.framework.quartz.config;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; 3 import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager;
  4 +import lombok.extern.slf4j.Slf4j;
4 import org.quartz.Scheduler; 5 import org.quartz.Scheduler;
5 import org.springframework.boot.autoconfigure.AutoConfiguration; 6 import org.springframework.boot.autoconfigure.AutoConfiguration;
6 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Bean;
7 import org.springframework.scheduling.annotation.EnableScheduling; 8 import org.springframework.scheduling.annotation.EnableScheduling;
8 9
  10 +import java.util.Optional;
  11 +
9 /** 12 /**
10 * 定时任务 Configuration 13 * 定时任务 Configuration
11 */ 14 */
12 @AutoConfiguration 15 @AutoConfiguration
13 @EnableScheduling // 开启 Spring 自带的定时任务 16 @EnableScheduling // 开启 Spring 自带的定时任务
  17 +@Slf4j
14 public class YudaoQuartzAutoConfiguration { 18 public class YudaoQuartzAutoConfiguration {
15 19
16 @Bean 20 @Bean
17 - public SchedulerManager schedulerManager(Scheduler scheduler) {  
18 - return new SchedulerManager(scheduler); 21 + public SchedulerManager schedulerManager(Optional<Scheduler> scheduler) {
  22 + if (!scheduler.isPresent()) {
  23 + log.info("[定时任务 - 已禁用][参考 https://doc.iocoder.cn/job/ 开启]");
  24 + return new SchedulerManager(null);
  25 + }
  26 + return new SchedulerManager(scheduler.get());
19 } 27 }
20 28
21 } 29 }
yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/scheduler/SchedulerManager.java
@@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.quartz.core.enums.JobDataKeyEnum; @@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.quartz.core.enums.JobDataKeyEnum;
4 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker; 4 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker;
5 import org.quartz.*; 5 import org.quartz.*;
6 6
  7 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
  8 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
  9 +
7 /** 10 /**
8 * {@link org.quartz.Scheduler} 的管理器,负责创建任务 11 * {@link org.quartz.Scheduler} 的管理器,负责创建任务
9 * 12 *
@@ -37,6 +40,7 @@ public class SchedulerManager { @@ -37,6 +40,7 @@ public class SchedulerManager {
37 public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression, 40 public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression,
38 Integer retryCount, Integer retryInterval) 41 Integer retryCount, Integer retryInterval)
39 throws SchedulerException { 42 throws SchedulerException {
  43 + validateScheduler();
40 // 创建 JobDetail 对象 44 // 创建 JobDetail 对象
41 JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class) 45 JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class)
42 .usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId) 46 .usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId)
@@ -61,6 +65,7 @@ public class SchedulerManager { @@ -61,6 +65,7 @@ public class SchedulerManager {
61 public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression, 65 public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression,
62 Integer retryCount, Integer retryInterval) 66 Integer retryCount, Integer retryInterval)
63 throws SchedulerException { 67 throws SchedulerException {
  68 + validateScheduler();
64 // 创建新 Trigger 对象 69 // 创建新 Trigger 对象
65 Trigger newTrigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval); 70 Trigger newTrigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval);
66 // 修改调度 71 // 修改调度
@@ -74,6 +79,7 @@ public class SchedulerManager { @@ -74,6 +79,7 @@ public class SchedulerManager {
74 * @throws SchedulerException 删除异常 79 * @throws SchedulerException 删除异常
75 */ 80 */
76 public void deleteJob(String jobHandlerName) throws SchedulerException { 81 public void deleteJob(String jobHandlerName) throws SchedulerException {
  82 + validateScheduler();
77 scheduler.deleteJob(new JobKey(jobHandlerName)); 83 scheduler.deleteJob(new JobKey(jobHandlerName));
78 } 84 }
79 85
@@ -84,6 +90,7 @@ public class SchedulerManager { @@ -84,6 +90,7 @@ public class SchedulerManager {
84 * @throws SchedulerException 暂停异常 90 * @throws SchedulerException 暂停异常
85 */ 91 */
86 public void pauseJob(String jobHandlerName) throws SchedulerException { 92 public void pauseJob(String jobHandlerName) throws SchedulerException {
  93 + validateScheduler();
87 scheduler.pauseJob(new JobKey(jobHandlerName)); 94 scheduler.pauseJob(new JobKey(jobHandlerName));
88 } 95 }
89 96
@@ -94,6 +101,7 @@ public class SchedulerManager { @@ -94,6 +101,7 @@ public class SchedulerManager {
94 * @throws SchedulerException 启动异常 101 * @throws SchedulerException 启动异常
95 */ 102 */
96 public void resumeJob(String jobHandlerName) throws SchedulerException { 103 public void resumeJob(String jobHandlerName) throws SchedulerException {
  104 + validateScheduler();
97 scheduler.resumeJob(new JobKey(jobHandlerName)); 105 scheduler.resumeJob(new JobKey(jobHandlerName));
98 scheduler.resumeTrigger(new TriggerKey(jobHandlerName)); 106 scheduler.resumeTrigger(new TriggerKey(jobHandlerName));
99 } 107 }
@@ -108,11 +116,12 @@ public class SchedulerManager { @@ -108,11 +116,12 @@ public class SchedulerManager {
108 */ 116 */
109 public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam) 117 public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam)
110 throws SchedulerException { 118 throws SchedulerException {
  119 + validateScheduler();
  120 + // 触发任务
111 JobDataMap data = new JobDataMap(); // 无需重试,所以不设置 retryCount 和 retryInterval 121 JobDataMap data = new JobDataMap(); // 无需重试,所以不设置 retryCount 和 retryInterval
112 data.put(JobDataKeyEnum.JOB_ID.name(), jobId); 122 data.put(JobDataKeyEnum.JOB_ID.name(), jobId);
113 data.put(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName); 123 data.put(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName);
114 data.put(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam); 124 data.put(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam);
115 - // 触发任务  
116 scheduler.triggerJob(new JobKey(jobHandlerName), data); 125 scheduler.triggerJob(new JobKey(jobHandlerName), data);
117 } 126 }
118 127
@@ -127,4 +136,11 @@ public class SchedulerManager { @@ -127,4 +136,11 @@ public class SchedulerManager {
127 .build(); 136 .build();
128 } 137 }
129 138
  139 + private void validateScheduler() {
  140 + if (scheduler == null) {
  141 + throw exception0(NOT_IMPLEMENTED.getCode(),
  142 + "[定时任务 - 已禁用][参考 https://doc.iocoder.cn/job/ 开启]");
  143 + }
  144 + }
  145 +
130 } 146 }
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
7 import com.baomidou.mybatisplus.core.conditions.Wrapper; 7 import com.baomidou.mybatisplus.core.conditions.Wrapper;
8 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 8 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 9 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
10 -import com.baomidou.mybatisplus.core.mapper.BaseMapper;  
11 import com.baomidou.mybatisplus.core.metadata.IPage; 10 import com.baomidou.mybatisplus.core.metadata.IPage;
12 import com.baomidou.mybatisplus.core.toolkit.support.SFunction; 11 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
13 import com.baomidou.mybatisplus.extension.toolkit.Db; 12 import com.baomidou.mybatisplus.extension.toolkit.Db;
yudao-framework/yudao-spring-boot-starter-protection/pom.xml
@@ -26,11 +26,13 @@ @@ -26,11 +26,13 @@
26 <dependency> 26 <dependency>
27 <groupId>com.baomidou</groupId> 27 <groupId>com.baomidou</groupId>
28 <artifactId>lock4j-redisson-spring-boot-starter</artifactId> 28 <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
  29 + <optional>true</optional>
29 </dependency> 30 </dependency>
30 31
31 <dependency> 32 <dependency>
32 <groupId>io.github.resilience4j</groupId> 33 <groupId>io.github.resilience4j</groupId>
33 <artifactId>resilience4j-spring-boot2</artifactId> 34 <artifactId>resilience4j-spring-boot2</artifactId>
  35 + <optional>true</optional>
34 </dependency> 36 </dependency>
35 </dependencies> 37 </dependencies>
36 38
yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java
@@ -3,9 +3,11 @@ package cn.iocoder.yudao.framework.lock4j.config; @@ -3,9 +3,11 @@ package cn.iocoder.yudao.framework.lock4j.config;
3 import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy; 3 import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
4 import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration; 4 import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
5 import org.springframework.boot.autoconfigure.AutoConfiguration; 5 import org.springframework.boot.autoconfigure.AutoConfiguration;
  6 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
6 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Bean;
7 8
8 @AutoConfiguration(before = LockAutoConfiguration.class) 9 @AutoConfiguration(before = LockAutoConfiguration.class)
  10 +@ConditionalOnClass(name = "com.baomidou.lock.annotation.Lock4j")
9 public class YudaoLock4jConfiguration { 11 public class YudaoLock4jConfiguration {
10 12
11 @Bean 13 @Bean
yudao-framework/yudao-spring-boot-starter-redis/pom.xml
@@ -33,12 +33,6 @@ @@ -33,12 +33,6 @@
33 </dependency> 33 </dependency>
34 34
35 <dependency> 35 <dependency>
36 - <groupId>io.netty</groupId>  
37 - <artifactId>netty-all</artifactId>  
38 - </dependency>  
39 -  
40 -  
41 - <dependency>  
42 <groupId>com.fasterxml.jackson.datatype</groupId> 36 <groupId>com.fasterxml.jackson.datatype</groupId>
43 <artifactId>jackson-datatype-jsr310</artifactId> 37 <artifactId>jackson-datatype-jsr310</artifactId>
44 </dependency> 38 </dependency>
yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/TimeoutRedisCacheManager.java
@@ -45,7 +45,7 @@ public class TimeoutRedisCacheManager extends RedisCacheManager { @@ -45,7 +45,7 @@ public class TimeoutRedisCacheManager extends RedisCacheManager {
45 Duration duration = parseDuration(names[1]); 45 Duration duration = parseDuration(names[1]);
46 cacheConfig = cacheConfig.entryTtl(duration); 46 cacheConfig = cacheConfig.entryTtl(duration);
47 } 47 }
48 - return super.createRedisCache(names[0], cacheConfig); 48 + return super.createRedisCache(name, cacheConfig);
49 } 49 }
50 50
51 /** 51 /**
yudao-framework/yudao-spring-boot-starter-web/pom.xml
@@ -55,13 +55,6 @@ @@ -55,13 +55,6 @@
55 <version>${revision}</version> 55 <version>${revision}</version>
56 </dependency> 56 </dependency>
57 57
58 - <!-- 服务保障相关 -->  
59 - <dependency>  
60 - <groupId>io.github.resilience4j</groupId>  
61 - <artifactId>resilience4j-ratelimiter</artifactId>  
62 - <scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 -->  
63 - </dependency>  
64 -  
65 <!-- xss --> 58 <!-- xss -->
66 <dependency> 59 <dependency>
67 <groupId>org.jsoup</groupId> 60 <groupId>org.jsoup</groupId>
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
1 package cn.iocoder.yudao.framework.jackson.config; 1 package cn.iocoder.yudao.framework.jackson.config;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer; 5 import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
5 import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer; 6 import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
@@ -11,51 +12,41 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; @@ -11,51 +12,41 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
11 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; 12 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
12 import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; 13 import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
13 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
14 -import org.springframework.beans.BeansException;  
15 -import org.springframework.beans.factory.config.BeanPostProcessor;  
16 import org.springframework.boot.autoconfigure.AutoConfiguration; 15 import org.springframework.boot.autoconfigure.AutoConfiguration;
17 import org.springframework.context.annotation.Bean; 16 import org.springframework.context.annotation.Bean;
18 17
19 import java.time.LocalDate; 18 import java.time.LocalDate;
20 import java.time.LocalDateTime; 19 import java.time.LocalDateTime;
21 import java.time.LocalTime; 20 import java.time.LocalTime;
  21 +import java.util.List;
22 22
23 @AutoConfiguration 23 @AutoConfiguration
24 @Slf4j 24 @Slf4j
25 public class YudaoJacksonAutoConfiguration { 25 public class YudaoJacksonAutoConfiguration {
26 26
27 @Bean 27 @Bean
28 - public BeanPostProcessor objectMapperBeanPostProcessor() {  
29 - return new BeanPostProcessor() {  
30 -  
31 - @Override  
32 - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
33 - if (!(bean instanceof ObjectMapper)) {  
34 - return bean;  
35 - }  
36 - ObjectMapper objectMapper = (ObjectMapper) bean;  
37 - SimpleModule simpleModule = new SimpleModule();  
38 - /*  
39 - * 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型  
40 - * 2. 新增LocalDateTime序列化、反序列化规则  
41 - */  
42 - simpleModule  
43 - .addSerializer(Long.class, NumberSerializer.INSTANCE)  
44 - .addSerializer(Long.TYPE, NumberSerializer.INSTANCE)  
45 - .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)  
46 - .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)  
47 - .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)  
48 - .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)  
49 - .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)  
50 - .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);  
51 -  
52 - objectMapper.registerModules(simpleModule);  
53 -  
54 - JsonUtils.init(objectMapper);  
55 - log.info("初始化 jackson 自动配置");  
56 - return bean;  
57 - }  
58 - }; 28 + @SuppressWarnings("InstantiationOfUtilityClass")
  29 + public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
  30 + // 1.1 创建 SimpleModule 对象
  31 + SimpleModule simpleModule = new SimpleModule();
  32 + simpleModule
  33 + // 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
  34 + .addSerializer(Long.class, NumberSerializer.INSTANCE)
  35 + .addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
  36 + .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
  37 + .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
  38 + .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
  39 + .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
  40 + // 新增 LocalDateTime 序列化、反序列化规则
  41 + .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
  42 + .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
  43 + // 1.2 注册到 objectMapper
  44 + objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
  45 +
  46 + // 2. 设置 objectMapper 到 JsonUtils {
  47 + JsonUtils.init(CollUtil.getFirst(objectMappers));
  48 + log.info("[init][初始化 JsonUtils 成功]");
  49 + return new JsonUtils();
59 } 50 }
60 51
61 } 52 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
@@ -11,7 +11,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -11,7 +11,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
11 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 11 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
12 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 12 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
13 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; 13 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
14 -import io.github.resilience4j.ratelimiter.RequestNotPermitted;  
15 import lombok.AllArgsConstructor; 14 import lombok.AllArgsConstructor;
16 import lombok.extern.slf4j.Slf4j; 15 import lombok.extern.slf4j.Slf4j;
17 import org.apache.commons.lang3.exception.ExceptionUtils; 16 import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -33,6 +32,7 @@ import javax.validation.ConstraintViolationException; @@ -33,6 +32,7 @@ import javax.validation.ConstraintViolationException;
33 import javax.validation.ValidationException; 32 import javax.validation.ValidationException;
34 import java.time.LocalDateTime; 33 import java.time.LocalDateTime;
35 import java.util.Map; 34 import java.util.Map;
  35 +import java.util.Objects;
36 36
37 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*; 37 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*;
38 38
@@ -83,9 +83,6 @@ public class GlobalExceptionHandler { @@ -83,9 +83,6 @@ public class GlobalExceptionHandler {
83 if (ex instanceof HttpRequestMethodNotSupportedException) { 83 if (ex instanceof HttpRequestMethodNotSupportedException) {
84 return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); 84 return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
85 } 85 }
86 - if (ex instanceof RequestNotPermitted) {  
87 - return requestNotPermittedExceptionHandler(request, (RequestNotPermitted) ex);  
88 - }  
89 if (ex instanceof ServiceException) { 86 if (ex instanceof ServiceException) {
90 return serviceExceptionHandler((ServiceException) ex); 87 return serviceExceptionHandler((ServiceException) ex);
91 } 88 }
@@ -186,8 +183,7 @@ public class GlobalExceptionHandler { @@ -186,8 +183,7 @@ public class GlobalExceptionHandler {
186 /** 183 /**
187 * 处理 Resilience4j 限流抛出的异常 184 * 处理 Resilience4j 限流抛出的异常
188 */ 185 */
189 - @ExceptionHandler(value = RequestNotPermitted.class)  
190 - public CommonResult<?> requestNotPermittedExceptionHandler(HttpServletRequest req, RequestNotPermitted ex) { 186 + public CommonResult<?> requestNotPermittedExceptionHandler(HttpServletRequest req, Throwable ex) {
191 log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex); 187 log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex);
192 return CommonResult.error(TOO_MANY_REQUESTS); 188 return CommonResult.error(TOO_MANY_REQUESTS);
193 } 189 }
@@ -226,7 +222,12 @@ public class GlobalExceptionHandler { @@ -226,7 +222,12 @@ public class GlobalExceptionHandler {
226 return tableNotExistsResult; 222 return tableNotExistsResult;
227 } 223 }
228 224
229 - // 情况二:处理异常 225 + // 情况二:部分特殊的库的处理
  226 + if (Objects.equals("io.github.resilience4j.ratelimiter.RequestNotPermitted", ex.getClass().getName())) {
  227 + return requestNotPermittedExceptionHandler(req, ex);
  228 + }
  229 +
  230 + // 情况三:处理异常
230 log.error("[defaultExceptionHandler]", ex); 231 log.error("[defaultExceptionHandler]", ex);
231 // 插入异常日志 232 // 插入异常日志
232 this.createExceptionLog(req, ex); 233 this.createExceptionLog(req, ex);
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java
@@ -21,6 +21,7 @@ import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.cr @@ -21,6 +21,7 @@ import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.cr
21 21
22 @AutoConfiguration 22 @AutoConfiguration
23 @EnableConfigurationProperties(XssProperties.class) 23 @EnableConfigurationProperties(XssProperties.class)
  24 +@ConditionalOnProperty(prefix = "yudao.xss", name = "enable", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用
24 public class YudaoXssAutoConfiguration implements WebMvcConfigurer { 25 public class YudaoXssAutoConfiguration implements WebMvcConfigurer {
25 26
26 /** 27 /**
yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration 1 cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration
2 cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration 2 cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration
3 -com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration  
4 cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration 3 cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
5 cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration 4 cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
6 cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration 5 cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -4,61 +4,66 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -4,61 +4,66 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 4
5 /** 5 /**
6 * Bpm 错误码枚举类 6 * Bpm 错误码枚举类
7 - * 7 + * <p>
8 * bpm 系统,使用 1-009-000-000 段 8 * bpm 系统,使用 1-009-000-000 段
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== 通用流程处理 模块 1009000000 ==========  
13 - ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1009000002, "获取高亮流程图异常"); 12 + // ========== 通用流程处理 模块 1-009-000-000 ==========
  13 + ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1_009_000_002, "获取高亮流程图异常");
14 14
15 - // ========== OA 流程模块 1009001000 ==========  
16 - ErrorCode OA_LEAVE_NOT_EXISTS = new ErrorCode(1009001001, "请假申请不存在");  
17 - ErrorCode OA_PM_POST_NOT_EXISTS = new ErrorCode(1009001002, "项目经理岗位未设置");  
18 - ErrorCode OA_DEPART_PM_POST_NOT_EXISTS = new ErrorCode(1009001009, "部门的项目经理不存在");  
19 - ErrorCode OA_BM_POST_NOT_EXISTS = new ErrorCode(1009001004, "部门经理岗位未设置");  
20 - ErrorCode OA_DEPART_BM_POST_NOT_EXISTS = new ErrorCode(1009001005, "部门的部门经理不存在");  
21 - ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1009001006, "HR岗位未设置");  
22 - ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1009001007, "请假天数必须>=1"); 15 + // ========== OA 流程模块 1-009-001-000 ==========
  16 + ErrorCode OA_LEAVE_NOT_EXISTS = new ErrorCode(1_009_001_001, "请假申请不存在");
  17 + ErrorCode OA_PM_POST_NOT_EXISTS = new ErrorCode(1_009_001_002, "项目经理岗位未设置");
  18 + ErrorCode OA_DEPART_PM_POST_NOT_EXISTS = new ErrorCode(1_009_001_009, "部门的项目经理不存在");
  19 + ErrorCode OA_BM_POST_NOT_EXISTS = new ErrorCode(1_009_001_004, "部门经理岗位未设置");
  20 + ErrorCode OA_DEPART_BM_POST_NOT_EXISTS = new ErrorCode(1_009_001_005, "部门的部门经理不存在");
  21 + ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1_009_001_006, "HR岗位未设置");
  22 + ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1_009_001_007, "请假天数必须>=1");
23 23
24 - // ========== 流程模型 1009002000 ==========  
25 - ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1009002000, "已经存在流程标识为【{}】的流程");  
26 - ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1009002001, "流程模型不存在");  
27 - ErrorCode MODEL_KEY_VALID = new ErrorCode(1009002002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");  
28 - ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1009002003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");  
29 - ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1009002004, "部署流程失败," + 24 + // ========== 流程模型 1-009-002-000 ==========
  25 + ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1_009_002_000, "已经存在流程标识为【{}】的流程");
  26 + ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_009_002_001, "流程模型不存在");
  27 + ErrorCode MODEL_KEY_VALID = new ErrorCode(1_009_002_002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
  28 + ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1_009_002_003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
  29 + ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," +
30 "原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置"); 30 "原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置");
31 - ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1009003005, "流程定义部署失败,原因:信息未发生变化"); 31 + ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1_009_003_005, "流程定义部署失败,原因:信息未发生变化");
32 32
33 - // ========== 流程定义 1009003000 ==========  
34 - ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");  
35 - ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");  
36 - ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");  
37 - ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003003, "流程定义处于挂起状态");  
38 - ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009003004, "流程定义的模型不存在"); 33 + // ========== 流程定义 1-009-003-000 ==========
  34 + ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1_009_003_000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
  35 + ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1_009_003_001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
  36 + ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_009_003_002, "流程定义不存在");
  37 + ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1_009_003_003, "流程定义处于挂起状态");
  38 + ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1_009_003_004, "流程定义的模型不存在");
39 39
40 - // ========== 流程实例 1009004000 ==========  
41 - ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在");  
42 - ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1009004001, "流程取消失败,流程不处于运行中");  
43 - ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1009004002, "流程取消失败,该流程不是你发起的"); 40 + // ========== 流程实例 1-009-004-000 ==========
  41 + ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1_009_004_000, "流程实例不存在");
  42 + ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1_009_004_001, "流程取消失败,流程不处于运行中");
  43 + ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1_009_004_002, "流程取消失败,该流程不是你发起的");
44 44
45 - // ========== 流程任务 1009005000 ==========  
46 - ErrorCode TASK_COMPLETE_FAIL_NOT_EXISTS = new ErrorCode(1009005000, "审批任务失败,原因:该任务不处于未审批");  
47 - ErrorCode TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1009005001, "审批任务失败,原因:该任务的审批人不是你"); 45 + // ========== 流程任务 1-009-005-000 ==========
  46 + ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
  47 + ErrorCode TASK_NOT_EXISTS = new ErrorCode(1_009_005_002, "流程任务不存在");
  48 + ErrorCode TASK_IS_PENDING = new ErrorCode(1_009_005_003, "当前任务处于挂起状态,不能操作");
  49 + ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_004, " 目标节点不存在");
  50 + ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
  51 + ErrorCode TASK_DELEGATE_FAIL_USER_REPEAT = new ErrorCode(1_009_005_007, "任务委派失败,委派人和当前审批人为同一人");
  52 + ErrorCode TASK_DELEGATE_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_008, "任务委派失败,被委派人不存在");
48 53
49 - // ========== 流程任务分配规则 1009006000 ==========  
50 - ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1009006000, "流程({}) 的任务({}) 已经存在分配规则");  
51 - ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1009006001, "流程任务分配规则不存在");  
52 - ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1009006002, "只有流程模型的任务分配规则,才允许被修改");  
53 - ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1009006003, "操作失败,原因:找不到任务的审批人!");  
54 - ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1009006004, "操作失败,原因:任务分配脚本({}) 不存在"); 54 + // ========== 流程任务分配规则 1-009-006-000 ==========
  55 + ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1_009_006_000, "流程({}) 的任务({}) 已经存在分配规则");
  56 + ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1_009_006_001, "流程任务分配规则不存在");
  57 + ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1_009_006_002, "只有流程模型的任务分配规则,才允许被修改");
  58 + ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
  59 + ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1_009_006_004, "操作失败,原因:任务分配脚本({}) 不存在");
55 60
56 - // ========== 动态表单模块 1009010000 ==========  
57 - ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在");  
58 - ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009010001, "表单项({}) 和 ({}) 使用了相同的字段名({})"); 61 + // ========== 动态表单模块 1-009-010-000 ==========
  62 + ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
  63 + ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1_009_010_001, "表单项({}) 和 ({}) 使用了相同的字段名({})");
59 64
60 - // ========== 用户组模块 1009011000 ==========  
61 - ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1009011000, "用户组不存在");  
62 - ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1009011001, "名字为【{}】的用户组已被禁用"); 65 + // ========== 用户组模块 1-009-011-000 ==========
  66 + ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1_009_011_000, "用户组不存在");
  67 + ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1_009_011_001, "名字为【{}】的用户组已被禁用");
63 68
64 } 69 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java
@@ -20,7 +20,8 @@ public enum BpmProcessInstanceResultEnum { @@ -20,7 +20,8 @@ public enum BpmProcessInstanceResultEnum {
20 20
21 // ========== 流程任务独有的状态 ========== 21 // ========== 流程任务独有的状态 ==========
22 22
23 - BACK(5, "退回/驳回"); 23 + BACK(5, "驳回"), // 退回
  24 + DELEGATE(6, "委派");
24 25
25 /** 26 /**
26 * 结果 27 * 结果
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
@@ -75,4 +75,29 @@ public class BpmTaskController { @@ -75,4 +75,29 @@ public class BpmTaskController {
75 return success(true); 75 return success(true);
76 } 76 }
77 77
  78 + @GetMapping("/get-return-list")
  79 + @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮")
  80 + @Parameter(name = "taskId", description = "当前任务ID", required = true)
  81 + @PreAuthorize("@ss.hasPermission('bpm:task:update')")
  82 + public CommonResult<List<BpmTaskSimpleRespVO>> getReturnList(@RequestParam("taskId") String taskId) {
  83 + return success(taskService.getReturnTaskList(taskId));
  84 + }
  85 +
  86 + @PutMapping("/return")
  87 + @Operation(summary = "回退任务", description = "用于【流程详情】的【回退】按钮")
  88 + @PreAuthorize("@ss.hasPermission('bpm:task:update')")
  89 + public CommonResult<Boolean> returnTask(@Valid @RequestBody BpmTaskReturnReqVO reqVO) {
  90 + taskService.returnTask(getLoginUserId(), reqVO);
  91 + return success(true);
  92 + }
  93 +
  94 + @PutMapping("/delegate")
  95 + @Operation(summary = "委派任务", description = "用于【流程详情】的【委派】按钮。和向前【加签】有点像,唯一区别是【委托】没有单独创立任务")
  96 + @PreAuthorize("@ss.hasPermission('bpm:task:update')")
  97 + public CommonResult<Boolean> delegateTask(@Valid @RequestBody BpmTaskDelegateReqVO reqVO) {
  98 + // TODO @海:, 后面要有空格
  99 + taskService.delegateTask(reqVO,getLoginUserId());
  100 + return success(true);
  101 + }
  102 +
78 } 103 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDelegateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@Schema(description = "管理后台 - 委派流程任务的 Request VO")
  10 +@Data
  11 +public class BpmTaskDelegateReqVO {
  12 +
  13 + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  14 + @NotEmpty(message = "任务编号不能为空")
  15 + private String id;
  16 +
  17 + @Schema(description = "被委派人 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  18 + @NotNull(message = "被委派人 ID 不能为空")
  19 + private Long delegateUserId;
  20 +
  21 + @Schema(description = "委派原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "做不了决定,需要你先帮忙瞅瞅")
  22 + @NotEmpty(message = "委派原因不能为空")
  23 + private String reason;
  24 +
  25 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +
  8 +@Schema(description = "管理后台 - 回退流程任务的 Request VO")
  9 +@Data
  10 +public class BpmTaskReturnReqVO {
  11 +
  12 + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  13 + @NotEmpty(message = "任务编号不能为空")
  14 + private String id;
  15 +
  16 + @Schema(description = "回退到的任务 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + @NotEmpty(message = "回退到的任务 Key 不能为空")
  18 + private String targetDefinitionKey;
  19 +
  20 + @Schema(description = "回退意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "我就是想驳回")
  21 + @NotEmpty(message = "回退意见不能为空")
  22 + private String reason;
  23 +
  24 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSimpleRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - 流程任务的精简 Response VO")
  7 +@Data
  8 +public class BpmTaskSimpleRespVO {
  9 +
  10 + @Schema(description = "任务定义的标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "Activity_one")
  11 + private String definitionKey;
  12 +
  13 + @Schema(description = "任务名词", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批")
  14 + private String name;
  15 +
  16 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -6,11 +6,13 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils; @@ -6,11 +6,13 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils;
6 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 6 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO; 7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; 8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskSimpleRespVO;
9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO; 10 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
10 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; 11 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
11 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; 12 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
12 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 13 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
13 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 14 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  15 +import org.flowable.bpmn.model.FlowElement;
14 import org.flowable.common.engine.impl.db.SuspensionState; 16 import org.flowable.common.engine.impl.db.SuspensionState;
15 import org.flowable.engine.history.HistoricProcessInstance; 17 import org.flowable.engine.history.HistoricProcessInstance;
16 import org.flowable.engine.runtime.ProcessInstance; 18 import org.flowable.engine.runtime.ProcessInstance;
@@ -55,8 +57,8 @@ public interface BpmTaskConvert { @@ -55,8 +57,8 @@ public interface BpmTaskConvert {
55 } 57 }
56 58
57 default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks, 59 default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
58 - Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,  
59 - Map<Long, AdminUserRespDTO> userMap) { 60 + Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,
  61 + Map<Long, AdminUserRespDTO> userMap) {
60 return CollectionUtils.convertList(tasks, task -> { 62 return CollectionUtils.convertList(tasks, task -> {
61 BpmTaskDonePageItemRespVO respVO = convert2(task); 63 BpmTaskDonePageItemRespVO respVO = convert2(task);
62 BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId()); 64 BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
@@ -82,8 +84,8 @@ public interface BpmTaskConvert { @@ -82,8 +84,8 @@ public interface BpmTaskConvert {
82 BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser); 84 BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
83 85
84 default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks, 86 default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks,
85 - Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,  
86 - Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) { 87 + Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,
  88 + Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
87 return CollectionUtils.convertList(tasks, task -> { 89 return CollectionUtils.convertList(tasks, task -> {
88 BpmTaskRespVO respVO = convert3(task); 90 BpmTaskRespVO respVO = convert3(task);
89 BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId()); 91 BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
@@ -113,29 +115,34 @@ public interface BpmTaskConvert { @@ -113,29 +115,34 @@ public interface BpmTaskConvert {
113 void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to); 115 void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
114 116
115 @Mappings({@Mapping(source = "processInstance.id", target = "id"), 117 @Mappings({@Mapping(source = "processInstance.id", target = "id"),
116 - @Mapping(source = "processInstance.name", target = "name"),  
117 - @Mapping(source = "processInstance.startUserId", target = "startUserId"),  
118 - @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),  
119 - @Mapping(source = "startUser.nickname", target = "startUserNickname")}) 118 + @Mapping(source = "processInstance.name", target = "name"),
  119 + @Mapping(source = "processInstance.startUserId", target = "startUserId"),
  120 + @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
  121 + @Mapping(source = "startUser.nickname", target = "startUserNickname")})
120 BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, 122 BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance,
121 - AdminUserRespDTO startUser); 123 + AdminUserRespDTO startUser);
122 124
123 default BpmTaskExtDO convert2TaskExt(Task task) { 125 default BpmTaskExtDO convert2TaskExt(Task task) {
124 BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId()) 126 BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId())
125 - .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())  
126 - .setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId()); 127 + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())
  128 + .setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId());
127 taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime())); 129 taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime()));
128 return taskExtDO; 130 return taskExtDO;
129 } 131 }
130 132
131 default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, 133 default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
132 - Task task) { 134 + Task task) {
133 BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); 135 BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
134 reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId()) 136 reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
135 - .setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId())  
136 - .setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName())  
137 - .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())); 137 + .setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId())
  138 + .setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName())
  139 + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
138 return reqDTO; 140 return reqDTO;
139 } 141 }
140 142
  143 + default List<BpmTaskSimpleRespVO> convertList(List<? extends FlowElement> elementList) {
  144 + return CollectionUtils.convertList(elementList, element -> new BpmTaskSimpleRespVO()
  145 + .setName(element.getName())
  146 + .setDefinitionKey(element.getId()));
  147 + }
141 } 148 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
@@ -74,4 +74,12 @@ public interface BpmModelService { @@ -74,4 +74,12 @@ public interface BpmModelService {
74 */ 74 */
75 BpmnModel getBpmnModel(String id); 75 BpmnModel getBpmnModel(String id);
76 76
  77 + /**
  78 + * 获得流程定义编号对应的 BPMN Model
  79 + *
  80 + * @param processDefinitionId 流程定义编号
  81 + * @return BPMN Model
  82 + */
  83 + BpmnModel getBpmnModelByDefinitionId(String processDefinitionId);
  84 +
77 } 85 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -233,6 +233,11 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -233,6 +233,11 @@ public class BpmModelServiceImpl implements BpmModelService {
233 return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true); 233 return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
234 } 234 }
235 235
  236 + @Override
  237 + public BpmnModel getBpmnModelByDefinitionId(String processDefinitionId) {
  238 + return repositoryService.getBpmnModel(processDefinitionId);
  239 + }
  240 +
236 private void checkKeyNCName(String key) { 241 private void checkKeyNCName(String key) {
237 if (!ValidationUtils.isXmlNCName(key)) { 242 if (!ValidationUtils.isXmlNCName(key)) {
238 throw exception(MODEL_KEY_VALID); 243 throw exception(MODEL_KEY_VALID);
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil; @@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 7 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
8 -import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; 8 +import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; 9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
@@ -200,7 +200,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -200,7 +200,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
200 BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes()); 200 BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
201 BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId()); 201 BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
202 // 对比字节变化 202 // 对比字节变化
203 - if (!FlowableUtils.equals(oldModel, newModel)) { 203 + if (!BpmnModelUtils.equals(oldModel, newModel)) {
204 return false; 204 return false;
205 } 205 }
206 // 最终发现都一致,则返回 true 206 // 最终发现都一致,则返回 true
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
9 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; 9 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
10 -import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; 10 +import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
12 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; 12 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
13 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; 13 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
@@ -114,7 +114,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -114,7 +114,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
114 return Collections.emptyList(); 114 return Collections.emptyList();
115 } 115 }
116 // 获得用户任务,只有用户任务才可以设置分配规则 116 // 获得用户任务,只有用户任务才可以设置分配规则
117 - List<UserTask> userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class); 117 + List<UserTask> userTasks = BpmnModelUtils.getBpmnModelElements(model, UserTask.class);
118 if (CollUtil.isEmpty(userTasks)) { 118 if (CollUtil.isEmpty(userTasks)) {
119 return Collections.emptyList(); 119 return Collections.emptyList();
120 } 120 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
1 package cn.iocoder.yudao.module.bpm.service.task; 1 package cn.iocoder.yudao.module.bpm.service.task;
2 2
3 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 5 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
@@ -23,7 +22,6 @@ public interface BpmTaskService { @@ -23,7 +22,6 @@ public interface BpmTaskService {
23 * 22 *
24 * @param userId 用户编号 23 * @param userId 用户编号
25 * @param pageReqVO 分页请求 24 * @param pageReqVO 分页请求
26 - *  
27 * @return 流程任务分页 25 * @return 流程任务分页
28 */ 26 */
29 PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO); 27 PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
@@ -33,7 +31,6 @@ public interface BpmTaskService { @@ -33,7 +31,6 @@ public interface BpmTaskService {
33 * 31 *
34 * @param userId 用户编号 32 * @param userId 用户编号
35 * @param pageReqVO 分页请求 33 * @param pageReqVO 分页请求
36 - *  
37 * @return 流程任务分页 34 * @return 流程任务分页
38 */ 35 */
39 PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO); 36 PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
@@ -42,19 +39,17 @@ public interface BpmTaskService { @@ -42,19 +39,17 @@ public interface BpmTaskService {
42 * 获得流程任务 Map 39 * 获得流程任务 Map
43 * 40 *
44 * @param processInstanceIds 流程实例的编号数组 41 * @param processInstanceIds 流程实例的编号数组
45 - *  
46 * @return 流程任务 Map 42 * @return 流程任务 Map
47 */ 43 */
48 default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) { 44 default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
49 return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds), 45 return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
50 - Task::getProcessInstanceId); 46 + Task::getProcessInstanceId);
51 } 47 }
52 48
53 /** 49 /**
54 * 获得流程任务列表 50 * 获得流程任务列表
55 * 51 *
56 * @param processInstanceIds 流程实例的编号数组 52 * @param processInstanceIds 流程实例的编号数组
57 - *  
58 * @return 流程任务列表 53 * @return 流程任务列表
59 */ 54 */
60 List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds); 55 List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
@@ -63,7 +58,6 @@ public interface BpmTaskService { @@ -63,7 +58,6 @@ public interface BpmTaskService {
63 * 获得指令流程实例的流程任务列表,包括所有状态的 58 * 获得指令流程实例的流程任务列表,包括所有状态的
64 * 59 *
65 * @param processInstanceId 流程实例的编号 60 * @param processInstanceId 流程实例的编号
66 - *  
67 * @return 流程任务列表 61 * @return 流程任务列表
68 */ 62 */
69 List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId); 63 List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
@@ -128,4 +122,29 @@ public interface BpmTaskService { @@ -128,4 +122,29 @@ public interface BpmTaskService {
128 */ 122 */
129 void updateTaskExtAssign(Task task); 123 void updateTaskExtAssign(Task task);
130 124
  125 + /**
  126 + * 获取当前任务的可回退的流程集合
  127 + *
  128 + * @param taskId 当前的任务 ID
  129 + * @return 可以回退的节点列表
  130 + */
  131 + List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId);
  132 +
  133 + /**
  134 + * 将任务回退到指定的 targetDefinitionKey 位置
  135 + *
  136 + * @param userId 用户编号
  137 + * @param reqVO 回退的任务key和当前所在的任务ID
  138 + */
  139 + void returnTask(Long userId, BpmTaskReturnReqVO reqVO);
  140 +
  141 + // TODO @海:userId 放前面
  142 + /**
  143 + * 将指定任务委派给其他人处理,等接收人处理后再回到原审批人手中审批
  144 + *
  145 + * @param reqVO 被委派人和被委派的任务编号理由参数
  146 + * @param userId 用户编号
  147 + */
  148 + void delegateTask(BpmTaskDelegateReqVO reqVO, Long userId);
  149 +
131 } 150 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
1 package cn.iocoder.yudao.module.bpm.service.task; 1 package cn.iocoder.yudao.module.bpm.service.task;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.collection.ListUtil;  
5 import cn.hutool.core.util.ArrayUtil; 4 import cn.hutool.core.util.ArrayUtil;
6 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 7 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
9 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 8 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
10 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 9 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
  10 +import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
  11 +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
11 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 12 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
12 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; 13 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
13 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; 14 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
14 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; 15 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
15 import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; 16 import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
16 import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; 17 import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  18 +import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
17 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; 19 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
18 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 20 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
19 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 21 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
20 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 22 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
21 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 23 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
22 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
  25 +import org.flowable.bpmn.model.BpmnModel;
  26 +import org.flowable.bpmn.model.FlowElement;
  27 +import org.flowable.bpmn.model.UserTask;
23 import org.flowable.engine.HistoryService; 28 import org.flowable.engine.HistoryService;
  29 +import org.flowable.engine.RuntimeService;
24 import org.flowable.engine.TaskService; 30 import org.flowable.engine.TaskService;
25 import org.flowable.engine.history.HistoricProcessInstance; 31 import org.flowable.engine.history.HistoricProcessInstance;
26 import org.flowable.engine.runtime.ProcessInstance; 32 import org.flowable.engine.runtime.ProcessInstance;
  33 +import org.flowable.task.api.DelegationState;
27 import org.flowable.task.api.Task; 34 import org.flowable.task.api.Task;
28 import org.flowable.task.api.TaskQuery; 35 import org.flowable.task.api.TaskQuery;
29 import org.flowable.task.api.history.HistoricTaskInstance; 36 import org.flowable.task.api.history.HistoricTaskInstance;
@@ -32,6 +39,7 @@ import org.springframework.stereotype.Service; @@ -32,6 +39,7 @@ import org.springframework.stereotype.Service;
32 import org.springframework.transaction.annotation.Transactional; 39 import org.springframework.transaction.annotation.Transactional;
33 import org.springframework.transaction.support.TransactionSynchronization; 40 import org.springframework.transaction.support.TransactionSynchronization;
34 import org.springframework.transaction.support.TransactionSynchronizationManager; 41 import org.springframework.transaction.support.TransactionSynchronizationManager;
  42 +import org.springframework.util.Assert;
35 43
36 import javax.annotation.Resource; 44 import javax.annotation.Resource;
37 import javax.validation.Valid; 45 import javax.validation.Valid;
@@ -39,8 +47,7 @@ import java.time.LocalDateTime; @@ -39,8 +47,7 @@ import java.time.LocalDateTime;
39 import java.util.*; 47 import java.util.*;
40 48
41 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 49 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
42 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
43 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 50 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
44 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; 51 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
45 52
46 /** 53 /**
@@ -57,23 +64,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -57,23 +64,29 @@ public class BpmTaskServiceImpl implements BpmTaskService {
57 private TaskService taskService; 64 private TaskService taskService;
58 @Resource 65 @Resource
59 private HistoryService historyService; 66 private HistoryService historyService;
  67 + @Resource
  68 + private RuntimeService runtimeService;
60 69
61 @Resource 70 @Resource
62 private BpmProcessInstanceService processInstanceService; 71 private BpmProcessInstanceService processInstanceService;
63 @Resource 72 @Resource
  73 + private BpmModelService bpmModelService;
  74 + @Resource
  75 + private BpmMessageService messageService;
  76 +
  77 + @Resource
64 private AdminUserApi adminUserApi; 78 private AdminUserApi adminUserApi;
65 @Resource 79 @Resource
66 private DeptApi deptApi; 80 private DeptApi deptApi;
  81 +
67 @Resource 82 @Resource
68 private BpmTaskExtMapper taskExtMapper; 83 private BpmTaskExtMapper taskExtMapper;
69 - @Resource  
70 - private BpmMessageService messageService;  
71 84
72 @Override 85 @Override
73 public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { 86 public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
74 // 查询待办任务 87 // 查询待办任务
75 TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己 88 TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己
76 - .orderByTaskCreateTime().desc(); // 创建时间倒序 89 + .orderByTaskCreateTime().desc(); // 创建时间倒序
77 if (StrUtil.isNotBlank(pageVO.getName())) { 90 if (StrUtil.isNotBlank(pageVO.getName())) {
78 taskQuery.taskNameLike("%" + pageVO.getName() + "%"); 91 taskQuery.taskNameLike("%" + pageVO.getName() + "%");
79 } 92 }
@@ -91,21 +104,21 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -91,21 +104,21 @@ public class BpmTaskServiceImpl implements BpmTaskService {
91 104
92 // 获得 ProcessInstance Map 105 // 获得 ProcessInstance Map
93 Map<String, ProcessInstance> processInstanceMap = 106 Map<String, ProcessInstance> processInstanceMap =
94 - processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId)); 107 + processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId));
95 // 获得 User Map 108 // 获得 User Map
96 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( 109 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
97 - convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); 110 + convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
98 // 拼接结果 111 // 拼接结果
99 return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap), 112 return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
100 - taskQuery.count()); 113 + taskQuery.count());
101 } 114 }
102 115
103 @Override 116 @Override
104 public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) { 117 public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
105 // 查询已办任务 118 // 查询已办任务
106 HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成 119 HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
107 - .taskAssignee(String.valueOf(userId)) // 分配给自己  
108 - .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序 120 + .taskAssignee(String.valueOf(userId)) // 分配给自己
  121 + .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
109 if (StrUtil.isNotBlank(pageVO.getName())) { 122 if (StrUtil.isNotBlank(pageVO.getName())) {
110 taskQuery.taskNameLike("%" + pageVO.getName() + "%"); 123 taskQuery.taskNameLike("%" + pageVO.getName() + "%");
111 } 124 }
@@ -123,19 +136,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -123,19 +136,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
123 136
124 // 获得 TaskExtDO Map 137 // 获得 TaskExtDO Map
125 List<BpmTaskExtDO> bpmTaskExtDOs = 138 List<BpmTaskExtDO> bpmTaskExtDOs =
126 - taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId)); 139 + taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
127 Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId); 140 Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
128 // 获得 ProcessInstance Map 141 // 获得 ProcessInstance Map
129 Map<String, HistoricProcessInstance> historicProcessInstanceMap = 142 Map<String, HistoricProcessInstance> historicProcessInstanceMap =
130 - processInstanceService.getHistoricProcessInstanceMap(  
131 - convertSet(tasks, HistoricTaskInstance::getProcessInstanceId)); 143 + processInstanceService.getHistoricProcessInstanceMap(
  144 + convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
132 // 获得 User Map 145 // 获得 User Map
133 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( 146 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
134 - convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); 147 + convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
135 // 拼接结果 148 // 拼接结果
136 return new PageResult<>( 149 return new PageResult<>(
137 - BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),  
138 - taskQuery.count()); 150 + BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
  151 + taskQuery.count());
139 } 152 }
140 153
141 @Override 154 @Override
@@ -176,27 +189,58 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -176,27 +189,58 @@ public class BpmTaskServiceImpl implements BpmTaskService {
176 @Override 189 @Override
177 @Transactional(rollbackFor = Exception.class) 190 @Transactional(rollbackFor = Exception.class)
178 public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) { 191 public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
179 - // 校验任务存在  
180 - Task task = checkTask(userId, reqVO.getId());  
181 - // 校验流程实例存在 192 + // 1.1 校验任务存在
  193 + Task task = validateTask(userId, reqVO.getId());
  194 + // 1.2 校验流程实例存在
182 ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); 195 ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
183 if (instance == null) { 196 if (instance == null) {
184 throw exception(PROCESS_INSTANCE_NOT_EXISTS); 197 throw exception(PROCESS_INSTANCE_NOT_EXISTS);
185 } 198 }
186 199
  200 + // 情况一:被委派的任务,不调用 complete 去完成任务
  201 + if (DelegationState.PENDING.equals(task.getDelegationState())) {
  202 + approveDelegateTask(reqVO, task);
  203 + return;
  204 + }
  205 +
  206 + // 情况二:自己审批的任务,调用 complete 去完成任务
187 // 完成任务,审批通过 207 // 完成任务,审批通过
188 taskService.complete(task.getId(), instance.getProcessVariables()); 208 taskService.complete(task.getId(), instance.getProcessVariables());
189 -  
190 // 更新任务拓展表为通过 209 // 更新任务拓展表为通过
191 taskExtMapper.updateByTaskId( 210 taskExtMapper.updateByTaskId(
192 - new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())  
193 - .setReason(reqVO.getReason())); 211 + new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
  212 + .setReason(reqVO.getReason()));
  213 + }
  214 +
  215 + /**
  216 + * 审批被委派的任务
  217 + *
  218 + * @param reqVO 前端请求参数,包含当前任务ID,审批意见等
  219 + * @param task 当前被审批的任务
  220 + */
  221 + private void approveDelegateTask(BpmTaskApproveReqVO reqVO, Task task) {
  222 + // 1. 添加审批意见
  223 + AdminUserRespDTO currentUser = adminUserApi.getUser(WebFrameworkUtils.getLoginUserId());
  224 + AdminUserRespDTO sourceApproveUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner()));
  225 + Assert.notNull(sourceApproveUser, "委派任务找不到原审批人,需要检查数据");
  226 + String comment = StrUtil.format("[{}]完成委派任务,任务重新回到[{}]手中,审批意见为:{}", currentUser.getNickname(),
  227 + sourceApproveUser.getNickname(), reqVO.getReason());
  228 + taskService.addComment(reqVO.getId(), task.getProcessInstanceId(),
  229 + BpmProcessInstanceResultEnum.DELEGATE.getResult().toString(), comment);
  230 +
  231 + // 2.1 调用 resolveTask 完成任务。
  232 + // 底层调用 TaskHelper.changeTaskAssignee(task, task.getOwner()):将 owner 设置为 assignee
  233 + taskService.resolveTask(task.getId());
  234 + // 2.2 更新任务拓展表为【处理中】
  235 + taskExtMapper.updateByTaskId(
  236 + new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult())
  237 + .setReason(reqVO.getReason()));
194 } 238 }
195 239
196 @Override 240 @Override
197 @Transactional(rollbackFor = Exception.class) 241 @Transactional(rollbackFor = Exception.class)
198 public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) { 242 public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
199 - Task task = checkTask(userId, reqVO.getId()); 243 + Task task = validateTask(userId, reqVO.getId());
200 // 校验流程实例存在 244 // 校验流程实例存在
201 ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); 245 ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
202 if (instance == null) { 246 if (instance == null) {
@@ -208,14 +252,14 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -208,14 +252,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
208 252
209 // 更新任务拓展表为不通过 253 // 更新任务拓展表为不通过
210 taskExtMapper.updateByTaskId( 254 taskExtMapper.updateByTaskId(
211 - new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())  
212 - .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason())); 255 + new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
  256 + .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
213 } 257 }
214 258
215 @Override 259 @Override
216 public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) { 260 public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) {
217 // 校验任务存在 261 // 校验任务存在
218 - Task task = checkTask(userId, reqVO.getId()); 262 + Task task = validateTask(userId, reqVO.getId());
219 // 更新负责人 263 // 更新负责人
220 updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId()); 264 updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId());
221 } 265 }
@@ -231,13 +275,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -231,13 +275,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
231 * @param userId 用户 id 275 * @param userId 用户 id
232 * @param taskId task id 276 * @param taskId task id
233 */ 277 */
234 - private Task checkTask(Long userId, String taskId) { 278 + private Task validateTask(Long userId, String taskId) {
235 Task task = getTask(taskId); 279 Task task = getTask(taskId);
236 if (task == null) { 280 if (task == null) {
237 - throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS); 281 + throw exception(TASK_NOT_EXISTS);
238 } 282 }
239 if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) { 283 if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {
240 - throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF); 284 + throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
241 } 285 }
242 return task; 286 return task;
243 } 287 }
@@ -245,7 +289,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -245,7 +289,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
245 @Override 289 @Override
246 public void createTaskExt(Task task) { 290 public void createTaskExt(Task task) {
247 BpmTaskExtDO taskExtDO = 291 BpmTaskExtDO taskExtDO =
248 - BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); 292 + BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
249 taskExtMapper.insert(taskExtDO); 293 taskExtMapper.insert(taskExtDO);
250 } 294 }
251 295
@@ -293,27 +337,183 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -293,27 +337,183 @@ public class BpmTaskServiceImpl implements BpmTaskService {
293 @Override 337 @Override
294 public void updateTaskExtAssign(Task task) { 338 public void updateTaskExtAssign(Task task) {
295 BpmTaskExtDO taskExtDO = 339 BpmTaskExtDO taskExtDO =
296 - new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId()); 340 + new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
297 taskExtMapper.updateByTaskId(taskExtDO); 341 taskExtMapper.updateByTaskId(taskExtDO);
298 // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 342 // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
299 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { 343 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
300 @Override 344 @Override
301 public void afterCommit() { 345 public void afterCommit() {
302 ProcessInstance processInstance = 346 ProcessInstance processInstance =
303 - processInstanceService.getProcessInstance(task.getProcessInstanceId()); 347 + processInstanceService.getProcessInstance(task.getProcessInstanceId());
304 AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId())); 348 AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
305 messageService.sendMessageWhenTaskAssigned( 349 messageService.sendMessageWhenTaskAssigned(
306 - BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task)); 350 + BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
307 } 351 }
308 }); 352 });
309 } 353 }
310 354
311 private Task getTask(String id) { 355 private Task getTask(String id) {
312 - return taskService.createTaskQuery().taskId(id).singleResult(); 356 + Task task = taskService.createTaskQuery().taskId(id).singleResult();
  357 + if (null == task) {
  358 + throw exception(TASK_NOT_EXISTS);
  359 + }
  360 + return task;
313 } 361 }
314 362
315 private HistoricTaskInstance getHistoricTask(String id) { 363 private HistoricTaskInstance getHistoricTask(String id) {
316 return historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult(); 364 return historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
317 } 365 }
318 366
  367 + @Override
  368 + public List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId) {
  369 + // 1. 校验当前任务 task 存在
  370 + Task task = getTask(taskId);
  371 + if (task == null) {
  372 + throw exception(TASK_NOT_EXISTS);
  373 + }
  374 + // 根据流程定义获取流程模型信息
  375 + BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
  376 + FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
  377 + if (source == null) {
  378 + throw exception(TASK_NOT_EXISTS);
  379 + }
  380 +
  381 + // 2.1 查询该任务的前置任务节点的 key 集合
  382 + List<UserTask> previousUserList = BpmnModelUtils.getPreviousUserTaskList(source, null, null);
  383 + if (CollUtil.isEmpty(previousUserList)) {
  384 + return Collections.emptyList();
  385 + }
  386 + // 2.2 过滤:只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回
  387 + previousUserList.removeIf(userTask -> !BpmnModelUtils.isSequentialReachable(source, userTask, null));
  388 + return BpmTaskConvert.INSTANCE.convertList(previousUserList);
  389 + }
  390 +
  391 + @Override
  392 + @Transactional(rollbackFor = Exception.class)
  393 + public void returnTask(Long userId, BpmTaskReturnReqVO reqVO) {
  394 + // 1.1 当前任务 task
  395 + Task task = validateTask(userId, reqVO.getId());
  396 + if (task.isSuspended()) {
  397 + throw exception(TASK_IS_PENDING);
  398 + }
  399 + // 1.2 校验源头和目标节点的关系,并返回目标元素
  400 + FlowElement targetElement = validateTargetTaskCanReturn(task.getTaskDefinitionKey(), reqVO.getTargetDefinitionKey(), task.getProcessDefinitionId());
  401 +
  402 + // 2. 调用 flowable 框架的回退逻辑
  403 + returnTask0(task, targetElement, reqVO);
  404 +
  405 + // 3. 更新任务扩展表
  406 + taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
  407 + .setResult(BpmProcessInstanceResultEnum.BACK.getResult())
  408 + .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
  409 + }
  410 +
  411 + /**
  412 + * 回退流程节点时,校验目标任务节点是否可回退
  413 + *
  414 + * @param sourceKey 当前任务节点 Key
  415 + * @param targetKey 目标任务节点 key
  416 + * @param processDefinitionId 当前流程定义 ID
  417 + * @return 目标任务节点元素
  418 + */
  419 + private FlowElement validateTargetTaskCanReturn(String sourceKey, String targetKey, String processDefinitionId) {
  420 + // 1.1 获取流程模型信息
  421 + BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(processDefinitionId);
  422 + // 1.3 获取当前任务节点元素
  423 + FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, sourceKey);
  424 + // 1.3 获取跳转的节点元素
  425 + FlowElement target = BpmnModelUtils.getFlowElementById(bpmnModel, targetKey);
  426 + if (target == null) {
  427 + throw exception(TASK_TARGET_NODE_NOT_EXISTS);
  428 + }
  429 +
  430 + // 2.2 只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回
  431 + if (!BpmnModelUtils.isSequentialReachable(source, target, null)) {
  432 + throw exception(TASK_RETURN_FAIL_SOURCE_TARGET_ERROR);
  433 + }
  434 + return target;
  435 + }
  436 +
  437 + /**
  438 + * 执行回退逻辑
  439 + *
  440 + * @param currentTask 当前回退的任务
  441 + * @param targetElement 需要回退到的目标任务
  442 + * @param reqVO 前端参数封装
  443 + */
  444 + public void returnTask0(Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
  445 + // 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveActivityIdsToSingleActivityId 回撤
  446 + // 1.1 获取所有正常进行的任务节点 Key
  447 + List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
  448 + List<String> runTaskKeyList = convertList(taskList, Task::getTaskDefinitionKey);
  449 + // 1.2 通过 targetElement 的出口连线,计算在 runTaskKeyList 有哪些 key 需要被撤回
  450 + // 为什么不直接使用 runTaskKeyList 呢?因为可能存在多个审批分支,例如说:A -> B -> C 和 D -> F,而只要 C 撤回到 A,需要排除掉 F
  451 + List<UserTask> returnUserTaskList = BpmnModelUtils.iteratorFindChildUserTasks(targetElement, runTaskKeyList, null, null);
  452 + List<String> returnTaskKeyList = convertList(returnUserTaskList, UserTask::getId);
  453 +
  454 + // 2. 给当前要被回退的 task 数组,设置回退意见
  455 + taskList.forEach(task -> {
  456 + // 需要排除掉,不需要设置回退意见的任务
  457 + if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
  458 + return;
  459 + }
  460 + taskService.addComment(task.getId(), currentTask.getProcessInstanceId(),
  461 + BpmProcessInstanceResultEnum.BACK.getResult().toString(), reqVO.getReason());
  462 + });
  463 +
  464 + // 3. 执行驳回
  465 + runtimeService.createChangeActivityStateBuilder()
  466 + .processInstanceId(currentTask.getProcessInstanceId())
  467 + .moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多)
  468 + reqVO.getTargetDefinitionKey()) // targetKey 跳转到的节点(1)
  469 + .changeState();
  470 + }
  471 +
  472 + @Override
  473 + @Transactional(rollbackFor = Exception.class)
  474 + public void delegateTask(BpmTaskDelegateReqVO reqVO, Long userId) {
  475 + // 1.1 校验任务
  476 + Task task = validateTaskCanDelegate(userId, reqVO);
  477 + // 1.2 校验目标用户存在
  478 + AdminUserRespDTO delegateUser = adminUserApi.getUser(reqVO.getDelegateUserId());
  479 + if (delegateUser == null) {
  480 + throw exception(TASK_DELEGATE_FAIL_USER_NOT_EXISTS);
  481 + }
  482 +
  483 + // 2. 添加审批意见
  484 + AdminUserRespDTO currentUser = adminUserApi.getUser(userId);
  485 + String comment = StrUtil.format("[{}]将任务委派给[{}],委派理由为:{}", currentUser.getNickname(),
  486 + delegateUser.getNickname(), reqVO.getReason());
  487 + String taskId = reqVO.getId();
  488 + // TODO 海:后面改;感觉 comment 应该 type 做个枚举;不和 result 耦合在一起;
  489 + taskService.addComment(taskId, task.getProcessInstanceId(),
  490 + BpmProcessInstanceResultEnum.DELEGATE.getResult().toString(), comment);
  491 +
  492 + // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
  493 + taskService.setOwner(taskId, task.getAssignee());
  494 + // 3.2 执行委派,将任务委派给 receiveId
  495 + taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
  496 + // 3.3 更新任务拓展表为【委派】
  497 + taskExtMapper.updateByTaskId(
  498 + new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.DELEGATE.getResult())
  499 + .setReason(reqVO.getReason()));
  500 + }
  501 +
  502 + /**
  503 + * 校验任务委派参数
  504 + *
  505 + * @param userId 用户编号
  506 + * @param reqVO 任务编号,接收人ID
  507 + * @return 当前任务信息
  508 + */
  509 + private Task validateTaskCanDelegate(Long userId, BpmTaskDelegateReqVO reqVO) {
  510 + // 校验任务
  511 + Task task = validateTask(userId, reqVO.getId());
  512 + // 校验当前审批人和被委派人不是同一人
  513 + if (task.getAssignee().equals(reqVO.getDelegateUserId().toString())) {
  514 + throw exception(TASK_DELEGATE_FAIL_USER_REPEAT);
  515 + }
  516 + return task;
  517 + }
  518 +
319 } 519 }
yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java
@@ -9,49 +9,49 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,49 +9,49 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== 参数配置 1001000000 ==========  
13 - ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1001000001, "参数配置不存在");  
14 - ErrorCode CONFIG_KEY_DUPLICATE = new ErrorCode(1001000002, "参数配置 key 重复");  
15 - ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1001000003, "不能删除类型为系统内置的参数配置");  
16 - ErrorCode CONFIG_GET_VALUE_ERROR_IF_VISIBLE = new ErrorCode(1001000004, "获取参数配置失败,原因:不允许获取不可见配置");  
17 -  
18 - // ========== 定时任务 1001001000 ==========  
19 - ErrorCode JOB_NOT_EXISTS = new ErrorCode(1001001000, "定时任务不存在");  
20 - ErrorCode JOB_HANDLER_EXISTS = new ErrorCode(1001001001, "定时任务的处理器已经存在");  
21 - ErrorCode JOB_CHANGE_STATUS_INVALID = new ErrorCode(1001001002, "只允许修改为开启或者关闭状态");  
22 - ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1001001003, "定时任务已经处于该状态,无需修改");  
23 - ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1001001004, "只有开启状态的任务,才可以修改");  
24 - ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1001001005, "CRON 表达式不正确");  
25 -  
26 - // ========== API 错误日志 1001002000 ==========  
27 - ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在");  
28 - ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理");  
29 -  
30 - // ========= 文件相关 1001003000=================  
31 - ErrorCode FILE_PATH_EXISTS = new ErrorCode(1001003000, "文件路径已存在");  
32 - ErrorCode FILE_NOT_EXISTS = new ErrorCode(1001003001, "文件不存在");  
33 - ErrorCode FILE_IS_EMPTY = new ErrorCode(1001003002, "文件为空");  
34 -  
35 - // ========== 代码生成器 1001004000 ==========  
36 - ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1003001000, "表定义已经存在");  
37 - ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1003001001, "导入的表不存在");  
38 - ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1003001002, "导入的字段不存在");  
39 - ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1003001004, "表定义不存在");  
40 - ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1003001005, "字段义不存在");  
41 - ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1003001006, "同步的字段不存在");  
42 - ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1003001007, "同步失败,不存在改变");  
43 - ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1003001008, "数据库的表注释未填写");  
44 - ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1003001009, "数据库的表字段({})注释未填写");  
45 -  
46 - // ========== 字典类型(测试)1001005000 ==========  
47 - ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1001005000, "测试示例不存在");  
48 -  
49 - // ========== 文件配置 1001006000 ==========  
50 - ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1001006000, "文件配置不存在");  
51 - ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1001006001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件");  
52 -  
53 - // ========== 数据源配置 1001007000 ==========  
54 - ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1001007000, "数据源配置不存在");  
55 - ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1001007001, "数据源配置不正确,无法进行连接"); 12 + // ========== 参数配置 1-001-000-000 ==========
  13 + ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1_001_000_001, "参数配置不存在");
  14 + ErrorCode CONFIG_KEY_DUPLICATE = new ErrorCode(1_001_000_002, "参数配置 key 重复");
  15 + ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1_001_000_003, "不能删除类型为系统内置的参数配置");
  16 + ErrorCode CONFIG_GET_VALUE_ERROR_IF_VISIBLE = new ErrorCode(1_001_000_004, "获取参数配置失败,原因:不允许获取不可见配置");
  17 +
  18 + // ========== 定时任务 1-001-001-000 ==========
  19 + ErrorCode JOB_NOT_EXISTS = new ErrorCode(1_001_001_000, "定时任务不存在");
  20 + ErrorCode JOB_HANDLER_EXISTS = new ErrorCode(1_001_001_001, "定时任务的处理器已经存在");
  21 + ErrorCode JOB_CHANGE_STATUS_INVALID = new ErrorCode(1_001_001_002, "只允许修改为开启或者关闭状态");
  22 + ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1_001_001_003, "定时任务已经处于该状态,无需修改");
  23 + ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1_001_001_004, "只有开启状态的任务,才可以修改");
  24 + ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1_001_001_005, "CRON 表达式不正确");
  25 +
  26 + // ========== API 错误日志 1-001-002-000 ==========
  27 + ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1_001_002_000, "API 错误日志不存在");
  28 + ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1_001_002_001, "API 错误日志已处理");
  29 +
  30 + // ========= 文件相关 1-001-003-000 =================
  31 + ErrorCode FILE_PATH_EXISTS = new ErrorCode(1_001_003_000, "文件路径已存在");
  32 + ErrorCode FILE_NOT_EXISTS = new ErrorCode(1_001_003_001, "文件不存在");
  33 + ErrorCode FILE_IS_EMPTY = new ErrorCode(1_001_003_002, "文件为空");
  34 +
  35 + // ========== 代码生成器 1-001-004-000 ==========
  36 + ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1_003_001_000, "表定义已经存在");
  37 + ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1_003_001_001, "导入的表不存在");
  38 + ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1_003_001_002, "导入的字段不存在");
  39 + ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_004, "表定义不存在");
  40 + ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_005, "字段义不存在");
  41 + ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1_003_001_006, "同步的字段不存在");
  42 + ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变");
  43 + ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写");
  44 + ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写");
  45 +
  46 + // ========== 字典类型(测试)1-001-005-000 ==========
  47 + ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1_001_005_000, "测试示例不存在");
  48 +
  49 + // ========== 文件配置 1-001-006-000 ==========
  50 + ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在");
  51 + ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1_001_006_001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件");
  52 +
  53 + // ========== 数据源配置 1-001-007-000 ==========
  54 + ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在");
  55 + ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接");
56 56
57 } 57 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileConfigMapper.java
@@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; 6 import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
7 import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; 7 import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 -import org.apache.ibatis.annotations.Select;  
10 -  
11 -import java.time.LocalDateTime;  
12 9
13 @Mapper 10 @Mapper
14 public interface FileConfigMapper extends BaseMapperX<FileConfigDO> { 11 public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
@@ -21,7 +18,8 @@ public interface FileConfigMapper extends BaseMapperX&lt;FileConfigDO&gt; { @@ -21,7 +18,8 @@ public interface FileConfigMapper extends BaseMapperX&lt;FileConfigDO&gt; {
21 .orderByDesc(FileConfigDO::getId)); 18 .orderByDesc(FileConfigDO::getId));
22 } 19 }
23 20
24 - @Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}")  
25 - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); 21 + default FileConfigDO selectByMaster() {
  22 + return selectOne(FileConfigDO::getMaster, true);
  23 + }
26 24
27 } 25 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
1 package cn.iocoder.yudao.module.infra.service.file; 1 package cn.iocoder.yudao.module.infra.service.file;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.io.resource.ResourceUtil; 3 import cn.hutool.core.io.resource.ResourceUtil;
5 import cn.hutool.core.util.IdUtil; 4 import cn.hutool.core.util.IdUtil;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 7 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
10 import cn.iocoder.yudao.framework.file.core.client.FileClient; 8 import cn.iocoder.yudao.framework.file.core.client.FileClient;
@@ -17,22 +15,22 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigU @@ -17,22 +15,22 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigU
17 import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert; 15 import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert;
18 import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; 16 import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
19 import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; 17 import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
  18 +import com.google.common.cache.CacheLoader;
  19 +import com.google.common.cache.LoadingCache;
20 import lombok.Getter; 20 import lombok.Getter;
21 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
22 -import org.springframework.scheduling.annotation.Scheduled;  
23 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
24 import org.springframework.transaction.annotation.Transactional; 23 import org.springframework.transaction.annotation.Transactional;
25 import org.springframework.validation.annotation.Validated; 24 import org.springframework.validation.annotation.Validated;
26 25
27 -import javax.annotation.PostConstruct;  
28 import javax.annotation.Resource; 26 import javax.annotation.Resource;
29 import javax.validation.Validator; 27 import javax.validation.Validator;
30 -import java.time.LocalDateTime;  
31 -import java.util.List; 28 +import java.time.Duration;
32 import java.util.Map; 29 import java.util.Map;
33 -import java.util.concurrent.TimeUnit; 30 +import java.util.Objects;
34 31
35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  33 +import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
36 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER; 34 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER;
37 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS; 35 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS;
38 36
@@ -46,19 +44,29 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG @@ -46,19 +44,29 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG
46 @Slf4j 44 @Slf4j
47 public class FileConfigServiceImpl implements FileConfigService { 45 public class FileConfigServiceImpl implements FileConfigService {
48 46
49 - @Resource  
50 - private FileClientFactory fileClientFactory; 47 + private static final Long CACHE_MASTER_ID = 0L;
51 48
52 /** 49 /**
53 - * 文件配置的缓存  
54 - */  
55 - @Getter  
56 - private List<FileConfigDO> fileConfigCache;  
57 - /**  
58 - * Master FileClient 对象,有且仅有一个,即 {@link FileConfigDO#getMaster()} 对应的 50 + * {@link FileClient} 缓存,通过它异步刷新 fileClientFactory
59 */ 51 */
60 @Getter 52 @Getter
61 - private FileClient masterFileClient; 53 + private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
  54 + new CacheLoader<Long, FileClient>() {
  55 +
  56 + @Override
  57 + public FileClient load(Long id) {
  58 + FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
  59 + fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
  60 + if (config != null) {
  61 + fileClientFactory.createOrUpdateFileClient(id, config.getStorage(), config.getConfig());
  62 + }
  63 + return fileClientFactory.getFileClient(id);
  64 + }
  65 +
  66 + });
  67 +
  68 + @Resource
  69 + private FileClientFactory fileClientFactory;
62 70
63 @Resource 71 @Resource
64 private FileConfigMapper fileConfigMapper; 72 private FileConfigMapper fileConfigMapper;
@@ -66,53 +74,12 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -66,53 +74,12 @@ public class FileConfigServiceImpl implements FileConfigService {
66 @Resource 74 @Resource
67 private Validator validator; 75 private Validator validator;
68 76
69 - @PostConstruct  
70 - public void initLocalCache() {  
71 - // 第一步:查询数据  
72 - List<FileConfigDO> configs = fileConfigMapper.selectList();  
73 - log.info("[initLocalCache][缓存文件配置,数量为:{}]", configs.size());  
74 -  
75 - // 第二步:构建缓存:创建或更新文件 Client  
76 - configs.forEach(config -> {  
77 - fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());  
78 - // 如果是 master,进行设置  
79 - if (Boolean.TRUE.equals(config.getMaster())) {  
80 - masterFileClient = fileClientFactory.getFileClient(config.getId());  
81 - }  
82 - });  
83 - this.fileConfigCache = configs;  
84 - }  
85 -  
86 - /**  
87 - * 通过定时任务轮询,刷新缓存  
88 - *  
89 - * 目的:多节点部署时,通过轮询”通知“所有节点,进行刷新  
90 - */  
91 - @Scheduled(initialDelay = 60, fixedRate = 60, timeUnit = TimeUnit.SECONDS)  
92 - public void refreshLocalCache() {  
93 - // 情况一:如果缓存里没有数据,则直接刷新缓存  
94 - if (CollUtil.isEmpty(fileConfigCache)) {  
95 - initLocalCache();  
96 - return;  
97 - }  
98 -  
99 - // 情况二,如果缓存里数据,则通过 updateTime 判断是否有数据变更,有变更则刷新缓存  
100 - LocalDateTime maxTime = CollectionUtils.getMaxValue(fileConfigCache, FileConfigDO::getUpdateTime);  
101 - if (fileConfigMapper.selectCountByUpdateTimeGt(maxTime) > 0) {  
102 - initLocalCache();  
103 - }  
104 - }  
105 -  
106 @Override 77 @Override
107 public Long createFileConfig(FileConfigCreateReqVO createReqVO) { 78 public Long createFileConfig(FileConfigCreateReqVO createReqVO) {
108 - // 插入  
109 FileConfigDO fileConfig = FileConfigConvert.INSTANCE.convert(createReqVO) 79 FileConfigDO fileConfig = FileConfigConvert.INSTANCE.convert(createReqVO)
110 .setConfig(parseClientConfig(createReqVO.getStorage(), createReqVO.getConfig())) 80 .setConfig(parseClientConfig(createReqVO.getStorage(), createReqVO.getConfig()))
111 .setMaster(false); // 默认非 master 81 .setMaster(false); // 默认非 master
112 fileConfigMapper.insert(fileConfig); 82 fileConfigMapper.insert(fileConfig);
113 -  
114 - // 刷新缓存  
115 - initLocalCache();  
116 return fileConfig.getId(); 83 return fileConfig.getId();
117 } 84 }
118 85
@@ -125,8 +92,8 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -125,8 +92,8 @@ public class FileConfigServiceImpl implements FileConfigService {
125 .setConfig(parseClientConfig(config.getStorage(), updateReqVO.getConfig())); 92 .setConfig(parseClientConfig(config.getStorage(), updateReqVO.getConfig()));
126 fileConfigMapper.updateById(updateObj); 93 fileConfigMapper.updateById(updateObj);
127 94
128 - // 刷新缓存  
129 - initLocalCache(); 95 + // 清空缓存
  96 + clearCache(config.getId(), null);
130 } 97 }
131 98
132 @Override 99 @Override
@@ -139,8 +106,8 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -139,8 +106,8 @@ public class FileConfigServiceImpl implements FileConfigService {
139 // 更新 106 // 更新
140 fileConfigMapper.updateById(new FileConfigDO().setId(id).setMaster(true)); 107 fileConfigMapper.updateById(new FileConfigDO().setId(id).setMaster(true));
141 108
142 - // 刷新缓存  
143 - initLocalCache(); 109 + // 清空缓存
  110 + clearCache(null, true);
144 } 111 }
145 112
146 private FileClientConfig parseClientConfig(Integer storage, Map<String, Object> config) { 113 private FileClientConfig parseClientConfig(Integer storage, Map<String, Object> config) {
@@ -164,8 +131,23 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -164,8 +131,23 @@ public class FileConfigServiceImpl implements FileConfigService {
164 // 删除 131 // 删除
165 fileConfigMapper.deleteById(id); 132 fileConfigMapper.deleteById(id);
166 133
167 - // 刷新缓存  
168 - initLocalCache(); 134 + // 清空缓存
  135 + clearCache(id, null);
  136 + }
  137 +
  138 + /**
  139 + * 清空指定文件配置
  140 + *
  141 + * @param id 配置编号
  142 + * @param master 是否主配置
  143 + */
  144 + private void clearCache(Long id, Boolean master) {
  145 + if (id != null) {
  146 + clientCache.invalidate(id);
  147 + }
  148 + if (Boolean.TRUE.equals(master)) {
  149 + clientCache.invalidate(CACHE_MASTER_ID);
  150 + }
169 } 151 }
170 152
171 private FileConfigDO validateFileConfigExists(Long id) { 153 private FileConfigDO validateFileConfigExists(Long id) {
@@ -192,12 +174,17 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -192,12 +174,17 @@ public class FileConfigServiceImpl implements FileConfigService {
192 validateFileConfigExists(id); 174 validateFileConfigExists(id);
193 // 上传文件 175 // 上传文件
194 byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); 176 byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
195 - return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg"); 177 + return getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg");
196 } 178 }
197 179
198 @Override 180 @Override
199 public FileClient getFileClient(Long id) { 181 public FileClient getFileClient(Long id) {
200 - return fileClientFactory.getFileClient(id); 182 + return clientCache.getUnchecked(id);
  183 + }
  184 +
  185 + @Override
  186 + public FileClient getMasterFileClient() {
  187 + return clientCache.getUnchecked(CACHE_MASTER_ID);
201 } 188 }
202 189
203 } 190 }
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/api/api.ts.vm
@@ -3,27 +3,27 @@ import { defHttp } from &#39;@/utils/http/axios&#39; @@ -3,27 +3,27 @@ import { defHttp } from &#39;@/utils/http/axios&#39;
3 3
4 // 查询${table.classComment}列表 4 // 查询${table.classComment}列表
5 export function get${simpleClassName}Page(params) { 5 export function get${simpleClassName}Page(params) {
6 - return defHttp.get({ url: '${baseURL}/page', params }) 6 + return defHttp.get({ url: '${baseURL}/page', params })
7 } 7 }
8 8
9 // 查询${table.classComment}详情 9 // 查询${table.classComment}详情
10 export function get${simpleClassName}(id: number) { 10 export function get${simpleClassName}(id: number) {
11 - return defHttp.get({ url: '${baseURL}/get?id=' + id }) 11 + return defHttp.get({ url: `${baseURL}/get?id=${id}` })
12 } 12 }
13 13
14 // 新增${table.classComment} 14 // 新增${table.classComment}
15 export function create${simpleClassName}(data) { 15 export function create${simpleClassName}(data) {
16 - return defHttp.post({ url: '${baseURL}/create', data }) 16 + return defHttp.post({ url: '${baseURL}/create', data })
17 } 17 }
18 18
19 // 修改${table.classComment} 19 // 修改${table.classComment}
20 export function update${simpleClassName}(data) { 20 export function update${simpleClassName}(data) {
21 - return defHttp.put({ url: '${baseURL}/update', data }) 21 + return defHttp.put({ url: '${baseURL}/update', data })
22 } 22 }
23 23
24 // 删除${table.classComment} 24 // 删除${table.classComment}
25 export function delete${simpleClassName}(id: number) { 25 export function delete${simpleClassName}(id: number) {
26 - return defHttp.delete({ url: '${baseURL}/delete?id=' + id }) 26 + return defHttp.delete({ url: `${baseURL}/delete?id=${id}` })
27 } 27 }
28 28
29 // 导出${table.classComment} Excel 29 // 导出${table.classComment} Excel
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm
1 -import { BasicColumn, FormSchema, useRender } from '@/components/Table' 1 +import type { BasicColumn, FormSchema } from '@/components/Table'
  2 +import { useRender } from '@/components/Table'
2 import { DICT_TYPE, getDictOptions } from '@/utils/dict' 3 import { DICT_TYPE, getDictOptions } from '@/utils/dict'
3 4
4 export const columns: BasicColumn[] = [ 5 export const columns: BasicColumn[] = [
@@ -92,13 +93,13 @@ export const createFormSchema: FormSchema[] = [ @@ -92,13 +93,13 @@ export const createFormSchema: FormSchema[] = [
92 #elseif($column.htmlType == "imageUpload")## 图片上传 93 #elseif($column.htmlType == "imageUpload")## 图片上传
93 component: 'FileUpload', 94 component: 'FileUpload',
94 componentProps: { 95 componentProps: {
95 - fileType: 'file', 96 + fileType: 'image',
96 maxCount: 1, 97 maxCount: 1,
97 }, 98 },
98 #elseif($column.htmlType == "fileUpload")## 文件上传 99 #elseif($column.htmlType == "fileUpload")## 文件上传
99 component: 'FileUpload', 100 component: 'FileUpload',
100 componentProps: { 101 componentProps: {
101 - fileType: 'image', 102 + fileType: 'file',
102 maxCount: 1, 103 maxCount: 1,
103 }, 104 },
104 #elseif($column.htmlType == "editor")## 文本编辑器 105 #elseif($column.htmlType == "editor")## 文本编辑器
@@ -132,6 +133,11 @@ export const createFormSchema: FormSchema[] = [ @@ -132,6 +133,11 @@ export const createFormSchema: FormSchema[] = [
132 }, 133 },
133 #elseif($column.htmlType == "datetime")## 时间框 134 #elseif($column.htmlType == "datetime")## 时间框
134 component: 'DatePicker', 135 component: 'DatePicker',
  136 + componentProps: {
  137 + showTime: true,
  138 + format: 'YYYY-MM-DD HH:mm:ss',
  139 + valueFormat: 'x',
  140 + },
135 #elseif($column.htmlType == "textarea")## 文本域 141 #elseif($column.htmlType == "textarea")## 文本域
136 component: 'InputTextArea', 142 component: 'InputTextArea',
137 #end 143 #end
@@ -154,7 +160,7 @@ export const updateFormSchema: FormSchema[] = [ @@ -154,7 +160,7 @@ export const updateFormSchema: FormSchema[] = [
154 #set ($javaField = $column.javaField) 160 #set ($javaField = $column.javaField)
155 #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) 161 #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
156 #set ($comment = $column.columnComment) 162 #set ($comment = $column.columnComment)
157 -#if (!$column.primaryKey)## 忽略主键,不用在表单里 163 + #if (!$column.primaryKey)## 忽略主键,不用在表单里
158 { 164 {
159 label: '${comment}', 165 label: '${comment}',
160 field: '${javaField}', 166 field: '${javaField}',
@@ -164,45 +170,57 @@ export const updateFormSchema: FormSchema[] = [ @@ -164,45 +170,57 @@ export const updateFormSchema: FormSchema[] = [
164 #if ($column.htmlType == "input") 170 #if ($column.htmlType == "input")
165 component: 'Input', 171 component: 'Input',
166 #elseif($column.htmlType == "imageUpload")## 图片上传 172 #elseif($column.htmlType == "imageUpload")## 图片上传
167 - component: 'Upload', 173 + component: 'FileUpload',
  174 + componentProps: {
  175 + fileType: 'image',
  176 + maxCount: 1,
  177 + },
168 #elseif($column.htmlType == "fileUpload")## 文件上传 178 #elseif($column.htmlType == "fileUpload")## 文件上传
169 - component: 'Upload',  
170 - #elseif($column.htmlType == "editor")## 文本编辑器  
171 - component: 'Editor', 179 + component: 'FileUpload',
  180 + componentProps: {
  181 + fileType: 'file',
  182 + maxCount: 1,
  183 + },
  184 + #elseif($column.htmlType == "editor")## 文本编辑器component: 'Editor',
172 #elseif($column.htmlType == "select")## 下拉框 185 #elseif($column.htmlType == "select")## 下拉框
173 component: 'Select', 186 component: 'Select',
174 componentProps: { 187 componentProps: {
175 #if ("" != $dictType)## 有数据字典 188 #if ("" != $dictType)## 有数据字典
176 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), 189 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
177 #else##没数据字典 190 #else##没数据字典
178 - options:[], 191 + options:[],
179 #end 192 #end
180 }, 193 },
181 #elseif($column.htmlType == "checkbox")## 多选框 194 #elseif($column.htmlType == "checkbox")## 多选框
182 component: 'Checkbox', 195 component: 'Checkbox',
183 componentProps: { 196 componentProps: {
184 #if ("" != $dictType)## 有数据字典 197 #if ("" != $dictType)## 有数据字典
185 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), 198 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
186 #else##没数据字典 199 #else##没数据字典
187 - options:[], 200 + options:[],
188 #end 201 #end
189 }, 202 },
190 #elseif($column.htmlType == "radio")## 单选框 203 #elseif($column.htmlType == "radio")## 单选框
191 component: 'RadioButtonGroup', 204 component: 'RadioButtonGroup',
192 componentProps: { 205 componentProps: {
193 #if ("" != $dictType)## 有数据字典 206 #if ("" != $dictType)## 有数据字典
194 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), 207 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
195 #else##没数据字典 208 #else##没数据字典
196 - options:[], 209 + options:[],
197 #end 210 #end
198 }, 211 },
199 #elseif($column.htmlType == "datetime")## 时间框 212 #elseif($column.htmlType == "datetime")## 时间框
200 component: 'DatePicker', 213 component: 'DatePicker',
  214 + componentProps: {
  215 + showTime: true,
  216 + format: 'YYYY-MM-DD HH:mm:ss',
  217 + valueFormat: 'x',
  218 + },
201 #elseif($column.htmlType == "textarea")## 文本域 219 #elseif($column.htmlType == "textarea")## 文本域
202 component: 'InputTextArea', 220 component: 'InputTextArea',
203 #end 221 #end
204 }, 222 },
205 -#end 223 + #end
206 #end 224 #end
207 #end 225 #end
208 ] 226 ]
209 \ No newline at end of file 227 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/form.vue.vm
@@ -9,9 +9,10 @@ import { create${simpleClassName}, get${simpleClassName}, update${simpleClassNam @@ -9,9 +9,10 @@ import { create${simpleClassName}, get${simpleClassName}, update${simpleClassNam
9 9
10 defineOptions({ name: '${table.className}Modal' }) 10 defineOptions({ name: '${table.className}Modal' })
11 11
  12 +const emit = defineEmits(['success', 'register'])
  13 +
12 const { t } = useI18n() 14 const { t } = useI18n()
13 const { createMessage } = useMessage() 15 const { createMessage } = useMessage()
14 -const emit = defineEmits(['success', 'register'])  
15 const isUpdate = ref(true) 16 const isUpdate = ref(true)
16 17
17 const [registerForm, { setFieldsValue, resetFields, resetSchema, validate }] = useForm({ 18 const [registerForm, { setFieldsValue, resetFields, resetSchema, validate }] = useForm({
@@ -37,11 +38,11 @@ async function handleSubmit() { @@ -37,11 +38,11 @@ async function handleSubmit() {
37 try { 38 try {
38 const values = await validate() 39 const values = await validate()
39 setModalProps({ confirmLoading: true }) 40 setModalProps({ confirmLoading: true })
40 - if (unref(isUpdate)) { 41 + if (unref(isUpdate))
41 await update${simpleClassName}(values) 42 await update${simpleClassName}(values)
42 - } else { 43 + else
43 await create${simpleClassName}(values) 44 await create${simpleClassName}(values)
44 - } 45 +
45 closeModal() 46 closeModal()
46 emit('success') 47 emit('success')
47 createMessage.success(t('common.saveSuccessText')) 48 createMessage.success(t('common.saveSuccessText'))
@@ -51,7 +52,7 @@ async function handleSubmit() { @@ -51,7 +52,7 @@ async function handleSubmit() {
51 } 52 }
52 </script> 53 </script>
53 <template> 54 <template>
54 - <BasicModal v-bind="$attrs" @register="registerModal" :title="isUpdate ? t('action.edit') : t('action.create')" @ok="handleSubmit"> 55 + <BasicModal v-bind="$attrs" :title="isUpdate ? t('action.edit') : t('action.create')" @register="registerModal" @ok="handleSubmit">
55 <BasicForm @register="registerForm" /> 56 <BasicForm @register="registerForm" />
56 </BasicModal> 57 </BasicModal>
57 </template> 58 </template>
58 \ No newline at end of file 59 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/index.vue.vm
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 -import ${simpleClassName}Modal from './${simpleClassName}Modal.vue' 2 +import ${ simpleClassName }Modal from './${simpleClassName}Modal.vue'
3 import { columns, searchFormSchema } from './${classNameVar}.data' 3 import { columns, searchFormSchema } from './${classNameVar}.data'
4 import { useI18n } from '@/hooks/web/useI18n' 4 import { useI18n } from '@/hooks/web/useI18n'
5 import { useMessage } from '@/hooks/web/useMessage' 5 import { useMessage } from '@/hooks/web/useMessage'
6 import { useModal } from '@/components/Modal' 6 import { useModal } from '@/components/Modal'
7 import { IconEnum } from '@/enums/appEnum' 7 import { IconEnum } from '@/enums/appEnum'
8 import { BasicTable, useTable, TableAction } from '@/components/Table' 8 import { BasicTable, useTable, TableAction } from '@/components/Table'
9 -import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${classNameVar}' 9 +import { delete${ simpleClassName }, export${ simpleClassName }, get${ simpleClassName } Page } from '@/api/${table.moduleName}/${classNameVar}'
10 10
11 defineOptions({ name: '${table.className}' }) 11 defineOptions({ name: '${table.className}' })
12 12
@@ -16,17 +16,17 @@ const [registerModal, { openModal }] = useModal() @@ -16,17 +16,17 @@ const [registerModal, { openModal }] = useModal()
16 16
17 const [registerTable, { getForm, reload }] = useTable({ 17 const [registerTable, { getForm, reload }] = useTable({
18 title: '${table.classComment}列表', 18 title: '${table.classComment}列表',
19 - api: get${simpleClassName}Page,  
20 - columns,  
21 - formConfig: { labelWidth: 120, schemas: searchFormSchema },  
22 - useSearchForm: true,  
23 - showTableSetting: true,  
24 - actionColumn: {  
25 - width: 140,  
26 - title: t('common.action'),  
27 - dataIndex: 'action',  
28 - fixed: 'right',  
29 - }, 19 + api: get${ simpleClassName }Page,
  20 + columns,
  21 + formConfig: { labelWidth: 120, schemas: searchFormSchema },
  22 + useSearchForm: true,
  23 + showTableSetting: true,
  24 + actionColumn: {
  25 + width: 140,
  26 + title: t('common.action'),
  27 + dataIndex: 'action',
  28 + fixed: 'right',
  29 + },
30 }) 30 })
31 31
32 function handleCreate() { 32 function handleCreate() {
@@ -43,14 +43,14 @@ async function handleExport() { @@ -43,14 +43,14 @@ async function handleExport() {
43 iconType: 'warning', 43 iconType: 'warning',
44 content: t('common.exportMessage'), 44 content: t('common.exportMessage'),
45 async onOk() { 45 async onOk() {
46 - await export${simpleClassName}(getForm().getFieldsValue()) 46 + await export${ simpleClassName } (getForm().getFieldsValue())
47 createMessage.success(t('common.exportSuccessText')) 47 createMessage.success(t('common.exportSuccessText'))
48 }, 48 },
49 }) 49 })
50 } 50 }
51 51
52 async function handleDelete(record: Recordable) { 52 async function handleDelete(record: Recordable) {
53 - await delete${simpleClassName}(record.id) 53 + await delete${ simpleClassName } (record.id)
54 createMessage.success(t('common.delSuccessText')) 54 createMessage.success(t('common.delSuccessText'))
55 reload() 55 reload()
56 } 56 }
@@ -89,4 +89,4 @@ async function handleDelete(record: Recordable) { @@ -89,4 +89,4 @@ async function handleDelete(record: Recordable) {
89 </BasicTable> 89 </BasicTable>
90 <${simpleClassName}Modal @register="registerModal" @success="reload()" /> 90 <${simpleClassName}Modal @register="registerModal" @success="reload()" />
91 </div> 91 </div>
92 -</template>  
93 \ No newline at end of file 92 \ No newline at end of file
  93 +</template>
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
@@ -60,31 +60,6 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -60,31 +60,6 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
60 private FileClientFactory fileClientFactory; 60 private FileClientFactory fileClientFactory;
61 61
62 @Test 62 @Test
63 - public void testInitLocalCache() {  
64 - // mock 数据  
65 - FileConfigDO configDO1 = randomFileConfigDO().setId(1L).setMaster(true);  
66 - fileConfigMapper.insert(configDO1);  
67 - FileConfigDO configDO2 = randomFileConfigDO().setId(2L).setMaster(false);  
68 - fileConfigMapper.insert(configDO2);  
69 - // mock fileClientFactory 获得 master  
70 - FileClient masterFileClient = mock(FileClient.class);  
71 - when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient);  
72 -  
73 - // 调用  
74 - fileConfigService.initLocalCache();  
75 - // 断言 fileClientFactory 调用  
76 - verify(fileClientFactory).createOrUpdateFileClient(eq(1L),  
77 - eq(configDO1.getStorage()), eq(configDO1.getConfig()));  
78 - verify(fileClientFactory).createOrUpdateFileClient(eq(2L),  
79 - eq(configDO2.getStorage()), eq(configDO2.getConfig()));  
80 - assertSame(masterFileClient, fileConfigService.getMasterFileClient());  
81 - // 断言 fileConfigCache 缓存  
82 - assertEquals(2, fileConfigService.getFileConfigCache().size());  
83 - assertEquals(configDO1, fileConfigService.getFileConfigCache().get(0));  
84 - assertEquals(configDO2, fileConfigService.getFileConfigCache().get(1));  
85 - }  
86 -  
87 - @Test  
88 public void testCreateFileConfig_success() { 63 public void testCreateFileConfig_success() {
89 // 准备参数 64 // 准备参数
90 Map<String, Object> config = MapUtil.<String, Object>builder().put("basePath", "/yunai") 65 Map<String, Object> config = MapUtil.<String, Object>builder().put("basePath", "/yunai")
@@ -102,6 +77,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -102,6 +77,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
102 assertFalse(fileConfig.getMaster()); 77 assertFalse(fileConfig.getMaster());
103 assertEquals("/yunai", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath()); 78 assertEquals("/yunai", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
104 assertEquals("https://www.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain()); 79 assertEquals("https://www.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
  80 + // 验证 cache
  81 + assertNull(fileConfigService.getClientCache().getIfPresent(fileConfigId));
105 } 82 }
106 83
107 @Test 84 @Test
@@ -125,6 +102,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -125,6 +102,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
125 assertPojoEquals(reqVO, fileConfig, "config"); 102 assertPojoEquals(reqVO, fileConfig, "config");
126 assertEquals("/yunai2", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath()); 103 assertEquals("/yunai2", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
127 assertEquals("https://doc.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain()); 104 assertEquals("https://doc.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
  105 + // 验证 cache
  106 + assertNull(fileConfigService.getClientCache().getIfPresent(fileConfig.getId()));
128 } 107 }
129 108
130 @Test 109 @Test
@@ -149,6 +128,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -149,6 +128,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
149 // 断言数据 128 // 断言数据
150 assertTrue(fileConfigMapper.selectById(dbFileConfig.getId()).getMaster()); 129 assertTrue(fileConfigMapper.selectById(dbFileConfig.getId()).getMaster());
151 assertFalse(fileConfigMapper.selectById(masterFileConfig.getId()).getMaster()); 130 assertFalse(fileConfigMapper.selectById(masterFileConfig.getId()).getMaster());
  131 + // 验证 cache
  132 + assertNull(fileConfigService.getClientCache().getIfPresent(0L));
152 } 133 }
153 134
154 @Test 135 @Test
@@ -169,6 +150,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -169,6 +150,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
169 fileConfigService.deleteFileConfig(id); 150 fileConfigService.deleteFileConfig(id);
170 // 校验数据不存在了 151 // 校验数据不存在了
171 assertNull(fileConfigMapper.selectById(id)); 152 assertNull(fileConfigMapper.selectById(id));
  153 + // 验证 cache
  154 + assertNull(fileConfigService.getClientCache().getIfPresent(id));
172 } 155 }
173 156
174 @Test 157 @Test
@@ -250,14 +233,38 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -250,14 +233,38 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
250 233
251 @Test 234 @Test
252 public void testGetFileClient() { 235 public void testGetFileClient() {
  236 + // mock 数据
  237 + FileConfigDO fileConfig = randomFileConfigDO().setMaster(false);
  238 + fileConfigMapper.insert(fileConfig);
253 // 准备参数 239 // 准备参数
254 - Long id = randomLongId(); 240 + Long id = fileConfig.getId();
255 // mock 获得 Client 241 // mock 获得 Client
256 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig()); 242 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
257 when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient); 243 when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient);
258 244
259 // 调用,并断言 245 // 调用,并断言
260 assertSame(fileClient, fileConfigService.getFileClient(id)); 246 assertSame(fileClient, fileConfigService.getFileClient(id));
  247 + // 断言缓存
  248 + verify(fileClientFactory).createOrUpdateFileClient(eq(id), eq(fileConfig.getStorage()),
  249 + eq(fileConfig.getConfig()));
  250 + }
  251 +
  252 + @Test
  253 + public void testGetMasterFileClient() {
  254 + // mock 数据
  255 + FileConfigDO fileConfig = randomFileConfigDO().setMaster(true);
  256 + fileConfigMapper.insert(fileConfig);
  257 + // 准备参数
  258 + Long id = fileConfig.getId();
  259 + // mock 获得 Client
  260 + FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
  261 + when(fileClientFactory.getFileClient(eq(0L))).thenReturn(fileClient);
  262 +
  263 + // 调用,并断言
  264 + assertSame(fileClient, fileConfigService.getMasterFileClient());
  265 + // 断言缓存
  266 + verify(fileClientFactory).createOrUpdateFileClient(eq(0L), eq(fileConfig.getStorage()),
  267 + eq(fileConfig.getConfig()));
261 } 268 }
262 269
263 private FileConfigDO randomFileConfigDO() { 270 private FileConfigDO randomFileConfigDO() {
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImplTest.java
@@ -139,4 +139,5 @@ public class FileServiceImplTest extends BaseDbUnitTest { @@ -139,4 +139,5 @@ public class FileServiceImplTest extends BaseDbUnitTest {
139 // 断言 139 // 断言
140 assertSame(result, content); 140 assertSame(result, content);
141 } 141 }
  142 +
142 } 143 }
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== 商品分类相关 1008001000 ============  
13 - ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");  
14 - ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");  
15 - ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");  
16 - ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");  
17 - ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");  
18 - ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1008001005, "类别下存在商品,无法删除");  
19 -  
20 - // ========== 商品品牌相关编号 1008002000 ==========  
21 - ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");  
22 - ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌已禁用");  
23 - ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");  
24 -  
25 - // ========== 商品属性项 1008003000 ==========  
26 - ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");  
27 - ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");  
28 - ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");  
29 -  
30 - // ========== 商品属性值 1008004000 ==========  
31 - ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");  
32 - ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");  
33 -  
34 - // ========== 商品 SPU 1008005000 ==========  
35 - ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");  
36 - ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");  
37 - ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");  
38 - ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1008005003, "商品 SPU 不处于回收站状态");  
39 -  
40 - // ========== 商品 SKU 1008006000 ==========  
41 - ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");  
42 - ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");  
43 - ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");  
44 - ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");  
45 - ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");  
46 -  
47 - // ========== 商品 评价 1008007000 ==========  
48 - ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品评价不存在");  
49 - ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1008007001, "订单的商品评价已存在");  
50 -  
51 - // ========== 商品 收藏 1008008000 ==========  
52 - ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏");  
53 - ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1008008001, "商品收藏不存在"); 12 + // ========== 商品分类相关 1-008-001-000 ============
  13 + ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_008_001_000, "商品分类不存在");
  14 + ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_008_001_001, "父分类不存在");
  15 + ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_008_001_002, "父分类不能是二级分类");
  16 + ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_008_001_003, "存在子分类,无法删除");
  17 + ErrorCode CATEGORY_DISABLED = new ErrorCode(1_008_001_004, "商品分类({})已禁用,无法使用");
  18 + ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1_008_001_005, "类别下存在商品,无法删除");
  19 +
  20 + // ========== 商品品牌相关编号 1-008-002-000 ==========
  21 + ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1_008_002_000, "品牌不存在");
  22 + ErrorCode BRAND_DISABLED = new ErrorCode(1_008_002_001, "品牌已禁用");
  23 + ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1_008_002_002, "品牌名称已存在");
  24 +
  25 + // ========== 商品属性项 1-008-003-000 ==========
  26 + ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1_008_003_000, "属性项不存在");
  27 + ErrorCode PROPERTY_EXISTS = new ErrorCode(1_008_003_001, "属性项的名称已存在");
  28 + ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1_008_003_002, "属性项下存在属性值,无法删除");
  29 +
  30 + // ========== 商品属性值 1-008-004-000 ==========
  31 + ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1_008_004_000, "属性值不存在");
  32 + ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1_008_004_001, "属性值的名称已存在");
  33 +
  34 + // ========== 商品 SPU 1-008-005-000 ==========
  35 + ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在");
  36 + ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
  37 + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU 不处于上架状态");
  38 + ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_003, "商品 SPU 不处于回收站状态");
  39 +
  40 + // ========== 商品 SKU 1-008-006-000 ==========
  41 + ErrorCode SKU_NOT_EXISTS = new ErrorCode(1_008_006_000, "商品 SKU 不存在");
  42 + ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1_008_006_001, "商品 SKU 的属性组合存在重复");
  43 + ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1_008_006_002, "一个 SPU 下的每个 SKU,其属性项必须一致");
  44 + ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1_008_006_003, "一个 SPU 下的每个 SKU,必须不重复");
  45 + ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1_008_006_004, "商品 SKU 库存不足");
  46 +
  47 + // ========== 商品 评价 1-008-007-000 ==========
  48 + ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1_008_007_000, "商品评价不存在");
  49 + ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1_008_007_001, "订单的商品评价已存在");
  50 +
  51 + // ========== 商品 收藏 1-008-008-000 ==========
  52 + ErrorCode FAVORITE_EXISTS = new ErrorCode(1_008_008_000, "该商品已经被收藏");
  53 + ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1_008_008_001, "商品收藏不存在");
54 54
55 } 55 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== 促销活动相关 1013001000 ============  
13 - ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1013001000, "限时折扣活动不存在");  
14 - ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013001001, "存在商品参加了其它限时折扣活动");  
15 - ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013001002, "限时折扣活动已关闭,不能修改");  
16 - ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1013001003, "限时折扣活动未关闭,不能删除");  
17 - ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013001004, "限时折扣活动已关闭,不能重复关闭");  
18 - ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013001005, "限时折扣活动已结束,不能关闭");  
19 -  
20 - // ========== Banner 相关 1013002000 ============  
21 - ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1013002000, "Banner 不存在");  
22 -  
23 - // ========== Coupon 相关 1013003000 ============  
24 - ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1013003000, "优惠劵没有可使用的商品!");  
25 - ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1013003001, "所结算的商品中未满足使用的金额");  
26 -  
27 - // ========== 优惠劵模板 1013004000 ==========  
28 - ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1013004000, "优惠劵模板不存在");  
29 - ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1013004001, "发放数量不能小于已领取数量({})");  
30 - ErrorCode COUPON_TEMPLATE_NOT_ENOUGH = new ErrorCode(1013004002, "当前剩余数量不够领取");  
31 - ErrorCode COUPON_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1013004003, "用户已领取过此优惠券");  
32 - ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1013004004, "优惠券已过期");  
33 - ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1013004005, "领取方式不正确");  
34 -  
35 - // ========== 优惠劵 1013005000 ==========  
36 - ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1013005000, "优惠券不存在");  
37 - ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");  
38 - ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");  
39 - ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内");  
40 - ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态");  
41 -  
42 - // ========== 满减送活动 1013006000 ==========  
43 - ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1013006000, "满减送活动不存在");  
44 - ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013006001, "存在商品参加了其它满减送活动");  
45 - ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013006002, "满减送活动已关闭,不能修改");  
46 - ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1013006003, "满减送活动未关闭,不能删除");  
47 - ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013006004, "满减送活动已关闭,不能重复关闭");  
48 - ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013006005, "满减送活动已结束,不能关闭");  
49 -  
50 - // ========== TODO 空着 1013007000 ============  
51 -  
52 - // ========== 秒杀活动 1013008000 ========== 12 + // ========== 促销活动相关 1-013-001-000 ============
  13 + ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_001_000, "限时折扣活动不存在");
  14 + ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_001_001, "存在商品参加了其它限时折扣活动");
  15 + ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改");
  16 + ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
  17 + ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");
  18 + ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_001_005, "限时折扣活动已结束,不能关闭");
  19 +
  20 + // ========== Banner 相关 1-013-002-000 ============
  21 + ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在");
  22 +
  23 + // ========== Coupon 相关 1-013-003-000 ============
  24 + ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1_013_003_000, "优惠劵没有可使用的商品!");
  25 + ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1_013_003_001, "所结算的商品中未满足使用的金额");
  26 +
  27 + // ========== 优惠劵模板 1-013-004-000 ==========
  28 + ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在");
  29 + ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1_013_004_001, "发放数量不能小于已领取数量({})");
  30 + ErrorCode COUPON_TEMPLATE_NOT_ENOUGH = new ErrorCode(1_013_004_002, "当前剩余数量不够领取");
  31 + ErrorCode COUPON_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1_013_004_003, "用户已领取过此优惠券");
  32 + ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1_013_004_004, "优惠券已过期");
  33 + ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1_013_004_005, "领取方式不正确");
  34 +
  35 + // ========== 优惠劵 1-013-005-000 ==========
  36 + ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1_013_005_000, "优惠券不存在");
  37 + ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1_013_005_001, "回收优惠劵失败,优惠劵已被使用");
  38 + ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1_013_005_002, "优惠劵不处于待使用状态");
  39 + ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1_013_005_003, "优惠券不在使用时间范围内");
  40 + ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1_013_005_004, "优惠劵不是已使用状态");
  41 +
  42 + // ========== 满减送活动 1-013-006-000 ==========
  43 + ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_006_000, "满减送活动不存在");
  44 + ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_006_001, "存在商品参加了其它满减送活动");
  45 + ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
  46 + ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
  47 + ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
  48 + ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_006_005, "满减送活动已结束,不能关闭");
  49 +
  50 + // ========== TODO 空着 1-013-007-000 ============
  51 +
  52 + // ========== 秒杀活动 1-013-008-000 ==========
53 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在"); 53 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
54 ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突"); 54 ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
55 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); 55 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
@@ -57,19 +57,19 @@ public interface ErrorCodeConstants { @@ -57,19 +57,19 @@ public interface ErrorCodeConstants {
57 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); 57 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
58 ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足"); 58 ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
59 59
60 - // ========== 秒杀时段 1013009000 ==========  
61 - ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");  
62 - ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");  
63 - ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭"); 60 + // ========== 秒杀时段 1-013-009-000 ==========
  61 + ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1_013_009_000, "秒杀时段不存在");
  62 + ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1_013_009_001, "秒杀时段冲突");
  63 + ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1_013_009_004, "秒杀时段已关闭");
64 64
65 - // ========== 拼团活动 1013010000 ========== 65 + // ========== 拼团活动 1-013-010-000 ==========
66 ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); 66 ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
67 ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动"); 67 ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
68 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改"); 68 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
69 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除"); 69 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
70 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭"); 70 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
71 71
72 - // ========== 拼团记录 1013011000 ========== 72 + // ========== 拼团记录 1-013-011-000 ==========
73 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在"); 73 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
74 ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团"); 74 ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
75 ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在"); 75 ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在");
@@ -79,17 +79,17 @@ public interface ErrorCodeConstants { @@ -79,17 +79,17 @@ public interface ErrorCodeConstants {
79 ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出"); 79 ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出");
80 ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数"); 80 ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数");
81 81
82 - // ========== 砍价活动 1013012000 ========== 82 + // ========== 砍价活动 1-013-012-000 ==========
83 ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在"); 83 ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
84 ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动"); 84 ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
85 ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改"); 85 ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
86 ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除"); 86 ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
87 ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足"); 87 ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
88 88
89 - // ========== 砍价记录 1013013000 ==========  
90 - ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在");  
91 - ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1013013001, "砍价失败,已参与过该砍价");  
92 - ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013013002, "砍价失败,父砍价不存在");  
93 - ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1013013003, "砍价失败,砍价人数已满"); 89 + // ========== 砍价记录 1-013-013-000 ==========
  90 + ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1_013_013_000, "砍价记录不存在");
  91 + ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1_013_013_001, "砍价失败,已参与过该砍价");
  92 + ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_013_002, "砍价失败,父砍价不存在");
  93 + ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1_013_013_003, "砍价失败,砍价人数已满");
94 94
95 } 95 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/vo/article/AppArticleRespVO.java
@@ -9,41 +9,41 @@ import java.time.LocalDateTime; @@ -9,41 +9,41 @@ import java.time.LocalDateTime;
9 @Data 9 @Data
10 public class AppArticleRespVO { 10 public class AppArticleRespVO {
11 11
12 - @Schema(description = "文章编号", required = true, example = "1") 12 + @Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
13 private Long id; 13 private Long id;
14 14
15 - @Schema(description = "文章标题", required = true, example = "芋道源码 - 促销模块") 15 + @Schema(description = "文章标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码 - 促销模块")
16 private String title; 16 private String title;
17 17
18 - @Schema(description = "文章作者", required = true, example = "芋道源码") 18 + @Schema(description = "文章作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
19 private String author; 19 private String author;
20 20
21 - @Schema(description = "分类编号", required = true, example = "2048") 21 + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
22 private Long categoryId; 22 private Long categoryId;
23 23
24 - @Schema(description = "图文封面", required = true, example = "https://www.iocoder.cn/1.png") 24 + @Schema(description = "图文封面", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
25 private String picUrl; 25 private String picUrl;
26 26
27 - @Schema(description = "文章简介", required = true, example = "我是简介") 27 + @Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是简介")
28 private String introduction; 28 private String introduction;
29 29
30 - @Schema(description = "文章内容", required = true, example = "我是详细") 30 + @Schema(description = "文章内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是详细")
31 private String description; 31 private String description;
32 32
33 - @Schema(description = "发布时间", required = true) 33 + @Schema(description = "发布时间", requiredMode = Schema.RequiredMode.REQUIRED)
34 private LocalDateTime createTime; 34 private LocalDateTime createTime;
35 35
36 - @Schema(description = "浏览量", required = true, example = "1024") 36 + @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
37 private Integer browseCount; 37 private Integer browseCount;
38 38
39 @Schema(description = "关联的商品 SPU 编号", example = "1024") 39 @Schema(description = "关联的商品 SPU 编号", example = "1024")
40 private Long spuId; 40 private Long spuId;
41 41
42 // TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回; 42 // TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
43 -// @Schema(description = "是否热卖推荐", required = true, example = "true") 43 +// @Schema(description = "是否热卖推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
44 // private Boolean recommendHot; 44 // private Boolean recommendHot;
45 // 45 //
46 -// @Schema(description = "是否 Banner 推荐", required = true, example = "true") 46 +// @Schema(description = "是否 Banner 推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
47 // private Boolean recommendBanner; 47 // private Boolean recommendBanner;
48 48
49 } 49 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/vo/category/AppArticleCategoryRespVO.java
@@ -7,20 +7,20 @@ import lombok.Data; @@ -7,20 +7,20 @@ import lombok.Data;
7 @Data 7 @Data
8 public class AppArticleCategoryRespVO { 8 public class AppArticleCategoryRespVO {
9 9
10 - @Schema(description = "分类编号", required = true, example = "1") 10 + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
11 private Long id; 11 private Long id;
12 12
13 - @Schema(description = "分类名称", required = true, example = "技术") 13 + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术")
14 private String name; 14 private String name;
15 15
16 - @Schema(description = "分类图标", required = true, example = "https://www.iocoder.cn/1.png") 16 + @Schema(description = "分类图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
17 private String picUrl; 17 private String picUrl;
18 18
19 // TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回; 19 // TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
20 -// @Schema(description = "状态", required = true, example = "1") 20 +// @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
21 // private Integer status; 21 // private Integer status;
22 // 22 //
23 -// @Schema(description = "排序", required = true, example = "1024") 23 +// @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
24 // private Integer sort; 24 // private Integer sort;
25 25
26 } 26 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityDetailRespVO.java
@@ -9,46 +9,46 @@ import java.time.LocalDateTime; @@ -9,46 +9,46 @@ import java.time.LocalDateTime;
9 @Data 9 @Data
10 public class AppBargainActivityDetailRespVO { 10 public class AppBargainActivityDetailRespVO {
11 11
12 - @Schema(description = "砍价活动编号", required = true, example = "1024") 12 + @Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 private Long id; 13 private Long id;
14 14
15 - @Schema(description = "砍价活动名称", required = true, example = "618 大砍价") 15 + @Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大砍价")
16 private String name; 16 private String name;
17 17
18 - @Schema(description = "活动开始时间", required = true) 18 + @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
19 private LocalDateTime startTime; 19 private LocalDateTime startTime;
20 20
21 - @Schema(description = "活动结束时间", required = true) 21 + @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
22 private LocalDateTime endTime; 22 private LocalDateTime endTime;
23 23
24 - @Schema(description = "商品 SPU 编号", required = true, example = "2048") 24 + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
25 private Long spuId; 25 private Long spuId;
26 26
27 - @Schema(description = "商品 SKU 编号", required = true, example = "1024") 27 + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
28 private Long skuId; 28 private Long skuId;
29 29
30 - @Schema(description = "商品价格,单位:分", required = true, example = "100") 30 + @Schema(description = "商品价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
31 private Integer price; 31 private Integer price;
32 32
33 - @Schema(description = "商品描述", required = true, example = "我要吃西红柿") 33 + @Schema(description = "商品描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "我要吃西红柿")
34 private String description; 34 private String description;
35 35
36 - @Schema(description = "砍价库存", required = true, example = "512") 36 + @Schema(description = "砍价库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
37 private Integer stock; 37 private Integer stock;
38 38
39 - @Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取 39 + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") // 从 SPU 的 picUrl 读取
40 private String picUrl; 40 private String picUrl;
41 41
42 - @Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取 42 + @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") // 从 SPU 的 marketPrice 读取
43 private Integer marketPrice; 43 private Integer marketPrice;
44 44
45 - @Schema(description = "商品单位", required = true, example = "个") // 从 SPU 的 unit 读取,然后转换 45 + @Schema(description = "商品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") // 从 SPU 的 unit 读取,然后转换
46 private String unitName; 46 private String unitName;
47 47
48 - @Schema(description = "砍价最低金额,单位:分", required = true, example = "100") 48 + @Schema(description = "砍价最低金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
49 private Integer bargainPrice; 49 private Integer bargainPrice;
50 50
51 - @Schema(description = "砍价成功数量", required = true, example = "100") 51 + @Schema(description = "砍价成功数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
52 private Integer successCount; 52 private Integer successCount;
53 53
54 } 54 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityRespVO.java
@@ -9,34 +9,34 @@ import java.time.LocalDateTime; @@ -9,34 +9,34 @@ import java.time.LocalDateTime;
9 @Data 9 @Data
10 public class AppBargainActivityRespVO { 10 public class AppBargainActivityRespVO {
11 11
12 - @Schema(description = "砍价活动编号", required = true, example = "1024") 12 + @Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 private Long id; 13 private Long id;
14 14
15 - @Schema(description = "砍价活动名称", required = true, example = "618 大砍价") 15 + @Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大砍价")
16 private String name; 16 private String name;
17 17
18 - @Schema(description = "活动开始时间", required = true) 18 + @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
19 private LocalDateTime startTime; 19 private LocalDateTime startTime;
20 20
21 - @Schema(description = "活动结束时间", required = true) 21 + @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
22 private LocalDateTime endTime; 22 private LocalDateTime endTime;
23 23
24 - @Schema(description = "商品 SPU 编号", required = true, example = "2048") 24 + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
25 private Long spuId; 25 private Long spuId;
26 26
27 - @Schema(description = "商品 SKU 编号", required = true, example = "1024") 27 + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
28 private Long skuId; 28 private Long skuId;
29 29
30 - @Schema(description = "砍价库存", required = true, example = "512") 30 + @Schema(description = "砍价库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
31 private Integer stock; 31 private Integer stock;
32 32
33 - @Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取 33 + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") // 从 SPU 的 picUrl 读取
34 private String picUrl; 34 private String picUrl;
35 35
36 - @Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取 36 + @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") // 从 SPU 的 marketPrice 读取
37 private Integer marketPrice; 37 private Integer marketPrice;
38 38
39 - @Schema(description = "砍价最低金额,单位:分", required = true, example = "100") 39 + @Schema(description = "砍价最低金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
40 private Integer bargainPrice; 40 private Integer bargainPrice;
41 41
42 } 42 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/help/AppBargainHelpCreateReqVO.java
@@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
9 @Data 9 @Data
10 public class AppBargainHelpCreateReqVO { 10 public class AppBargainHelpCreateReqVO {
11 11
12 - @Schema(description = "砍价记录编号", required = true, example = "1024") 12 + @Schema(description = "砍价记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 @NotNull(message = "砍价记录编号不能为空") 13 @NotNull(message = "砍价记录编号不能为空")
14 private Long recordId; 14 private Long recordId;
15 15
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/help/AppBargainHelpRespVO.java
@@ -9,16 +9,16 @@ import java.time.LocalDateTime; @@ -9,16 +9,16 @@ import java.time.LocalDateTime;
9 @Data 9 @Data
10 public class AppBargainHelpRespVO { 10 public class AppBargainHelpRespVO {
11 11
12 - @Schema(description = "助力用户的昵称", required = true, example = "1024") 12 + @Schema(description = "助力用户的昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 private String nickname; 13 private String nickname;
14 14
15 - @Schema(description = "助力用户的头像", required = true, example = "1024") 15 + @Schema(description = "助力用户的头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
16 private String avatar; 16 private String avatar;
17 17
18 - @Schema(description = "助力用户的砍价金额", required = true, example = "1024") 18 + @Schema(description = "助力用户的砍价金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
19 private Integer reducePrice; 19 private Integer reducePrice;
20 20
21 - @Schema(description = "创建时间", required = true, example = "1024") 21 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
22 private LocalDateTime createTime; 22 private LocalDateTime createTime;
23 23
24 } 24 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/record/AppBargainRecordCreateReqVO.java
@@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
9 @Data 9 @Data
10 public class AppBargainRecordCreateReqVO { 10 public class AppBargainRecordCreateReqVO {
11 11
12 - @Schema(description = "砍价活动编号", required = true, example = "1024") 12 + @Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 @NotNull(message = "砍价活动编号不能为空") 13 @NotNull(message = "砍价活动编号不能为空")
14 private Long activityId; 14 private Long activityId;
15 15
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/record/AppBargainRecordSummaryRespVO.java
@@ -9,23 +9,23 @@ import java.util.List; @@ -9,23 +9,23 @@ import java.util.List;
9 @Data 9 @Data
10 public class AppBargainRecordSummaryRespVO { 10 public class AppBargainRecordSummaryRespVO {
11 11
12 - @Schema(description = "砍价用户数量", required = true, example = "1024") 12 + @Schema(description = "砍价用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 private Integer userCount; 13 private Integer userCount;
14 14
15 - @Schema(description = "成功砍价的记录", required = true) // 只返回最近的 7 个 15 + @Schema(description = "成功砍价的记录", requiredMode = Schema.RequiredMode.REQUIRED) // 只返回最近的 7 个
16 private List<Record> successRecords; 16 private List<Record> successRecords;
17 17
18 @Schema(description = "成功砍价记录") 18 @Schema(description = "成功砍价记录")
19 @Data 19 @Data
20 public static class Record { 20 public static class Record {
21 21
22 - @Schema(description = "用户昵称", required = true, example = "王**") 22 + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王**")
23 private String nickname; 23 private String nickname;
24 24
25 - @Schema(description = "用户头像", required = true, example = "https://www.iocoder.cn/xxx.jpg") 25 + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
26 private String avatar; 26 private String avatar;
27 27
28 - @Schema(description = "活动名称", required = true, example = "天蚕土豆") 28 + @Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "天蚕土豆")
29 private String activityName; 29 private String activityName;
30 30
31 } 31 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
@@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
11 */ 11 */
12 public interface ErrorCodeConstants { 12 public interface ErrorCodeConstants {
13 13
14 - // ========== Order 模块 1011000000 ========== 14 + // ========== Order 模块 1-011-000-000 ==========
15 ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在"); 15 ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
16 ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在"); 16 ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
17 ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试"); 17 ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
@@ -33,45 +33,44 @@ public interface ErrorCodeConstants { @@ -33,45 +33,44 @@ public interface ErrorCodeConstants {
33 ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1011000028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元"); 33 ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1011000028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元");
34 ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态"); 34 ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态");
35 35
36 - // ========== After Sale 模块 1011000100 ==========  
37 - ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");  
38 - ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1011000101, "申请退款金额错误");  
39 - ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1011000102, "订单已关闭,无法申请售后");  
40 - ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1011000103, "订单未支付,无法申请售后");  
41 - ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1011000104, "订单未发货,无法申请【退货退款】售后");  
42 - ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1011000105, "订单项已申请售后,无法重复申请");  
43 - ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1011000106, "审批失败,售后状态不处于审批中");  
44 - ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试");  
45 - ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");  
46 - ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】");  
47 - ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000110, "退款失败,售后单状态不是【待退款】"); 36 + // ========== After Sale 模块 1-011-000-100 ==========
  37 + ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
  38 + ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1_011_000_101, "申请退款金额错误");
  39 + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1_011_000_102, "订单已关闭,无法申请售后");
  40 + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1_011_000_103, "订单未支付,无法申请售后");
  41 + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1_011_000_104, "订单未发货,无法申请【退货退款】售后");
  42 + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1_011_000_105, "订单项已申请售后,无法重复申请");
  43 + ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1_011_000_106, "审批失败,售后状态不处于审批中");
  44 + ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1_011_000_107, "操作售后单失败,请刷新后重试");
  45 + ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1_011_000_108, "退货失败,售后单状态不处于【待买家退货】");
  46 + ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1_011_000_109, "确认收货失败,售后单状态不处于【待确认收货】");
  47 + ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1_011_000_110, "退款失败,售后单状态不是【待退款】");
48 ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY = 48 ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY =
49 - new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】"); 49 + new ErrorCode(1_011_000_111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
50 50
51 - // ========== Cart 模块 1011002000 ==========  
52 - ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); 51 + // ========== Cart 模块 1-011-002-000 ==========
  52 + ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在");
53 53
54 - // ========== Price 相关 1011003000 ============ 54 + // ========== Price 相关 1-011-003-000 ============
55 ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0"); 55 ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
56 ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板"); 56 ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
57 ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵"); 57 ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
58 58
59 - // ========== 物流 Express 模块 1011004000 ==========  
60 - ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在");  
61 - ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011004001, "已经存在该编码的快递公司");  
62 - ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1011004002, "需要接入快递服务商,比如【快递100】");  
63 - ErrorCode EXPRESS_STATUS_NOT_ENABLE = new ErrorCode(1011004003, "快递公司未启用"); 59 + // ========== 物流 Express 模块 1-011-004-000 ==========
  60 + ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
  61 + ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1_011_004_001, "已经存在该编码的快递公司");
  62 + ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1_011_004_002, "需要接入快递服务商,比如【快递100】");
  63 + ErrorCode EXPRESS_STATUS_NOT_ENABLE = new ErrorCode(1_011_004_003, "快递公司未启用");
64 64
65 - ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011004101, "快递查询接口异常");  
66 - ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011004102, "快递查询返回失败,原因:{}"); 65 + ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1_011_004_101, "快递查询接口异常");
  66 + ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1_011_004_102, "快递查询返回失败,原因:{}");
67 67
68 - // ========== 物流 Template 模块 1011005000 ==========  
69 - ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011005000, "已经存在该运费模板名");  
70 - ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");  
71 -  
72 - // ========== 物流 PICK_UP 模块 1011006000 ==========  
73 - ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在"); 68 + // ========== 物流 Template 模块 1-011-005-000 ==========
  69 + ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1_011_005_000, "已经存在该运费模板名");
  70 + ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_011_005_001, "运费模板不存在");
74 71
  72 + // ========== 物流 PICK_UP 模块 1-011-006-000 ==========
  73 + ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店不存在");
75 74
76 // ========== 分销用户 模块 1011007000 ========== 75 // ========== 分销用户 模块 1011007000 ==========
77 ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); 76 ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/config/AppDeliveryConfigRespVO.java
@@ -8,10 +8,10 @@ import lombok.Data; @@ -8,10 +8,10 @@ import lombok.Data;
8 @Data 8 @Data
9 public class AppDeliveryConfigRespVO { 9 public class AppDeliveryConfigRespVO {
10 10
11 - @Schema(description = "腾讯地图 KEY", required = true, example = "123456") 11 + @Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
12 private String tencentLbsKey; 12 private String tencentLbsKey;
13 13
14 - @Schema(description = "是否开启自提", required = true, example = "true") 14 + @Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
15 private Boolean pickUpEnable; 15 private Boolean pickUpEnable;
16 16
17 } 17 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/express/AppDeliveryExpressRespVO.java
@@ -7,10 +7,10 @@ import lombok.Data; @@ -7,10 +7,10 @@ import lombok.Data;
7 @Data 7 @Data
8 public class AppDeliveryExpressRespVO { 8 public class AppDeliveryExpressRespVO {
9 9
10 - @Schema(description = "编号", required = true, example = "1") 10 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
11 private Long id; 11 private Long id;
12 12
13 - @Schema(description = "门店名称", required = true, example = "顺丰") 13 + @Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "顺丰")
14 private String name; 14 private String name;
15 15
16 } 16 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
@@ -25,12 +25,12 @@ public class AppTradeOrderSettlementReqVO { @@ -25,12 +25,12 @@ public class AppTradeOrderSettlementReqVO {
25 @Schema(description = "优惠劵编号", example = "1024") 25 @Schema(description = "优惠劵编号", example = "1024")
26 private Long couponId; 26 private Long couponId;
27 27
28 - @Schema(description = "是否使用积分", required = true, example = "true") 28 + @Schema(description = "是否使用积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
29 @NotNull(message = "是否使用积分不能为空") 29 @NotNull(message = "是否使用积分不能为空")
30 private Boolean pointStatus; 30 private Boolean pointStatus;
31 31
32 // ========== 配送相关相关字段 ========== 32 // ========== 配送相关相关字段 ==========
33 - @Schema(description = "配送方式", example = "1") 33 + @Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
34 @InEnum(value = DeliveryTypeEnum.class, message = "配送方式不正确") 34 @InEnum(value = DeliveryTypeEnum.class, message = "配送方式不正确")
35 private Integer deliveryType; 35 private Integer deliveryType;
36 36
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
@@ -13,7 +13,7 @@ import java.util.List; @@ -13,7 +13,7 @@ import java.util.List;
13 @Data 13 @Data
14 public class AppTradeOrderSettlementRespVO { 14 public class AppTradeOrderSettlementRespVO {
15 15
16 - @Schema(description = "交易类型", required = true, example = "1") // 对应 TradeOrderTypeEnum 枚举 16 + @Schema(description = "交易类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 对应 TradeOrderTypeEnum 枚举
17 private Integer type = 1; // TODO 芋艿:改成计算 17 private Integer type = 1; // TODO 芋艿:改成计算
18 18
19 @Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED) 19 @Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED)
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
@@ -9,51 +9,51 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,51 +9,51 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== 用户相关 1004001000============ 12 + // ========== 用户相关 1-004-001-000 ============
13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); 13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
14 ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); 14 ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户");
15 ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); 15 ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
16 ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1004001003, "用户积分余额不足"); 16 ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1004001003, "用户积分余额不足");
17 17
18 - // ========== AUTH 模块 1004003000 ==========  
19 - ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");  
20 - ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1004003001, "登录失败,账号被禁用");  
21 - ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定");  
22 - ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1004003006, "获得手机号失败");  
23 - ErrorCode AUTH_MOBILE_USED = new ErrorCode(1004003007, "手机号已经被使用"); 18 + // ========== AUTH 模块 1-004-003-000 ==========
  19 + ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,账号密码不正确");
  20 + ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_004_003_001, "登录失败,账号被禁用");
  21 + ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_004_003_005, "未绑定账号,需要进行绑定");
  22 + ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1_004_003_006, "获得手机号失败");
  23 + ErrorCode AUTH_MOBILE_USED = new ErrorCode(1_004_003_007, "手机号已经被使用");
24 24
25 - // ========== 用户收件地址 1004004000 ==========  
26 - ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在"); 25 + // ========== 用户收件地址 1-004-004-000 ==========
  26 + ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1_004_004_000, "用户收件地址不存在");
27 27
28 - //========== 用户标签 1004006000 ==========  
29 - ErrorCode TAG_NOT_EXISTS = new ErrorCode(1004006000, "用户标签不存在");  
30 - ErrorCode TAG_NAME_EXISTS = new ErrorCode(1004006001, "用户标签已经存在");  
31 - ErrorCode TAG_HAS_USER = new ErrorCode(1004006002, "用户标签下存在用户,无法删除"); 28 + //========== 用户标签 1-004-006-000 ==========
  29 + ErrorCode TAG_NOT_EXISTS = new ErrorCode(1_004_006_000, "用户标签不存在");
  30 + ErrorCode TAG_NAME_EXISTS = new ErrorCode(1_004_006_001, "用户标签已经存在");
  31 + ErrorCode TAG_HAS_USER = new ErrorCode(1_004_006_002, "用户标签下存在用户,无法删除");
32 32
33 - //========== 积分配置 1004007000 ========== 33 + //========== 积分配置 1-004-007-000 ==========
34 34
35 - //========== 积分记录 1004008000 ==========  
36 - ErrorCode POINT_RECORD_BIZ_NOT_SUPPORT = new ErrorCode(1004008000, "用户积分记录业务类型不支持"); 35 + //========== 积分记录 1-004-008-000 ==========
  36 + ErrorCode POINT_RECORD_BIZ_NOT_SUPPORT = new ErrorCode(1_004_008_000, "用户积分记录业务类型不支持");
37 37
38 - //========== 签到配置 1004009000 ==========  
39 - ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(1004009000, "签到天数规则不存在");  
40 - ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1004009001, "签到天数规则已存在"); 38 + //========== 签到配置 1-004-009-000 ==========
  39 + ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(1_004_009_000, "签到天数规则不存在");
  40 + ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1_004_009_001, "签到天数规则已存在");
41 41
42 - //========== 签到配置 1004010000 ========== 42 + //========== 签到配置 1-004-010-000 ==========
43 ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1004010000,"今日已签到,请勿重复签到"); 43 ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1004010000,"今日已签到,请勿重复签到");
44 44
45 - //========== 用户等级 1004011000 ==========  
46 - ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1004011000, "用户等级不存在");  
47 - ErrorCode LEVEL_NAME_EXISTS = new ErrorCode(1004011001, "用户等级名称[{}]已被使用");  
48 - ErrorCode LEVEL_VALUE_EXISTS = new ErrorCode(1004011002, "用户等级值[{}]已被[{}]使用");  
49 - ErrorCode LEVEL_EXPERIENCE_MIN = new ErrorCode(1004011003, "升级经验必须大于上一个等级[{}]设置的升级经验[{}]");  
50 - ErrorCode LEVEL_EXPERIENCE_MAX = new ErrorCode(1004011004, "升级经验必须小于下一个等级[{}]设置的升级经验[{}]");  
51 - ErrorCode LEVEL_HAS_USER = new ErrorCode(1004011005, "用户等级下存在用户,无法删除"); 45 + //========== 用户等级 1-004-011-000 ==========
  46 + ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1_004_011_000, "用户等级不存在");
  47 + ErrorCode LEVEL_NAME_EXISTS = new ErrorCode(1_004_011_001, "用户等级名称[{}]已被使用");
  48 + ErrorCode LEVEL_VALUE_EXISTS = new ErrorCode(1_004_011_002, "用户等级值[{}]已被[{}]使用");
  49 + ErrorCode LEVEL_EXPERIENCE_MIN = new ErrorCode(1_004_011_003, "升级经验必须大于上一个等级[{}]设置的升级经验[{}]");
  50 + ErrorCode LEVEL_EXPERIENCE_MAX = new ErrorCode(1_004_011_004, "升级经验必须小于下一个等级[{}]设置的升级经验[{}]");
  51 + ErrorCode LEVEL_HAS_USER = new ErrorCode(1_004_011_005, "用户等级下存在用户,无法删除");
52 52
53 - ErrorCode EXPERIENCE_BIZ_NOT_SUPPORT = new ErrorCode(1004011201, "用户经验业务类型不支持"); 53 + ErrorCode EXPERIENCE_BIZ_NOT_SUPPORT = new ErrorCode(1_004_011_201, "用户经验业务类型不支持");
54 54
55 - //========== 用户分组 1004012000 ==========  
56 - ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1004012000, "用户分组不存在");  
57 - ErrorCode GROUP_HAS_USER = new ErrorCode(1004012001, "用户分组下存在用户,无法删除"); 55 + //========== 用户分组 1-004-012-000 ==========
  56 + ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_004_012_000, "用户分组不存在");
  57 + ErrorCode GROUP_HAS_USER = new ErrorCode(1_004_012_001, "用户分组下存在用户,无法删除");
58 58
59 } 59 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java
@@ -33,7 +33,7 @@ public class AppAuthLoginReqVO { @@ -33,7 +33,7 @@ public class AppAuthLoginReqVO {
33 33
34 // ========== 绑定社交登录时,需要传递如下参数 ========== 34 // ========== 绑定社交登录时,需要传递如下参数 ==========
35 35
36 - @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 36 + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
37 @InEnum(SocialTypeEnum.class) 37 @InEnum(SocialTypeEnum.class)
38 private Integer socialType; 38 private Integer socialType;
39 39
@@ -53,4 +53,4 @@ public class AppAuthLoginReqVO { @@ -53,4 +53,4 @@ public class AppAuthLoginReqVO {
53 return socialType == null || StrUtil.isNotEmpty(socialState); 53 return socialType == null || StrUtil.isNotEmpty(socialState);
54 } 54 }
55 55
56 -} 56 -}
  57 +}
57 \ No newline at end of file 58 \ No newline at end of file
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java
@@ -35,7 +35,7 @@ public class AppAuthSmsLoginReqVO { @@ -35,7 +35,7 @@ public class AppAuthSmsLoginReqVO {
35 35
36 // ========== 绑定社交登录时,需要传递如下参数 ========== 36 // ========== 绑定社交登录时,需要传递如下参数 ==========
37 37
38 - @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 38 + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
39 @InEnum(SocialTypeEnum.class) 39 @InEnum(SocialTypeEnum.class)
40 private Integer socialType; 40 private Integer socialType;
41 41
@@ -55,4 +55,4 @@ public class AppAuthSmsLoginReqVO { @@ -55,4 +55,4 @@ public class AppAuthSmsLoginReqVO {
55 return socialType == null || StrUtil.isNotEmpty(socialState); 55 return socialType == null || StrUtil.isNotEmpty(socialState);
56 } 56 }
57 57
58 -} 58 -}
  59 +}
59 \ No newline at end of file 60 \ No newline at end of file
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull; @@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
18 @Builder 18 @Builder
19 public class AppAuthSocialLoginReqVO { 19 public class AppAuthSocialLoginReqVO {
20 20
21 - @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 21 + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
22 @InEnum(SocialTypeEnum.class) 22 @InEnum(SocialTypeEnum.class)
23 @NotNull(message = "社交平台的类型不能为空") 23 @NotNull(message = "社交平台的类型不能为空")
24 private Integer type; 24 private Integer type;
@@ -31,4 +31,4 @@ public class AppAuthSocialLoginReqVO { @@ -31,4 +31,4 @@ public class AppAuthSocialLoginReqVO {
31 @NotEmpty(message = "state 不能为空") 31 @NotEmpty(message = "state 不能为空")
32 private String state; 32 private String state;
33 33
34 -} 34 -}
  35 +}
35 \ No newline at end of file 36 \ No newline at end of file
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull; @@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
18 @Builder 18 @Builder
19 public class AppSocialUserBindReqVO { 19 public class AppSocialUserBindReqVO {
20 20
21 - @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 21 + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
22 @InEnum(SocialTypeEnum.class) 22 @InEnum(SocialTypeEnum.class)
23 @NotNull(message = "社交平台的类型不能为空") 23 @NotNull(message = "社交平台的类型不能为空")
24 private Integer type; 24 private Integer type;
@@ -31,4 +31,4 @@ public class AppSocialUserBindReqVO { @@ -31,4 +31,4 @@ public class AppSocialUserBindReqVO {
31 @NotEmpty(message = "state 不能为空") 31 @NotEmpty(message = "state 不能为空")
32 private String state; 32 private String state;
33 33
34 -} 34 -}
  35 +}
35 \ No newline at end of file 36 \ No newline at end of file
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java
@@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull; @@ -18,7 +18,7 @@ import javax.validation.constraints.NotNull;
18 @Builder 18 @Builder
19 public class AppSocialUserUnbindReqVO { 19 public class AppSocialUserUnbindReqVO {
20 20
21 - @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 21 + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
22 @InEnum(SocialTypeEnum.class) 22 @InEnum(SocialTypeEnum.class)
23 @NotNull(message = "社交平台的类型不能为空") 23 @NotNull(message = "社交平台的类型不能为空")
24 private Integer type; 24 private Integer type;
@@ -27,4 +27,4 @@ public class AppSocialUserUnbindReqVO { @@ -27,4 +27,4 @@ public class AppSocialUserUnbindReqVO {
27 @NotEmpty(message = "社交用户的 openid 不能为空") 27 @NotEmpty(message = "社交用户的 openid 不能为空")
28 private String openid; 28 private String openid;
29 29
30 -} 30 -}
  31 +}
31 \ No newline at end of file 32 \ No newline at end of file
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
@@ -222,10 +222,10 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -222,10 +222,10 @@ public class MemberUserServiceImpl implements MemberUserService {
222 } 222 }
223 // 如果 id 为空,说明不用比较是否为相同 id 的用户 223 // 如果 id 为空,说明不用比较是否为相同 id 的用户
224 if (id == null) { 224 if (id == null) {
225 - throw exception(USER_MOBILE_USED); 225 + throw exception(USER_MOBILE_USED, mobile);
226 } 226 }
227 if (!user.getId().equals(id)) { 227 if (!user.getId().equals(id)) {
228 - throw exception(USER_MOBILE_USED); 228 + throw exception(USER_MOBILE_USED, mobile);
229 } 229 }
230 } 230 }
231 231
yudao-module-mp/yudao-module-mp-api/src/main/java/cn/iocoder/yudao/module/mp/enums/ErrorCodeConstants.java
@@ -9,56 +9,56 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,56 +9,56 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== 公众号账号 1006000000============  
13 - ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1006000000, "公众号账号不存在");  
14 - ErrorCode ACCOUNT_GENERATE_QR_CODE_FAIL = new ErrorCode(1006000001, "生成公众号二维码失败,原因:{}");  
15 - ErrorCode ACCOUNT_CLEAR_QUOTA_FAIL = new ErrorCode(1006000002, "清空公众号的 API 配额失败,原因:{}"); 12 + // ========== 公众号账号 1-006-000-000 ============
  13 + ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1_006_000_000, "公众号账号不存在");
  14 + ErrorCode ACCOUNT_GENERATE_QR_CODE_FAIL = new ErrorCode(1_006_000_001, "生成公众号二维码失败,原因:{}");
  15 + ErrorCode ACCOUNT_CLEAR_QUOTA_FAIL = new ErrorCode(1_006_000_002, "清空公众号的 API 配额失败,原因:{}");
16 16
17 - // ========== 公众号统计 1006001000============  
18 - ErrorCode STATISTICS_GET_USER_SUMMARY_FAIL = new ErrorCode(1006001000, "获取粉丝增减数据失败,原因:{}");  
19 - ErrorCode STATISTICS_GET_USER_CUMULATE_FAIL = new ErrorCode(1006001001, "获得粉丝累计数据失败,原因:{}");  
20 - ErrorCode STATISTICS_GET_UPSTREAM_MESSAGE_FAIL = new ErrorCode(1006001002, "获得消息发送概况数据失败,原因:{}");  
21 - ErrorCode STATISTICS_GET_INTERFACE_SUMMARY_FAIL = new ErrorCode(1006001003, "获得接口分析数据失败,原因:{}"); 17 + // ========== 公众号统计 1-006-001-000 ============
  18 + ErrorCode STATISTICS_GET_USER_SUMMARY_FAIL = new ErrorCode(1_006_001_000, "获取粉丝增减数据失败,原因:{}");
  19 + ErrorCode STATISTICS_GET_USER_CUMULATE_FAIL = new ErrorCode(1_006_001_001, "获得粉丝累计数据失败,原因:{}");
  20 + ErrorCode STATISTICS_GET_UPSTREAM_MESSAGE_FAIL = new ErrorCode(1_006_001_002, "获得消息发送概况数据失败,原因:{}");
  21 + ErrorCode STATISTICS_GET_INTERFACE_SUMMARY_FAIL = new ErrorCode(1_006_001_003, "获得接口分析数据失败,原因:{}");
22 22
23 - // ========== 公众号标签 1006002000============  
24 - ErrorCode TAG_NOT_EXISTS = new ErrorCode(1006002000, "标签不存在");  
25 - ErrorCode TAG_CREATE_FAIL = new ErrorCode(1006002001, "创建标签失败,原因:{}");  
26 - ErrorCode TAG_UPDATE_FAIL = new ErrorCode(1006002002, "更新标签失败,原因:{}");  
27 - ErrorCode TAG_DELETE_FAIL = new ErrorCode(1006002003, "删除标签失败,原因:{}");  
28 - ErrorCode TAG_GET_FAIL = new ErrorCode(1006002004, "获得标签失败,原因:{}"); 23 + // ========== 公众号标签 1-006-002-000 ============
  24 + ErrorCode TAG_NOT_EXISTS = new ErrorCode(1_006_002_000, "标签不存在");
  25 + ErrorCode TAG_CREATE_FAIL = new ErrorCode(1_006_002_001, "创建标签失败,原因:{}");
  26 + ErrorCode TAG_UPDATE_FAIL = new ErrorCode(1_006_002_002, "更新标签失败,原因:{}");
  27 + ErrorCode TAG_DELETE_FAIL = new ErrorCode(1_006_002_003, "删除标签失败,原因:{}");
  28 + ErrorCode TAG_GET_FAIL = new ErrorCode(1_006_002_004, "获得标签失败,原因:{}");
29 29
30 - // ========== 公众号粉丝 1006003000============  
31 - ErrorCode USER_NOT_EXISTS = new ErrorCode(1006003000, "粉丝不存在");  
32 - ErrorCode USER_UPDATE_TAG_FAIL = new ErrorCode(1006003001, "更新粉丝标签失败,原因:{}"); 30 + // ========== 公众号粉丝 1-006-003-000 ============
  31 + ErrorCode USER_NOT_EXISTS = new ErrorCode(1_006_003_000, "粉丝不存在");
  32 + ErrorCode USER_UPDATE_TAG_FAIL = new ErrorCode(1_006_003_001, "更新粉丝标签失败,原因:{}");
33 33
34 - // ========== 公众号素材 1006004000============  
35 - ErrorCode MATERIAL_NOT_EXISTS = new ErrorCode(1006004000, "素材不存在");  
36 - ErrorCode MATERIAL_UPLOAD_FAIL = new ErrorCode(1006004001, "上传素材失败,原因:{}");  
37 - ErrorCode MATERIAL_IMAGE_UPLOAD_FAIL = new ErrorCode(1006004002, "上传图片失败,原因:{}");  
38 - ErrorCode MATERIAL_DELETE_FAIL = new ErrorCode(1006004003, "删除素材失败,原因:{}"); 34 + // ========== 公众号素材 1-006-004-000 ============
  35 + ErrorCode MATERIAL_NOT_EXISTS = new ErrorCode(1_006_004_000, "素材不存在");
  36 + ErrorCode MATERIAL_UPLOAD_FAIL = new ErrorCode(1_006_004_001, "上传素材失败,原因:{}");
  37 + ErrorCode MATERIAL_IMAGE_UPLOAD_FAIL = new ErrorCode(1_006_004_002, "上传图片失败,原因:{}");
  38 + ErrorCode MATERIAL_DELETE_FAIL = new ErrorCode(1_006_004_003, "删除素材失败,原因:{}");
39 39
40 - // ========== 公众号消息 1006005000============  
41 - ErrorCode MESSAGE_SEND_FAIL = new ErrorCode(1006005000, "发送消息失败,原因:{}"); 40 + // ========== 公众号消息 1-006-005-000 ============
  41 + ErrorCode MESSAGE_SEND_FAIL = new ErrorCode(1_006_005_000, "发送消息失败,原因:{}");
42 42
43 - // ========== 公众号发布能力 1006006000============  
44 - ErrorCode FREE_PUBLISH_LIST_FAIL = new ErrorCode(1006006000, "获得已成功发布列表失败,原因:{}");  
45 - ErrorCode FREE_PUBLISH_SUBMIT_FAIL = new ErrorCode(1006006001, "提交发布失败,原因:{}");  
46 - ErrorCode FREE_PUBLISH_DELETE_FAIL = new ErrorCode(1006006002, "删除发布失败,原因:{}"); 43 + // ========== 公众号发布能力 1-006-006-000 ============
  44 + ErrorCode FREE_PUBLISH_LIST_FAIL = new ErrorCode(1_006_006_000, "获得已成功发布列表失败,原因:{}");
  45 + ErrorCode FREE_PUBLISH_SUBMIT_FAIL = new ErrorCode(1_006_006_001, "提交发布失败,原因:{}");
  46 + ErrorCode FREE_PUBLISH_DELETE_FAIL = new ErrorCode(1_006_006_002, "删除发布失败,原因:{}");
47 47
48 - // ========== 公众号草稿 1006007000============  
49 - ErrorCode DRAFT_LIST_FAIL = new ErrorCode(1006007000, "获得草稿列表失败,原因:{}");  
50 - ErrorCode DRAFT_CREATE_FAIL = new ErrorCode(1006007001, "创建草稿失败,原因:{}");  
51 - ErrorCode DRAFT_UPDATE_FAIL = new ErrorCode(1006007002, "更新草稿失败,原因:{}");  
52 - ErrorCode DRAFT_DELETE_FAIL = new ErrorCode(1006007003, "删除草稿失败,原因:{}"); 48 + // ========== 公众号草稿 1-006-007-000 ============
  49 + ErrorCode DRAFT_LIST_FAIL = new ErrorCode(1_006_007_000, "获得草稿列表失败,原因:{}");
  50 + ErrorCode DRAFT_CREATE_FAIL = new ErrorCode(1_006_007_001, "创建草稿失败,原因:{}");
  51 + ErrorCode DRAFT_UPDATE_FAIL = new ErrorCode(1_006_007_002, "更新草稿失败,原因:{}");
  52 + ErrorCode DRAFT_DELETE_FAIL = new ErrorCode(1_006_007_003, "删除草稿失败,原因:{}");
53 53
54 - // ========== 公众号菜单 1006008000============  
55 - ErrorCode MENU_SAVE_FAIL = new ErrorCode(1006008000, "创建菜单失败,原因:{}");  
56 - ErrorCode MENU_DELETE_FAIL = new ErrorCode(1006008001, "删除菜单失败,原因:{}"); 54 + // ========== 公众号菜单 1-006-008-000 ============
  55 + ErrorCode MENU_SAVE_FAIL = new ErrorCode(1_006_008_000, "创建菜单失败,原因:{}");
  56 + ErrorCode MENU_DELETE_FAIL = new ErrorCode(1_006_008_001, "删除菜单失败,原因:{}");
57 57
58 - // ========== 公众号自动回复 1006009000============  
59 - ErrorCode AUTO_REPLY_NOT_EXISTS = new ErrorCode(1006009000, "自动回复不存在");  
60 - ErrorCode AUTO_REPLY_ADD_SUBSCRIBE_FAIL_EXISTS = new ErrorCode(1006009001, "操作失败,原因:已存在关注时的回复");  
61 - ErrorCode AUTO_REPLY_ADD_MESSAGE_FAIL_EXISTS = new ErrorCode(1006009002, "操作失败,原因:已存在该消息类型的回复");  
62 - ErrorCode AUTO_REPLY_ADD_KEYWORD_FAIL_EXISTS = new ErrorCode(1006009003, "操作失败,原因:已关在该关键字的回复"); 58 + // ========== 公众号自动回复 1-006-009-000 ============
  59 + ErrorCode AUTO_REPLY_NOT_EXISTS = new ErrorCode(1_006_009_000, "自动回复不存在");
  60 + ErrorCode AUTO_REPLY_ADD_SUBSCRIBE_FAIL_EXISTS = new ErrorCode(1_006_009_001, "操作失败,原因:已存在关注时的回复");
  61 + ErrorCode AUTO_REPLY_ADD_MESSAGE_FAIL_EXISTS = new ErrorCode(1_006_009_002, "操作失败,原因:已存在该消息类型的回复");
  62 + ErrorCode AUTO_REPLY_ADD_KEYWORD_FAIL_EXISTS = new ErrorCode(1_006_009_003, "操作失败,原因:已关在该关键字的回复");
63 63
64 } 64 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -9,36 +9,38 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,36 +9,38 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== APP 模块 1007000000 ==========  
13 - ErrorCode APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在");  
14 - ErrorCode APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用");  
15 - ErrorCode APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在支付订单,无法删除");  
16 - ErrorCode APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1007000004, "支付应用存在退款订单,无法删除"); 12 + // ========== APP 模块 1-007-000-000 ==========
  13 + ErrorCode APP_NOT_FOUND = new ErrorCode(1_007_000_000, "App 不存在");
  14 + ErrorCode APP_IS_DISABLE = new ErrorCode(1_007_000_002, "App 已经被禁用");
  15 + ErrorCode APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1_007_000_003, "支付应用存在支付订单,无法删除");
  16 + ErrorCode APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1_007_000_004, "支付应用存在退款订单,无法删除");
17 17
18 - // ========== CHANNEL 模块 1007001000 ==========  
19 - ErrorCode CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在");  
20 - ErrorCode CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用");  
21 - ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001004, "已存在相同的渠道"); 18 + // ========== CHANNEL 模块 1-007-001-000 ==========
  19 + ErrorCode CHANNEL_NOT_FOUND = new ErrorCode(1_007_001_000, "支付渠道的配置不存在");
  20 + ErrorCode CHANNEL_IS_DISABLE = new ErrorCode(1_007_001_001, "支付渠道已经禁用");
  21 + ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1_007_001_004, "已存在相同的渠道");
22 22
23 - // ========== ORDER 模块 1007002000 ========== 23 + // ========== ORDER 模块 1-007-002-000 ==========
24 ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); 24 ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在");
25 ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); 25 ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付");
26 ErrorCode PAY_ORDER_STATUS_IS_SUCCESS = new ErrorCode(1007002002, "订单已支付,请刷新页面"); 26 ErrorCode PAY_ORDER_STATUS_IS_SUCCESS = new ErrorCode(1007002002, "订单已支付,请刷新页面");
27 ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期"); 27 ErrorCode PAY_ORDER_IS_EXPIRED = new ErrorCode(1007002003, "支付订单已经过期");
28 ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}"); 28 ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1007002004, "发起支付报错,错误码:{},错误提示:{}");
29 ErrorCode PAY_ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款"); 29 ErrorCode PAY_ORDER_REFUND_FAIL_STATUS_ERROR = new ErrorCode(1007002005, "支付订单退款失败,原因:状态不是已支付或已退款");
  30 + ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1_007_002_006, "支付订单调价失败,原因:支付订单已付款,不能调价");
  31 + ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1007002007, "支付订单调价失败,原因:价格没有变化");
30 32
31 - // ========== ORDER 模块(拓展单) 1007003000 ========== 33 + // ========== ORDER 模块(拓展单) 1-007-003-000 ==========
32 ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在"); 34 ErrorCode PAY_ORDER_EXTENSION_NOT_FOUND = new ErrorCode(1007003000, "支付交易拓展单不存在");
33 ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付"); 35 ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
34 ErrorCode PAY_ORDER_EXTENSION_IS_PAID = new ErrorCode(1007003002, "订单已支付,请等待支付结果"); 36 ErrorCode PAY_ORDER_EXTENSION_IS_PAID = new ErrorCode(1007003002, "订单已支付,请等待支付结果");
35 37
36 - // ========== 支付模块(退款) 1007006000 ==========  
37 - ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额");  
38 - ErrorCode REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中");  
39 - ErrorCode REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单");  
40 - ErrorCode REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");  
41 - ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款"); 38 + // ========== 支付模块(退款) 1-007-006-000 ==========
  39 + ErrorCode REFUND_PRICE_EXCEED = new ErrorCode(1_007_006_000, "退款金额超过订单可退款金额");
  40 + ErrorCode REFUND_HAS_REFUNDING = new ErrorCode(1_007_006_002, "已经有退款在处理中");
  41 + ErrorCode REFUND_EXISTS = new ErrorCode(1_007_006_003, "已经存在退款单");
  42 + ErrorCode REFUND_NOT_FOUND = new ErrorCode(1_007_006_004, "支付退款单不存在");
  43 + ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_006_005, "支付退款单不处于待退款");
42 44
43 // ========== 钱包模块 1007007000 ========== 45 // ========== 钱包模块 1007007000 ==========
44 ErrorCode WALLET_NOT_FOUND = new ErrorCode(1007007000, "用户钱包不存在"); 46 ErrorCode WALLET_NOT_FOUND = new ErrorCode(1007007000, "用户钱包不存在");
@@ -47,7 +49,7 @@ public interface ErrorCodeConstants { @@ -47,7 +49,7 @@ public interface ErrorCodeConstants {
47 ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1007007003, "已经存在钱包退款"); 49 ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1007007003, "已经存在钱包退款");
48 ErrorCode WALLET_FREEZE_PRICE_NOT_ENOUGH = new ErrorCode(1007007004, "钱包冻结余额不足"); 50 ErrorCode WALLET_FREEZE_PRICE_NOT_ENOUGH = new ErrorCode(1007007004, "钱包冻结余额不足");
49 51
50 - // ========== 钱包充值模块 1007008000 ========== 52 + // ========== 钱包模块 1-007-007-000 ==========
51 ErrorCode WALLET_RECHARGE_NOT_FOUND = new ErrorCode(1007008000, "钱包充值记录不存在"); 53 ErrorCode WALLET_RECHARGE_NOT_FOUND = new ErrorCode(1007008000, "钱包充值记录不存在");
52 ErrorCode WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007008001, "钱包充值更新支付状态失败,钱包充值记录不是【未支付】状态"); 54 ErrorCode WALLET_RECHARGE_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007008001, "钱包充值更新支付状态失败,钱包充值记录不是【未支付】状态");
53 ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1007008002, "钱包充值更新支付状态失败,支付单编号不匹配"); 55 ErrorCode WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR = new ErrorCode(1007008002, "钱包充值更新支付状态失败,支付单编号不匹配");
@@ -59,7 +61,8 @@ public interface ErrorCodeConstants { @@ -59,7 +61,8 @@ public interface ErrorCodeConstants {
59 ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007008008, "钱包退款更新失败,钱包退款单编号不匹配"); 61 ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1007008008, "钱包退款更新失败,钱包退款单编号不匹配");
60 ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007008009, "钱包退款更新失败,退款订单不存在"); 62 ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1007008009, "钱包退款更新失败,退款订单不存在");
61 ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007008010, "钱包退款更新失败,退款单金额不匹配"); 63 ErrorCode WALLET_RECHARGE_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1007008010, "钱包退款更新失败,退款单金额不匹配");
62 - // ========== 示例订单 1007900000 ========== 64 +
  65 + // ========== 示例订单 1-007-900-000 ==========
63 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); 66 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在");
64 ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态"); 67 ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1007900001, "示例订单更新支付状态失败,订单不是【未支付】状态");
65 ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配"); 68 ErrorCode DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1007900002, "示例订单更新支付状态失败,支付单编号不匹配");
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 7 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
8 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
9 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
10 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; 9 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
11 import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; 10 import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
@@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; @@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
16 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; 15 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; 16 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
18 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 17 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
  18 +import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
19 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; 19 import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
20 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 20 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
21 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 21 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
@@ -53,9 +53,8 @@ public class PayNotifyController { @@ -53,9 +53,8 @@ public class PayNotifyController {
53 private PayNotifyService notifyService; 53 private PayNotifyService notifyService;
54 @Resource 54 @Resource
55 private PayAppService appService; 55 private PayAppService appService;
56 -  
57 @Resource 56 @Resource
58 - private PayClientFactory payClientFactory; 57 + private PayChannelService channelService;
59 58
60 @PostMapping(value = "/order/{channelId}") 59 @PostMapping(value = "/order/{channelId}")
61 @Operation(summary = "支付渠道的统一【支付】回调") 60 @Operation(summary = "支付渠道的统一【支付】回调")
@@ -66,7 +65,7 @@ public class PayNotifyController { @@ -66,7 +65,7 @@ public class PayNotifyController {
66 @RequestBody(required = false) String body) { 65 @RequestBody(required = false) String body) {
67 log.info("[notifyOrder][channelId({}) 回调数据({}/{})]", channelId, params, body); 66 log.info("[notifyOrder][channelId({}) 回调数据({}/{})]", channelId, params, body);
68 // 1. 校验支付渠道是否存在 67 // 1. 校验支付渠道是否存在
69 - PayClient payClient = payClientFactory.getPayClient(channelId); 68 + PayClient payClient = channelService.getPayClient(channelId);
70 if (payClient == null) { 69 if (payClient == null) {
71 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 70 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
72 throw exception(CHANNEL_NOT_FOUND); 71 throw exception(CHANNEL_NOT_FOUND);
@@ -87,7 +86,7 @@ public class PayNotifyController { @@ -87,7 +86,7 @@ public class PayNotifyController {
87 @RequestBody(required = false) String body) { 86 @RequestBody(required = false) String body) {
88 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body); 87 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
89 // 1. 校验支付渠道是否存在 88 // 1. 校验支付渠道是否存在
90 - PayClient payClient = payClientFactory.getPayClient(channelId); 89 + PayClient payClient = channelService.getPayClient(channelId);
91 if (payClient == null) { 90 if (payClient == null) {
92 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); 91 log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
93 throw exception(CHANNEL_NOT_FOUND); 92 throw exception(CHANNEL_NOT_FOUND);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java
@@ -13,16 +13,16 @@ import java.time.LocalDateTime; @@ -13,16 +13,16 @@ import java.time.LocalDateTime;
13 @ToString(callSuper = true) 13 @ToString(callSuper = true)
14 public class PayOrderDetailsRespVO extends PayOrderBaseVO { 14 public class PayOrderDetailsRespVO extends PayOrderBaseVO {
15 15
16 - @Schema(description = "支付订单编号", required = true, example = "1024") 16 + @Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
17 private Long id; 17 private Long id;
18 18
19 @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") 19 @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
20 private String appName; 20 private String appName;
21 21
22 - @Schema(description = "创建时间", required = true) 22 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
23 private LocalDateTime createTime; 23 private LocalDateTime createTime;
24 24
25 - @Schema(description = "更新时间", required = true) 25 + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
26 private LocalDateTime updateTime; 26 private LocalDateTime updateTime;
27 27
28 /** 28 /**
@@ -34,7 +34,7 @@ public class PayOrderDetailsRespVO extends PayOrderBaseVO { @@ -34,7 +34,7 @@ public class PayOrderDetailsRespVO extends PayOrderBaseVO {
34 @Schema(description = "支付订单扩展") 34 @Schema(description = "支付订单扩展")
35 public static class PayOrderExtension { 35 public static class PayOrderExtension {
36 36
37 - @Schema(description = "支付订单号", required = true, example = "1024") 37 + @Schema(description = "支付订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
38 private String no; 38 private String no;
39 39
40 @Schema(description = "支付异步通知的内容") 40 @Schema(description = "支付异步通知的内容")
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/channel/PayChannelMapper.java
@@ -28,7 +28,4 @@ public interface PayChannelMapper extends BaseMapperX&lt;PayChannelDO&gt; { @@ -28,7 +28,4 @@ public interface PayChannelMapper extends BaseMapperX&lt;PayChannelDO&gt; {
28 .eq(PayChannelDO::getStatus, status)); 28 .eq(PayChannelDO::getStatus, status));
29 } 29 }
30 30
31 - @Select("SELECT COUNT(*) FROM pay_channel WHERE update_time > #{maxUpdateTime}")  
32 - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);  
33 -  
34 } 31 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java
@@ -15,7 +15,6 @@ import javax.annotation.Resource; @@ -15,7 +15,6 @@ import javax.annotation.Resource;
15 * @author 芋道源码 15 * @author 芋道源码
16 */ 16 */
17 @Component 17 @Component
18 -@TenantJob // 多租户  
19 @Slf4j 18 @Slf4j
20 public class PayNotifyJob implements JobHandler { 19 public class PayNotifyJob implements JobHandler {
21 20
@@ -23,6 +22,7 @@ public class PayNotifyJob implements JobHandler { @@ -23,6 +22,7 @@ public class PayNotifyJob implements JobHandler {
23 private PayNotifyService payNotifyService; 22 private PayNotifyService payNotifyService;
24 23
25 @Override 24 @Override
  25 + @TenantJob
26 public String execute(String param) throws Exception { 26 public String execute(String param) throws Exception {
27 int notifyCount = payNotifyService.executeNotify(); 27 int notifyCount = payNotifyService.executeNotify();
28 return String.format("执行支付通知 %s 个", notifyCount); 28 return String.format("执行支付通知 %s 个", notifyCount);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderExpireJob.java
@@ -16,13 +16,13 @@ import javax.annotation.Resource; @@ -16,13 +16,13 @@ import javax.annotation.Resource;
16 * @author 芋道源码 16 * @author 芋道源码
17 */ 17 */
18 @Component 18 @Component
19 -@TenantJob  
20 public class PayOrderExpireJob implements JobHandler { 19 public class PayOrderExpireJob implements JobHandler {
21 20
22 @Resource 21 @Resource
23 private PayOrderService orderService; 22 private PayOrderService orderService;
24 23
25 @Override 24 @Override
  25 + @TenantJob
26 public String execute(String param) { 26 public String execute(String param) {
27 int count = orderService.expireOrder(); 27 int count = orderService.expireOrder();
28 return StrUtil.format("支付过期 {} 个", count); 28 return StrUtil.format("支付过期 {} 个", count);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/order/PayOrderSyncJob.java
@@ -18,7 +18,6 @@ import java.time.LocalDateTime; @@ -18,7 +18,6 @@ import java.time.LocalDateTime;
18 * @author 芋道源码 18 * @author 芋道源码
19 */ 19 */
20 @Component 20 @Component
21 -@TenantJob  
22 public class PayOrderSyncJob implements JobHandler { 21 public class PayOrderSyncJob implements JobHandler {
23 22
24 /** 23 /**
@@ -34,6 +33,7 @@ public class PayOrderSyncJob implements JobHandler { @@ -34,6 +33,7 @@ public class PayOrderSyncJob implements JobHandler {
34 private PayOrderService orderService; 33 private PayOrderService orderService;
35 34
36 @Override 35 @Override
  36 + @TenantJob
37 public String execute(String param) { 37 public String execute(String param) {
38 LocalDateTime minCreateTime = LocalDateTime.now().minus(CREATE_TIME_DURATION_BEFORE); 38 LocalDateTime minCreateTime = LocalDateTime.now().minus(CREATE_TIME_DURATION_BEFORE);
39 int count = orderService.syncOrder(minCreateTime); 39 int count = orderService.syncOrder(minCreateTime);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/refund/PayRefundSyncJob.java
@@ -16,13 +16,13 @@ import javax.annotation.Resource; @@ -16,13 +16,13 @@ import javax.annotation.Resource;
16 * @author 芋道源码 16 * @author 芋道源码
17 */ 17 */
18 @Component 18 @Component
19 -@TenantJob  
20 public class PayRefundSyncJob implements JobHandler { 19 public class PayRefundSyncJob implements JobHandler {
21 20
22 @Resource 21 @Resource
23 private PayRefundService refundService; 22 private PayRefundService refundService;
24 23
25 @Override 24 @Override
  25 + @TenantJob
26 public String execute(String param) { 26 public String execute(String param) {
27 int count = refundService.syncRefund(); 27 int count = refundService.syncRefund();
28 return StrUtil.format("同步退款订单 {} 个", count); 28 return StrUtil.format("同步退款订单 {} 个", count);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelService.java
1 package cn.iocoder.yudao.module.pay.service.channel; 1 package cn.iocoder.yudao.module.pay.service.channel;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
  4 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
4 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO; 5 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO;
5 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
@@ -92,4 +93,12 @@ public interface PayChannelService { @@ -92,4 +93,12 @@ public interface PayChannelService {
92 */ 93 */
93 List<PayChannelDO> getEnableChannelList(Long appId); 94 List<PayChannelDO> getEnableChannelList(Long appId);
94 95
  96 + /**
  97 + * 获得指定编号的支付客户端
  98 + *
  99 + * @param id 编号
  100 + * @return 支付客户端
  101 + */
  102 + PayClient getPayClient(Long id);
  103 +
95 } 104 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java
1 package cn.iocoder.yudao.module.pay.service.channel; 1 package cn.iocoder.yudao.module.pay.service.channel;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  7 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
9 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 8 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
10 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; 9 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
11 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 10 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
12 -import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;  
13 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO; 11 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelCreateReqVO;
14 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO; 12 import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateReqVO;
15 import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; 13 import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert;
16 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 14 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
17 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; 15 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
18 -import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient; 16 +import com.google.common.cache.CacheLoader;
  17 +import com.google.common.cache.LoadingCache;
19 import lombok.Getter; 18 import lombok.Getter;
20 -import lombok.Setter;  
21 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
22 -import org.springframework.scheduling.annotation.Scheduled;  
23 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
24 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
25 22
26 -import javax.annotation.PostConstruct;  
27 import javax.annotation.Resource; 23 import javax.annotation.Resource;
28 import javax.validation.Validator; 24 import javax.validation.Validator;
29 -import java.time.LocalDateTime; 25 +import java.time.Duration;
30 import java.util.Collection; 26 import java.util.Collection;
31 -import java.util.Collections;  
32 import java.util.List; 27 import java.util.List;
33 -import java.util.concurrent.TimeUnit;  
34 28
35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  30 +import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
36 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 31 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
37 32
38 /** 33 /**
@@ -45,71 +40,34 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; @@ -45,71 +40,34 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
45 @Validated 40 @Validated
46 public class PayChannelServiceImpl implements PayChannelService { 41 public class PayChannelServiceImpl implements PayChannelService {
47 42
48 - @Getter // 为了方便测试,这里提供 getter 方法  
49 - @Setter  
50 - private volatile List<PayChannelDO> channelCache; 43 + /**
  44 + * {@link PayClient} 缓存,通过它异步清空 smsClientFactory
  45 + */
  46 + @Getter
  47 + private final LoadingCache<Long, PayClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
  48 + new CacheLoader<Long, PayClient>() {
  49 +
  50 + @Override
  51 + public PayClient load(Long id) {
  52 + // 查询,然后尝试清空
  53 + PayChannelDO channel = payChannelMapper.selectById(id);
  54 + if (channel != null) {
  55 + payClientFactory.createOrUpdatePayClient(channel.getId(), channel.getCode(), channel.getConfig());
  56 + }
  57 + return payClientFactory.getPayClient(id);
  58 + }
  59 +
  60 + });
51 61
52 @Resource 62 @Resource
53 private PayClientFactory payClientFactory; 63 private PayClientFactory payClientFactory;
54 64
55 @Resource 65 @Resource
56 - private PayChannelMapper channelMapper; 66 + private PayChannelMapper payChannelMapper;
57 67
58 @Resource 68 @Resource
59 private Validator validator; 69 private Validator validator;
60 70
61 - /**  
62 - * 初始化 {@link #payClientFactory} 缓存  
63 - */  
64 - @PostConstruct  
65 - public void initLocalCache() {  
66 - // 注册钱包支付 Class  
67 - payClientFactory.registerPayClientClass(PayChannelEnum.WALLET, WalletPayClient.class);  
68 -  
69 - // 注意:忽略自动多租户,因为要全局初始化缓存  
70 - TenantUtils.executeIgnore(() -> {  
71 - // 第一步:查询数据  
72 - List<PayChannelDO> channels = Collections.emptyList();  
73 - try {  
74 - channels = channelMapper.selectList();  
75 - } catch (Throwable ex) {  
76 - if (!ex.getMessage().contains("doesn't exist")) {  
77 - throw ex;  
78 - }  
79 - log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");  
80 - }  
81 - log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size());  
82 -  
83 - // 第二步:构建缓存:创建或更新支付 Client  
84 - channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),  
85 - payChannel.getCode(), payChannel.getConfig()));  
86 - this.channelCache = channels;  
87 - });  
88 - }  
89 -  
90 - /**  
91 - * 通过定时任务轮询,刷新缓存  
92 - *  
93 - * 目的:多节点部署时,通过轮询”通知“所有节点,进行刷新  
94 - */  
95 - @Scheduled(initialDelay = 60, fixedRate = 60, timeUnit = TimeUnit.SECONDS)  
96 - public void refreshLocalCache() {  
97 - // 注意:忽略自动多租户,因为要全局初始化缓存  
98 - TenantUtils.executeIgnore(() -> {  
99 - // 情况一:如果缓存里没有数据,则直接刷新缓存  
100 - if (CollUtil.isEmpty(channelCache)) {  
101 - initLocalCache();  
102 - return;  
103 - }  
104 -  
105 - // 情况二,如果缓存里数据,则通过 updateTime 判断是否有数据变更,有变更则刷新缓存  
106 - LocalDateTime maxTime = CollectionUtils.getMaxValue(channelCache, PayChannelDO::getUpdateTime);  
107 - if (channelMapper.selectCountByUpdateTimeGt(maxTime) > 0) {  
108 - initLocalCache();  
109 - }  
110 - });  
111 - }  
112 -  
113 @Override 71 @Override
114 public Long createChannel(PayChannelCreateReqVO reqVO) { 72 public Long createChannel(PayChannelCreateReqVO reqVO) {
115 // 断言是否有重复的 73 // 断言是否有重复的
@@ -121,10 +79,7 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -121,10 +79,7 @@ public class PayChannelServiceImpl implements PayChannelService {
121 // 新增渠道 79 // 新增渠道
122 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO) 80 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO)
123 .setConfig(parseConfig(reqVO.getCode(), reqVO.getConfig())); 81 .setConfig(parseConfig(reqVO.getCode(), reqVO.getConfig()));
124 - channelMapper.insert(channel);  
125 -  
126 - // 刷新缓存  
127 - initLocalCache(); 82 + payChannelMapper.insert(channel);
128 return channel.getId(); 83 return channel.getId();
129 } 84 }
130 85
@@ -136,10 +91,10 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -136,10 +91,10 @@ public class PayChannelServiceImpl implements PayChannelService {
136 // 更新 91 // 更新
137 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO) 92 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO)
138 .setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig())); 93 .setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig()));
139 - channelMapper.updateById(channel); 94 + payChannelMapper.updateById(channel);
140 95
141 - // 刷新缓存  
142 - initLocalCache(); 96 + // 清空缓存
  97 + clearCache(channel.getId());
143 } 98 }
144 99
145 /** 100 /**
@@ -169,14 +124,23 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -169,14 +124,23 @@ public class PayChannelServiceImpl implements PayChannelService {
169 validateChannelExists(id); 124 validateChannelExists(id);
170 125
171 // 删除 126 // 删除
172 - channelMapper.deleteById(id); 127 + payChannelMapper.deleteById(id);
173 128
174 - // 刷新缓存  
175 - initLocalCache(); 129 + // 清空缓存
  130 + clearCache(id);
  131 + }
  132 +
  133 + /**
  134 + * 删除缓存
  135 + *
  136 + * @param id 渠道编号
  137 + */
  138 + private void clearCache(Long id) {
  139 + clientCache.invalidate(id);
176 } 140 }
177 141
178 private PayChannelDO validateChannelExists(Long id) { 142 private PayChannelDO validateChannelExists(Long id) {
179 - PayChannelDO channel = channelMapper.selectById(id); 143 + PayChannelDO channel = payChannelMapper.selectById(id);
180 if (channel == null) { 144 if (channel == null) {
181 throw exception(CHANNEL_NOT_FOUND); 145 throw exception(CHANNEL_NOT_FOUND);
182 } 146 }
@@ -185,29 +149,29 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -185,29 +149,29 @@ public class PayChannelServiceImpl implements PayChannelService {
185 149
186 @Override 150 @Override
187 public PayChannelDO getChannel(Long id) { 151 public PayChannelDO getChannel(Long id) {
188 - return channelMapper.selectById(id); 152 + return payChannelMapper.selectById(id);
189 } 153 }
190 154
191 @Override 155 @Override
192 public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) { 156 public List<PayChannelDO> getChannelListByAppIds(Collection<Long> appIds) {
193 - return channelMapper.selectListByAppIds(appIds); 157 + return payChannelMapper.selectListByAppIds(appIds);
194 } 158 }
195 159
196 @Override 160 @Override
197 public PayChannelDO getChannelByAppIdAndCode(Long appId, String code) { 161 public PayChannelDO getChannelByAppIdAndCode(Long appId, String code) {
198 - return channelMapper.selectByAppIdAndCode(appId, code); 162 + return payChannelMapper.selectByAppIdAndCode(appId, code);
199 } 163 }
200 164
201 @Override 165 @Override
202 public PayChannelDO validPayChannel(Long id) { 166 public PayChannelDO validPayChannel(Long id) {
203 - PayChannelDO channel = channelMapper.selectById(id); 167 + PayChannelDO channel = payChannelMapper.selectById(id);
204 validPayChannel(channel); 168 validPayChannel(channel);
205 return channel; 169 return channel;
206 } 170 }
207 171
208 @Override 172 @Override
209 public PayChannelDO validPayChannel(Long appId, String code) { 173 public PayChannelDO validPayChannel(Long appId, String code) {
210 - PayChannelDO channel = channelMapper.selectByAppIdAndCode(appId, code); 174 + PayChannelDO channel = payChannelMapper.selectByAppIdAndCode(appId, code);
211 validPayChannel(channel); 175 validPayChannel(channel);
212 return channel; 176 return channel;
213 } 177 }
@@ -223,7 +187,12 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -223,7 +187,12 @@ public class PayChannelServiceImpl implements PayChannelService {
223 187
224 @Override 188 @Override
225 public List<PayChannelDO> getEnableChannelList(Long appId) { 189 public List<PayChannelDO> getEnableChannelList(Long appId) {
226 - return channelMapper.selectListByAppId(appId, CommonStatusEnum.ENABLE.getStatus()); 190 + return payChannelMapper.selectListByAppId(appId, CommonStatusEnum.ENABLE.getStatus());
  191 + }
  192 +
  193 + @Override
  194 + public PayClient getPayClient(Long id) {
  195 + return clientCache.getUnchecked(id);
227 } 196 }
228 197
229 } 198 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 8 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
9 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 9 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
10 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 10 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
11 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; 11 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
13 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; 12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
14 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; 13 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
@@ -61,9 +60,6 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -61,9 +60,6 @@ public class PayOrderServiceImpl implements PayOrderService {
61 private PayProperties payProperties; 60 private PayProperties payProperties;
62 61
63 @Resource 62 @Resource
64 - private PayClientFactory payClientFactory;  
65 -  
66 - @Resource  
67 private PayOrderMapper orderMapper; 63 private PayOrderMapper orderMapper;
68 @Resource 64 @Resource
69 private PayOrderExtensionMapper orderExtensionMapper; 65 private PayOrderExtensionMapper orderExtensionMapper;
@@ -134,7 +130,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -134,7 +130,7 @@ public class PayOrderServiceImpl implements PayOrderService {
134 PayOrderDO order = validateOrderCanSubmit(reqVO.getId()); 130 PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
135 // 1.32 校验支付渠道是否有效 131 // 1.32 校验支付渠道是否有效
136 PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode()); 132 PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
137 - PayClient client = payClientFactory.getPayClient(channel.getId()); 133 + PayClient client = channelService.getPayClient(channel.getId());
138 134
139 // 2. 插入 PayOrderExtensionDO 135 // 2. 插入 PayOrderExtensionDO
140 String no = noRedisDAO.generate(payProperties.getOrderNoPrefix()); 136 String no = noRedisDAO.generate(payProperties.getOrderNoPrefix());
@@ -205,7 +201,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -205,7 +201,7 @@ public class PayOrderServiceImpl implements PayOrderService {
205 throw exception(PAY_ORDER_EXTENSION_IS_PAID); 201 throw exception(PAY_ORDER_EXTENSION_IS_PAID);
206 } 202 }
207 // 情况二:调用三方接口,查询支付单状态,是不是已支付 203 // 情况二:调用三方接口,查询支付单状态,是不是已支付
208 - PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); 204 + PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
209 if (payClient == null) { 205 if (payClient == null) {
210 log.error("[validateOrderCanSubmit][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId()); 206 log.error("[validateOrderCanSubmit][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
211 return; 207 return;
@@ -224,7 +220,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -224,7 +220,7 @@ public class PayOrderServiceImpl implements PayOrderService {
224 appService.validPayApp(appId); 220 appService.validPayApp(appId);
225 // 校验支付渠道是否有效 221 // 校验支付渠道是否有效
226 PayChannelDO channel = channelService.validPayChannel(appId, channelCode); 222 PayChannelDO channel = channelService.validPayChannel(appId, channelCode);
227 - PayClient client = payClientFactory.getPayClient(channel.getId()); 223 + PayClient client = channelService.getPayClient(channel.getId());
228 if (client == null) { 224 if (client == null) {
229 log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 225 log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
230 throw exception(CHANNEL_NOT_FOUND); 226 throw exception(CHANNEL_NOT_FOUND);
@@ -464,7 +460,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -464,7 +460,7 @@ public class PayOrderServiceImpl implements PayOrderService {
464 private boolean syncOrder(PayOrderExtensionDO orderExtension) { 460 private boolean syncOrder(PayOrderExtensionDO orderExtension) {
465 try { 461 try {
466 // 1.1 查询支付订单信息 462 // 1.1 查询支付订单信息
467 - PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); 463 + PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
468 if (payClient == null) { 464 if (payClient == null) {
469 log.error("[syncOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId()); 465 log.error("[syncOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
470 return false; 466 return false;
@@ -519,7 +515,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -519,7 +515,7 @@ public class PayOrderServiceImpl implements PayOrderService {
519 return false; 515 return false;
520 } 516 }
521 // 情况二:调用三方接口,查询支付单状态,是不是已支付/已退款 517 // 情况二:调用三方接口,查询支付单状态,是不是已支付/已退款
522 - PayClient payClient = payClientFactory.getPayClient(orderExtension.getChannelId()); 518 + PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
523 if (payClient == null) { 519 if (payClient == null) {
524 log.error("[expireOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId()); 520 log.error("[expireOrder][渠道编号({}) 找不到对应的支付客户端]", orderExtension.getChannelId());
525 return false; 521 return false;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.extra.spring.SpringUtil; 4 import cn.hutool.extra.spring.SpringUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
7 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
8 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
9 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
10 import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; 9 import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
@@ -53,9 +52,6 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -53,9 +52,6 @@ public class PayRefundServiceImpl implements PayRefundService {
53 private PayProperties payProperties; 52 private PayProperties payProperties;
54 53
55 @Resource 54 @Resource
56 - private PayClientFactory payClientFactory;  
57 -  
58 - @Resource  
59 private PayRefundMapper refundMapper; 55 private PayRefundMapper refundMapper;
60 @Resource 56 @Resource
61 private PayNoRedisDAO noRedisDAO; 57 private PayNoRedisDAO noRedisDAO;
@@ -102,7 +98,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -102,7 +98,7 @@ public class PayRefundServiceImpl implements PayRefundService {
102 PayOrderDO order = validatePayOrderCanRefund(reqDTO); 98 PayOrderDO order = validatePayOrderCanRefund(reqDTO);
103 // 1.3 校验支付渠道是否有效 99 // 1.3 校验支付渠道是否有效
104 PayChannelDO channel = channelService.validPayChannel(order.getChannelId()); 100 PayChannelDO channel = channelService.validPayChannel(order.getChannelId());
105 - PayClient client = payClientFactory.getPayClient(channel.getId()); 101 + PayClient client = channelService.getPayClient(channel.getId());
106 if (client == null) { 102 if (client == null) {
107 log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 103 log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
108 throw exception(CHANNEL_NOT_FOUND); 104 throw exception(CHANNEL_NOT_FOUND);
@@ -305,7 +301,7 @@ public class PayRefundServiceImpl implements PayRefundService { @@ -305,7 +301,7 @@ public class PayRefundServiceImpl implements PayRefundService {
305 private boolean syncRefund(PayRefundDO refund) { 301 private boolean syncRefund(PayRefundDO refund) {
306 try { 302 try {
307 // 1.1 查询退款订单信息 303 // 1.1 查询退款订单信息
308 - PayClient payClient = payClientFactory.getPayClient(refund.getChannelId()); 304 + PayClient payClient = channelService.getPayClient(refund.getChannelId());
309 if (payClient == null) { 305 if (payClient == null) {
310 log.error("[syncRefund][渠道编号({}) 找不到对应的支付客户端]", refund.getChannelId()); 306 log.error("[syncRefund][渠道编号({}) 找不到对应的支付客户端]", refund.getChannelId());
311 return false; 307 return false;
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.channel; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.channel;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  5 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
5 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
6 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; 7 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
7 import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig; 8 import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
@@ -12,30 +13,26 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR @@ -12,30 +13,26 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR
12 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
13 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; 14 import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
14 import com.alibaba.fastjson.JSON; 15 import com.alibaba.fastjson.JSON;
15 -import org.junit.jupiter.api.BeforeEach;  
16 import org.junit.jupiter.api.Test; 16 import org.junit.jupiter.api.Test;
17 import org.springframework.boot.test.mock.mockito.MockBean; 17 import org.springframework.boot.test.mock.mockito.MockBean;
18 import org.springframework.context.annotation.Import; 18 import org.springframework.context.annotation.Import;
19 19
20 import javax.annotation.Resource; 20 import javax.annotation.Resource;
21 import javax.validation.Validator; 21 import javax.validation.Validator;
22 -  
23 -import java.time.Duration;  
24 import java.util.Collections; 22 import java.util.Collections;
25 import java.util.List; 23 import java.util.List;
26 24
27 -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;  
28 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 25 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
29 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 26 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
30 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; 27 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
31 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 28 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
32 import static org.junit.jupiter.api.Assertions.*; 29 import static org.junit.jupiter.api.Assertions.*;
  30 +import static org.mockito.ArgumentMatchers.eq;
  31 +import static org.mockito.Mockito.*;
33 32
34 @Import({PayChannelServiceImpl.class}) 33 @Import({PayChannelServiceImpl.class})
35 public class PayChannelServiceTest extends BaseDbUnitTest { 34 public class PayChannelServiceTest extends BaseDbUnitTest {
36 35
37 - private static final String ALIPAY_SERVER_URL = "https://openapi.alipay.com/gateway.do";  
38 -  
39 @Resource 36 @Resource
40 private PayChannelServiceImpl channelService; 37 private PayChannelServiceImpl channelService;
41 38
@@ -47,45 +44,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -47,45 +44,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
47 @MockBean 44 @MockBean
48 private Validator validator; 45 private Validator validator;
49 46
50 - @BeforeEach  
51 - public void setUp() {  
52 - channelService.setChannelCache(null);  
53 - }  
54 -  
55 - @Test  
56 - public void testInitLocalCache() {  
57 - // mock 数据  
58 - PayChannelDO dbChannel = randomPojo(PayChannelDO.class,  
59 - o -> o.setConfig(randomWxPayClientConfig()));  
60 - channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据  
61 -  
62 - // 调用  
63 - channelService.initLocalCache();  
64 - // 校验缓存  
65 - assertEquals(1, channelService.getChannelCache().size());  
66 - assertEquals(dbChannel, channelService.getChannelCache().get(0));  
67 - }  
68 -  
69 - @Test  
70 - public void testRefreshLocalCache() {  
71 - // mock 数据 01  
72 - PayChannelDO dbChannel = randomPojo(PayChannelDO.class,  
73 - o -> o.setConfig(randomWxPayClientConfig()).setUpdateTime(addTime(Duration.ofMinutes(-2))));  
74 - channelMapper.insert(dbChannel);// @Sql: 先插入出一条存在的数据  
75 - channelService.initLocalCache();  
76 - // mock 数据 02  
77 - PayChannelDO dbChannel02 = randomPojo(PayChannelDO.class,  
78 - o -> o.setConfig(randomWxPayClientConfig()));  
79 - channelMapper.insert(dbChannel02);// @Sql: 先插入出一条存在的数据  
80 -  
81 - // 调用  
82 - channelService.refreshLocalCache();  
83 - // 校验缓存  
84 - assertEquals(2, channelService.getChannelCache().size());  
85 - assertEquals(dbChannel, channelService.getChannelCache().get(0));  
86 - assertEquals(dbChannel02, channelService.getChannelCache().get(1));  
87 - }  
88 -  
89 @Test 47 @Test
90 public void testCreateChannel_success() { 48 public void testCreateChannel_success() {
91 // 准备参数 49 // 准备参数
@@ -103,8 +61,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -103,8 +61,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
103 assertPojoEquals(reqVO, channel, "config"); 61 assertPojoEquals(reqVO, channel, "config");
104 assertPojoEquals(config, channel.getConfig()); 62 assertPojoEquals(config, channel.getConfig());
105 // 校验缓存 63 // 校验缓存
106 - assertEquals(1, channelService.getChannelCache().size());  
107 - assertEquals(channel, channelService.getChannelCache().get(0)); 64 + assertNull(channelService.getClientCache().getIfPresent(channelId));
108 } 65 }
109 66
110 @Test 67 @Test
@@ -146,8 +103,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -146,8 +103,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
146 assertPojoEquals(reqVO, channel, "config"); 103 assertPojoEquals(reqVO, channel, "config");
147 assertPojoEquals(config, channel.getConfig()); 104 assertPojoEquals(config, channel.getConfig());
148 // 校验缓存 105 // 校验缓存
149 - assertEquals(1, channelService.getChannelCache().size());  
150 - assertEquals(channel, channelService.getChannelCache().get(0)); 106 + assertNull(channelService.getClientCache().getIfPresent(channel.getId()));
151 } 107 }
152 108
153 @Test 109 @Test
@@ -179,7 +135,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -179,7 +135,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
179 // 校验数据不存在了 135 // 校验数据不存在了
180 assertNull(channelMapper.selectById(id)); 136 assertNull(channelMapper.selectById(id));
181 // 校验缓存 137 // 校验缓存
182 - assertEquals(0, channelService.getChannelCache().size()); 138 + assertNull(channelService.getClientCache().getIfPresent(id));
183 } 139 }
184 140
185 @Test 141 @Test
@@ -344,6 +300,28 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -344,6 +300,28 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
344 assertPojoEquals(channel, dbChannel03); 300 assertPojoEquals(channel, dbChannel03);
345 } 301 }
346 302
  303 + @Test
  304 + public void testGetPayClient() {
  305 + // mock 数据
  306 + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> {
  307 + o.setCode(PayChannelEnum.ALIPAY_APP.getCode());
  308 + o.setConfig(randomAlipayPayClientConfig());
  309 + });
  310 + channelMapper.insert(channel);
  311 + // mock 参数
  312 + Long id = channel.getId();
  313 + // mock 方法
  314 + PayClient mockClient = mock(PayClient.class);
  315 + when(payClientFactory.getPayClient(eq(id))).thenReturn(mockClient);
  316 +
  317 + // 调用
  318 + PayClient client = channelService.getPayClient(id);
  319 + // 断言
  320 + assertSame(client, mockClient);
  321 + verify(payClientFactory).createOrUpdatePayClient(eq(id), eq(channel.getCode()),
  322 + eq(channel.getConfig()));
  323 + }
  324 +
347 public WxPayClientConfig randomWxPayClientConfig() { 325 public WxPayClientConfig randomWxPayClientConfig() {
348 return new WxPayClientConfig() 326 return new WxPayClientConfig()
349 .setAppId(randomString()) 327 .setAppId(randomString())
yudao-module-report/yudao-module-report-api/src/main/java/cn/iocoder/yudao/module/report/enums/ErrorCodeConstants.java
@@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== AUTH 模块 1003000000 ==========  
13 - ErrorCode GO_VIEW_PROJECT_NOT_EXISTS = new ErrorCode(1003000000, "GoView 项目不存在"); 12 + // ========== AUTH 模块 1-003-000-000 ==========
  13 + ErrorCode GO_VIEW_PROJECT_NOT_EXISTS = new ErrorCode(1_003_000_000, "GoView 项目不存在");
14 14
15 } 15 }
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApi.java
1 package cn.iocoder.yudao.module.system.api.notify; 1 package cn.iocoder.yudao.module.system.api.notify;
2 2
3 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; 3 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
4 -import cn.iocoder.yudao.module.system.api.notify.dto.NotifyTemplateReqDTO;  
5 4
6 import javax.validation.Valid; 5 import javax.validation.Valid;
7 6
@@ -28,8 +27,4 @@ public interface NotifyMessageSendApi { @@ -28,8 +27,4 @@ public interface NotifyMessageSendApi {
28 */ 27 */
29 Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO); 28 Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO);
30 29
31 -  
32 - boolean validateNotifyTemplate(String orderDelivery);  
33 -  
34 - void createNotifyTemplate(NotifyTemplateReqDTO templateReqDTO);  
35 } 30 }
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -9,158 +9,158 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,158 +9,158 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
11 11
12 - // ========== AUTH 模块 1002000000 ==========  
13 - ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");  
14 - ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");  
15 - ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确,原因:{}");  
16 - ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");  
17 - ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");  
18 - ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1002000007, "手机号不存在");  
19 -  
20 - // ========== 菜单模块 1002001000 ==========  
21 - ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1002001000, "已经存在该名字的菜单");  
22 - ErrorCode MENU_PARENT_NOT_EXISTS = new ErrorCode(1002001001, "父菜单不存在");  
23 - ErrorCode MENU_PARENT_ERROR = new ErrorCode(1002001002, "不能设置自己为父菜单");  
24 - ErrorCode MENU_NOT_EXISTS = new ErrorCode(1002001003, "菜单不存在");  
25 - ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1002001004, "存在子菜单,无法删除");  
26 - ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1002001005, "父菜单的类型必须是目录或者菜单");  
27 -  
28 - // ========== 角色模块 1002002000 ==========  
29 - ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1002002000, "角色不存在");  
30 - ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1002002001, "已经存在名为【{}】的角色");  
31 - ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1002002002, "已经存在编码为【{}】的角色");  
32 - ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1002002003, "不能操作类型为系统内置的角色");  
33 - ErrorCode ROLE_IS_DISABLE = new ErrorCode(1002002004, "名字为【{}】的角色已被禁用");  
34 - ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1002002005, "编码【{}】不能使用");  
35 -  
36 - // ========== 用户模块 1002003000 ==========  
37 - ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1002003000, "用户账号已经存在");  
38 - ErrorCode USER_MOBILE_EXISTS = new ErrorCode(1002003001, "手机号已经存在");  
39 - ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1002003002, "邮箱已经存在");  
40 - ErrorCode USER_NOT_EXISTS = new ErrorCode(1002003003, "用户不存在");  
41 - ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002003004, "导入用户数据不能为空!");  
42 - ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1002003005, "用户密码校验失败");  
43 - ErrorCode USER_IS_DISABLE = new ErrorCode(1002003006, "名字为【{}】的用户已被禁用");  
44 - ErrorCode USER_COUNT_MAX = new ErrorCode(1002003008, "创建用户失败,原因:超过租户最大租户配额({})!");  
45 -  
46 - // ========== 部门模块 1002004000 ==========  
47 - ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1002004000, "已经存在该名字的部门");  
48 - ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1002004001,"父级部门不存在");  
49 - ErrorCode DEPT_NOT_FOUND = new ErrorCode(1002004002, "当前部门不存在");  
50 - ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1002004003, "存在子部门,无法删除");  
51 - ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1002004004, "不能设置自己为父部门");  
52 - ErrorCode DEPT_EXISTS_USER = new ErrorCode(1002004005, "部门中存在员工,无法删除");  
53 - ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1002004006, "部门({})不处于开启状态,不允许选择");  
54 - ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1002004007, "不能设置自己的子部门为父部门");  
55 -  
56 - // ========== 岗位模块 1002005000 ==========  
57 - ErrorCode POST_NOT_FOUND = new ErrorCode(1002005000, "当前岗位不存在");  
58 - ErrorCode POST_NOT_ENABLE = new ErrorCode(1002005001, "岗位({}) 不处于开启状态,不允许选择");  
59 - ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1002005002, "已经存在该名字的岗位");  
60 - ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1002005003, "已经存在该标识的岗位");  
61 -  
62 - // ========== 字典类型 1002006000 ==========  
63 - ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1002006001, "当前字典类型不存在");  
64 - ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1002006002, "字典类型不处于开启状态,不允许选择");  
65 - ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1002006003, "已经存在该名字的字典类型");  
66 - ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1002006004, "已经存在该类型的字典类型");  
67 - ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1002006005, "无法删除,该字典类型还有字典数据");  
68 -  
69 - // ========== 字典数据 1002007000 ==========  
70 - ErrorCode DICT_DATA_NOT_EXISTS = new ErrorCode(1002007001, "当前字典数据不存在");  
71 - ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1002007002, "字典数据({})不处于开启状态,不允许选择");  
72 - ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1002007003, "已经存在该值的字典数据");  
73 -  
74 - // ========== 通知公告 1002008000 ==========  
75 - ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1002008001, "当前通知公告不存在");  
76 -  
77 - // ========== 短信渠道 1002011000 ==========  
78 - ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1002011000, "短信渠道不存在");  
79 - ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1002011001, "短信渠道不处于开启状态,不允许选择");  
80 - ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1002011002, "无法删除,该短信渠道还有短信模板");  
81 -  
82 - // ========== 短信模板 1002012000 ==========  
83 - ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002012000, "短信模板不存在");  
84 - ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002012001, "已经存在编码为【{}】的短信模板");  
85 -  
86 - // ========== 短信发送 1002013000 ==========  
87 - ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1002013000, "手机号不存在");  
88 - ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1002013001, "模板参数({})缺失");  
89 - ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1002013002, "短信模板不存在");  
90 -  
91 - // ========== 短信验证码 1002014000 ==========  
92 - ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1002014000, "验证码不存在");  
93 - ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1002014001, "验证码已过期");  
94 - ErrorCode SMS_CODE_USED = new ErrorCode(1002014002, "验证码已使用");  
95 - ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1002014003, "验证码不正确");  
96 - ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1002014004, "超过每日短信发送数量");  
97 - ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1002014005, "短信发送过于频率");  
98 - ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1002014006, "手机号已被使用");  
99 - ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1002014007, "验证码未被使用");  
100 -  
101 - // ========== 租户信息 1002015000 ==========  
102 - ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002015000, "租户不存在");  
103 - ErrorCode TENANT_DISABLE = new ErrorCode(1002015001, "名字为【{}】的租户已被禁用");  
104 - ErrorCode TENANT_EXPIRE = new ErrorCode(1002015002, "名字为【{}】的租户已过期");  
105 - ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1002015003, "系统租户不能进行修改、删除等操作!");  
106 - ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1002015004, "名字为【{}】的租户已存在");  
107 -  
108 - // ========== 租户套餐 1002016000 ==========  
109 - ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1002016000, "租户套餐不存在");  
110 - ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1002016001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");  
111 - ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1002016002, "名字为【{}】的租户套餐已被禁用");  
112 -  
113 - // ========== 错误码模块 1002017000 ==========  
114 - ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002017000, "错误码不存在");  
115 - ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002017001, "已经存在编码为【{}】的错误码");  
116 -  
117 - // ========== 社交用户 1002018000 ==========  
118 - ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1002018000, "社交授权失败,原因是:{}");  
119 - ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002018001, "社交解绑失败,非当前用户绑定");  
120 - ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002018002, "社交授权失败,找不到对应的用户");  
121 -  
122 - // ========== 系统敏感词 1002019000 =========  
123 - ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");  
124 - ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");  
125 -  
126 - // ========== OAuth2 客户端 1002020000 =========  
127 - ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1002020000, "OAuth2 客户端不存在");  
128 - ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1002020001, "OAuth2 客户端编号已存在");  
129 - ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1002020002, "OAuth2 客户端已禁用");  
130 - ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1002020003, "不支持该授权类型");  
131 - ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1002020004, "授权范围过大");  
132 - ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1002020005, "无效 redirect_uri: {}");  
133 - ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1002020006, "无效 client_secret: {}");  
134 -  
135 - // ========== OAuth2 授权 1002021000 =========  
136 - ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1002021000, "client_id 不匹配");  
137 - ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1002021001, "redirect_uri 不匹配");  
138 - ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1002021002, "state 不匹配");  
139 - ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1002021003, "code 不存在");  
140 -  
141 - // ========== OAuth2 授权 1002022000 =========  
142 - ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在");  
143 - ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022001, "code 已过期");  
144 -  
145 - // ========== 邮箱账号 1002023000 ==========  
146 - ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1002023000, "邮箱账号不存在");  
147 - ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1002023001, "无法删除,该邮箱账号还有邮件模板");  
148 -  
149 - // ========== 邮件模版 1002024000 ==========  
150 - ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1002024000, "邮件模版不存在");  
151 - ErrorCode MAIL_TEMPLATE_CODE_EXISTS = new ErrorCode(1002024001, "邮件模版 code({}) 已存在");  
152 -  
153 - // ========== 邮件发送 1002025000 ==========  
154 - ErrorCode MAIL_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1002025000, "模板参数({})缺失");  
155 - ErrorCode MAIL_SEND_MAIL_NOT_EXISTS = new ErrorCode(1002025001, "邮箱不存在");  
156 -  
157 - // ========== 站内信模版 1002026000 ==========  
158 - ErrorCode NOTIFY_TEMPLATE_NOT_EXISTS = new ErrorCode(1002026000, "站内信模版不存在");  
159 - ErrorCode NOTIFY_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002026001, "已经存在编码为【{}】的站内信模板");  
160 -  
161 - // ========== 站内信模版 1002027000 ==========  
162 -  
163 - // ========== 站内信发送 1002028000 ==========  
164 - ErrorCode NOTIFY_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1002028000, "模板参数({})缺失"); 12 + // ========== AUTH 模块 1-002-000-000 ==========
  13 + ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_002_000_000, "登录失败,账号密码不正确");
  14 + ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用");
  15 + ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
  16 + ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
  17 + ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1_002_000_006, "Token 已经过期");
  18 + ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
  19 +
  20 + // ========== 菜单模块 1-002-001-000 ==========
  21 + ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单");
  22 + ErrorCode MENU_PARENT_NOT_EXISTS = new ErrorCode(1_002_001_001, "父菜单不存在");
  23 + ErrorCode MENU_PARENT_ERROR = new ErrorCode(1_002_001_002, "不能设置自己为父菜单");
  24 + ErrorCode MENU_NOT_EXISTS = new ErrorCode(1_002_001_003, "菜单不存在");
  25 + ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1_002_001_004, "存在子菜单,无法删除");
  26 + ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1_002_001_005, "父菜单的类型必须是目录或者菜单");
  27 +
  28 + // ========== 角色模块 1-002-002-000 ==========
  29 + ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1_002_002_000, "角色不存在");
  30 + ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1_002_002_001, "已经存在名为【{}】的角色");
  31 + ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1_002_002_002, "已经存在编码为【{}】的角色");
  32 + ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1_002_002_003, "不能操作类型为系统内置的角色");
  33 + ErrorCode ROLE_IS_DISABLE = new ErrorCode(1_002_002_004, "名字为【{}】的角色已被禁用");
  34 + ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "编码【{}】不能使用");
  35 +
  36 + // ========== 用户模块 1-002-003-000 ==========
  37 + ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_002_003_000, "用户账号已经存在");
  38 + ErrorCode USER_MOBILE_EXISTS = new ErrorCode(1_002_003_001, "手机号已经存在");
  39 + ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1_002_003_002, "邮箱已经存在");
  40 + ErrorCode USER_NOT_EXISTS = new ErrorCode(1_002_003_003, "用户不存在");
  41 + ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_003_004, "导入用户数据不能为空!");
  42 + ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败");
  43 + ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
  44 + ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
  45 +
  46 + // ========== 部门模块 1-002-004-000 ==========
  47 + ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
  48 + ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1_002_004_001,"父级部门不存在");
  49 + ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在");
  50 + ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");
  51 + ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门");
  52 + ErrorCode DEPT_EXISTS_USER = new ErrorCode(1_002_004_005, "部门中存在员工,无法删除");
  53 + ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择");
  54 + ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门");
  55 +
  56 + // ========== 岗位模块 1-002-005-000 ==========
  57 + ErrorCode POST_NOT_FOUND = new ErrorCode(1_002_005_000, "当前岗位不存在");
  58 + ErrorCode POST_NOT_ENABLE = new ErrorCode(1_002_005_001, "岗位({}) 不处于开启状态,不允许选择");
  59 + ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1_002_005_002, "已经存在该名字的岗位");
  60 + ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1_002_005_003, "已经存在该标识的岗位");
  61 +
  62 + // ========== 字典类型 1-002-006-000 ==========
  63 + ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1_002_006_001, "当前字典类型不存在");
  64 + ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1_002_006_002, "字典类型不处于开启状态,不允许选择");
  65 + ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1_002_006_003, "已经存在该名字的字典类型");
  66 + ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1_002_006_004, "已经存在该类型的字典类型");
  67 + ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1_002_006_005, "无法删除,该字典类型还有字典数据");
  68 +
  69 + // ========== 字典数据 1-002-007-000 ==========
  70 + ErrorCode DICT_DATA_NOT_EXISTS = new ErrorCode(1_002_007_001, "当前字典数据不存在");
  71 + ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1_002_007_002, "字典数据({})不处于开启状态,不允许选择");
  72 + ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1_002_007_003, "已经存在该值的字典数据");
  73 +
  74 + // ========== 通知公告 1-002-008-000 ==========
  75 + ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1_002_008_001, "当前通知公告不存在");
  76 +
  77 + // ========== 短信渠道 1-002-011-000 ==========
  78 + ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1_002_011_000, "短信渠道不存在");
  79 + ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1_002_011_001, "短信渠道不处于开启状态,不允许选择");
  80 + ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1_002_011_002, "无法删除,该短信渠道还有短信模板");
  81 +
  82 + // ========== 短信模板 1-002-012-000 ==========
  83 + ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在");
  84 + ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_012_001, "已经存在编码为【{}】的短信模板");
  85 +
  86 + // ========== 短信发送 1-002-013-000 ==========
  87 + ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在");
  88 + ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_013_001, "模板参数({})缺失");
  89 + ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_013_002, "短信模板不存在");
  90 +
  91 + // ========== 短信验证码 1-002-014-000 ==========
  92 + ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
  93 + ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
  94 + ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
  95 + ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确");
  96 + ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
  97 + ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率");
  98 + ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用");
  99 + ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用");
  100 +
  101 + // ========== 租户信息 1-002-015-000 ==========
  102 + ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
  103 + ErrorCode TENANT_DISABLE = new ErrorCode(1_002_015_001, "名字为【{}】的租户已被禁用");
  104 + ErrorCode TENANT_EXPIRE = new ErrorCode(1_002_015_002, "名字为【{}】的租户已过期");
  105 + ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1_002_015_003, "系统租户不能进行修改、删除等操作!");
  106 + ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1_002_015_004, "名字为【{}】的租户已存在");
  107 +
  108 + // ========== 租户套餐 1-002-016-000 ==========
  109 + ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在");
  110 + ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
  111 + ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用");
  112 +
  113 + // ========== 错误码模块 1-002-017-000 ==========
  114 + ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1_002_017_000, "错误码不存在");
  115 + ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1_002_017_001, "已经存在编码为【{}】的错误码");
  116 +
  117 + // ========== 社交用户 1-002-018-000 ==========
  118 + ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}");
  119 + ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1_002_018_001, "社交解绑失败,非当前用户绑定");
  120 + ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_002, "社交授权失败,找不到对应的用户");
  121 +
  122 + // ========== 系统敏感词 1-002-019-000 =========
  123 + ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1_002_019_000, "系统敏感词在所有标签中都不存在");
  124 + ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1_002_019_001, "系统敏感词已在标签中存在");
  125 +
  126 + // ========== OAuth2 客户端 1-002-020-000 =========
  127 + ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在");
  128 + ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 客户端编号已存在");
  129 + ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1_002_020_002, "OAuth2 客户端已禁用");
  130 + ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1_002_020_003, "不支持该授权类型");
  131 + ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1_002_020_004, "授权范围过大");
  132 + ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1_002_020_005, "无效 redirect_uri: {}");
  133 + ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1_002_020_006, "无效 client_secret: {}");
  134 +
  135 + // ========== OAuth2 授权 1-002-021-000 =========
  136 + ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1_002_021_000, "client_id 不匹配");
  137 + ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1_002_021_001, "redirect_uri 不匹配");
  138 + ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1_002_021_002, "state 不匹配");
  139 + ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1_002_021_003, "code 不存在");
  140 +
  141 + // ========== OAuth2 授权 1-002-022-000 =========
  142 + ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1_002_022_000, "code 不存在");
  143 + ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1_002_022_001, "code 已过期");
  144 +
  145 + // ========== 邮箱账号 1-002-023-000 ==========
  146 + ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1_002_023_000, "邮箱账号不存在");
  147 + ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1_002_023_001, "无法删除,该邮箱账号还有邮件模板");
  148 +
  149 + // ========== 邮件模版 1-002-024-000 ==========
  150 + ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_024_000, "邮件模版不存在");
  151 + ErrorCode MAIL_TEMPLATE_CODE_EXISTS = new ErrorCode(1_002_024_001, "邮件模版 code({}) 已存在");
  152 +
  153 + // ========== 邮件发送 1-002-025-000 ==========
  154 + ErrorCode MAIL_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_025_000, "模板参数({})缺失");
  155 + ErrorCode MAIL_SEND_MAIL_NOT_EXISTS = new ErrorCode(1_002_025_001, "邮箱不存在");
  156 +
  157 + // ========== 站内信模版 1-002-026-000 ==========
  158 + ErrorCode NOTIFY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_026_000, "站内信模版不存在");
  159 + ErrorCode NOTIFY_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_026_001, "已经存在编码为【{}】的站内信模板");
  160 +
  161 + // ========== 站内信模版 1-002-027-000 ==========
  162 +
  163 + // ========== 站内信发送 1-002-028-000 ==========
  164 + ErrorCode NOTIFY_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_028_000, "模板参数({})缺失");
165 165
166 } 166 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApiImpl.java
1 package cn.iocoder.yudao.module.system.api.notify; 1 package cn.iocoder.yudao.module.system.api.notify;
2 2
3 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; 3 import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
4 -import cn.iocoder.yudao.module.system.api.notify.dto.NotifyTemplateReqDTO;  
5 import cn.iocoder.yudao.module.system.service.notify.NotifySendService; 4 import cn.iocoder.yudao.module.system.service.notify.NotifySendService;
6 import org.springframework.stereotype.Service; 5 import org.springframework.stereotype.Service;
7 6
@@ -30,14 +29,4 @@ public class NotifyMessageSendApiImpl implements NotifyMessageSendApi { @@ -30,14 +29,4 @@ public class NotifyMessageSendApiImpl implements NotifyMessageSendApi {
30 reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); 29 reqDTO.getTemplateCode(), reqDTO.getTemplateParams());
31 } 30 }
32 31
33 - @Override  
34 - public boolean validateNotifyTemplate(String orderDelivery) {  
35 - return false;  
36 - }  
37 -  
38 - @Override  
39 - public void createNotifyTemplate(NotifyTemplateReqDTO templateReqDTO) {  
40 -  
41 - }  
42 -  
43 } 32 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
1 package cn.iocoder.yudao.module.system.controller.admin.auth; 1 package cn.iocoder.yudao.module.system.controller.admin.auth;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -153,4 +154,4 @@ public class AuthController { @@ -153,4 +154,4 @@ public class AuthController {
153 return success(authService.socialLogin(reqVO)); 154 return success(authService.socialLogin(reqVO));
154 } 155 }
155 156
156 -} 157 -}
  158 +}
157 \ No newline at end of file 159 \ No newline at end of file
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java
@@ -41,7 +41,7 @@ public class AuthLoginReqVO { @@ -41,7 +41,7 @@ public class AuthLoginReqVO {
41 41
42 // ========== 绑定社交登录时,需要传递如下参数 ========== 42 // ========== 绑定社交登录时,需要传递如下参数 ==========
43 43
44 - @Schema(description = "社交平台的类型,参见 SysUserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 44 + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
45 @InEnum(SocialTypeEnum.class) 45 @InEnum(SocialTypeEnum.class)
46 private Integer socialType; 46 private Integer socialType;
47 47
@@ -66,4 +66,4 @@ public class AuthLoginReqVO { @@ -66,4 +66,4 @@ public class AuthLoginReqVO {
66 return socialType == null || StrUtil.isNotEmpty(socialState); 66 return socialType == null || StrUtil.isNotEmpty(socialState);
67 } 67 }
68 68
69 -} 69 -}
  70 +}
70 \ No newline at end of file 71 \ No newline at end of file
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java
@@ -32,8 +32,8 @@ public interface SmsChannelConvert { @@ -32,8 +32,8 @@ public interface SmsChannelConvert {
32 32
33 PageResult<SmsChannelRespVO> convertPage(PageResult<SmsChannelDO> page); 33 PageResult<SmsChannelRespVO> convertPage(PageResult<SmsChannelDO> page);
34 34
35 - List<SmsChannelProperties> convertList02(List<SmsChannelDO> list);  
36 -  
37 List<SmsChannelSimpleRespVO> convertList03(List<SmsChannelDO> list); 35 List<SmsChannelSimpleRespVO> convertList03(List<SmsChannelDO> list);
38 36
  37 + SmsChannelProperties convert02(SmsChannelDO channel);
  38 +
39 } 39 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictDataDO.java
@@ -55,7 +55,7 @@ public class DictDataDO extends BaseDO { @@ -55,7 +55,7 @@ public class DictDataDO extends BaseDO {
55 /** 55 /**
56 * css 样式 56 * css 样式
57 */ 57 */
58 - @TableField(updateStrategy = FieldStrategy.IGNORED) 58 + @TableField(updateStrategy = FieldStrategy.ALWAYS)
59 private String cssClass; 59 private String cssClass;
60 /** 60 /**
61 * 备注 61 * 备注
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsChannelMapper.java
@@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; 6 import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
7 import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; 7 import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 -import org.apache.ibatis.annotations.Select;  
10 -  
11 -import java.time.LocalDateTime;  
12 9
13 @Mapper 10 @Mapper
14 public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> { 11 public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
@@ -21,7 +18,8 @@ public interface SmsChannelMapper extends BaseMapperX&lt;SmsChannelDO&gt; { @@ -21,7 +18,8 @@ public interface SmsChannelMapper extends BaseMapperX&lt;SmsChannelDO&gt; {
21 .orderByDesc(SmsChannelDO::getId)); 18 .orderByDesc(SmsChannelDO::getId));
22 } 19 }
23 20
24 - @Select("SELECT COUNT(*) FROM system_sms_channel WHERE update_time > #{maxUpdateTime}")  
25 - Long selectCountByUpdateTimeGt(LocalDateTime maxTime); 21 + default SmsChannelDO selectByCode(String code) {
  22 + return selectOne(SmsChannelDO::getCode, code);
  23 + }
26 24
27 } 25 }