Commit 597eacaaeba3fb1cd2bfcb27373dac992c39759f
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
# Conflicts: # yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
Showing
720 changed files
with
5807 additions
and
48819 deletions
Too many changes.
To preserve performance only 100 of 720 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) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [](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) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [](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) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [](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) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [](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) | [](https://gitee.com/yudaocode/yudao-ui-go-view) [](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | | 66 | | [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [](https://gitee.com/yudaocode/yudao-ui-go-view) [](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) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) [](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) | [](https://gitee.com/yudaocode/yudao-mall-uniapp) [](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 |  | 221 |  |
| 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 |
pom.xml
| @@ -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/brokerage.sql deleted
| 1 | --- 增加配置表 | ||
| 2 | -CREATE TABLE trade_config | ||
| 3 | -( | ||
| 4 | - id BIGINT AUTO_INCREMENT COMMENT '自增主键' PRIMARY KEY, | ||
| 5 | - brokerage_enabled BIT DEFAULT 1 NOT NULL COMMENT '是否启用分佣', | ||
| 6 | - brokerage_enabled_condition TINYINT DEFAULT 1 NOT NULL COMMENT '分佣模式:1-人人分销 2-指定分销', | ||
| 7 | - brokerage_bind_mode TINYINT DEFAULT 1 NOT NULL COMMENT '分销关系绑定模式: 1-没有推广人,2-新用户, 3-扫码覆盖', | ||
| 8 | - brokerage_poster_urls VARCHAR(2000) DEFAULT '' NULL COMMENT '分销海报图地址数组', | ||
| 9 | - brokerage_first_percent INT DEFAULT 0 NOT NULL COMMENT '一级返佣比例', | ||
| 10 | - brokerage_second_percent INT DEFAULT 0 NOT NULL COMMENT '二级返佣比例', | ||
| 11 | - brokerage_withdraw_min_price INT DEFAULT 0 NOT NULL COMMENT '用户提现最低金额', | ||
| 12 | - brokerage_withdraw_fee_percent INT DEFAULT 0 NOT NULL COMMENT '提现手续费百分比', | ||
| 13 | - brokerage_bank_names VARCHAR(200) DEFAULT '' NOT NULL COMMENT '提现银行(字典类型=brokerage_bank_name)', | ||
| 14 | - brokerage_frozen_days INT DEFAULT 7 NOT NULL COMMENT '佣金冻结时间(天)', | ||
| 15 | - brokerage_withdraw_types VARCHAR(32) DEFAULT '1,2,3,4' NOT NULL COMMENT '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝', | ||
| 16 | - creator VARCHAR(64) DEFAULT '' NULL COMMENT '创建者', | ||
| 17 | - create_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间', | ||
| 18 | - updater VARCHAR(64) DEFAULT '' NULL COMMENT '更新者', | ||
| 19 | - update_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 20 | - deleted BIT DEFAULT b'0' NOT NULL COMMENT '是否删除', | ||
| 21 | - tenant_id BIGINT DEFAULT 0 NOT NULL COMMENT '租户编号' | ||
| 22 | -) COMMENT '交易中心配置'; | ||
| 23 | - | ||
| 24 | -# alter table trade_config | ||
| 25 | -# add brokerage_withdraw_fee_percent int default 0 not null comment '提现手续费百分比' after brokerage_withdraw_min_price; | ||
| 26 | - | ||
| 27 | -# alter table trade_brokerage_user | ||
| 28 | -# add level int not null default 1 comment '等级' after frozen_price; | ||
| 29 | -# alter table trade_brokerage_user | ||
| 30 | -# add path varchar(2000) null comment '路径' after level; | ||
| 31 | - | ||
| 32 | - | ||
| 33 | --- 增加分销用户扩展表 | ||
| 34 | -create table trade_brokerage_user | ||
| 35 | -( | ||
| 36 | - id bigint auto_increment comment '用户编号' primary key, | ||
| 37 | - bind_user_id bigint null comment '推广员编号', | ||
| 38 | - bind_user_time datetime null comment '推广员绑定时间', | ||
| 39 | - brokerage_enabled bit default 1 not null comment '是否成为推广员', | ||
| 40 | - brokerage_time datetime null comment '成为分销员时间', | ||
| 41 | - price int default 0 not null comment '可用佣金', | ||
| 42 | - frozen_price int default 0 not null comment '冻结佣金', | ||
| 43 | - creator varchar(64) default '' null comment '创建者', | ||
| 44 | - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', | ||
| 45 | - updater varchar(64) default '' null comment '更新者', | ||
| 46 | - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', | ||
| 47 | - deleted bit default b'0' not null comment '是否删除', | ||
| 48 | - tenant_id bigint default 0 not null comment '租户编号' | ||
| 49 | -) | ||
| 50 | - comment '分销用户'; | ||
| 51 | - | ||
| 52 | -create index idx_invite_user_id on trade_brokerage_user (bind_user_id) comment '推广员编号'; | ||
| 53 | -create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是否成为推广员'; | ||
| 54 | - | ||
| 55 | - | ||
| 56 | -create table trade_brokerage_record | ||
| 57 | -( | ||
| 58 | - id int auto_increment comment '编号' | ||
| 59 | - primary key, | ||
| 60 | - user_id bigint not null comment '用户编号', | ||
| 61 | - biz_id varchar(64) default '' not null comment '业务编号', | ||
| 62 | - biz_type tinyint default 0 not null comment '业务类型:1-订单,2-提现', | ||
| 63 | - title varchar(64) default '' not null comment '标题', | ||
| 64 | - price int default 0 not null comment '金额', | ||
| 65 | - total_price int default 0 not null comment '当前总佣金', | ||
| 66 | - description varchar(500) default '' not null comment '说明', | ||
| 67 | - status tinyint default 0 not null comment '状态:0-待结算,1-已结算,2-已取消', | ||
| 68 | - frozen_days int default 0 not null comment '冻结时间(天)', | ||
| 69 | - unfreeze_time datetime null comment '解冻时间', | ||
| 70 | - source_user_level int not null comment '来源用户等级', | ||
| 71 | - source_user_id bigint not null comment '来源用户编号', | ||
| 72 | - creator varchar(64) default '' null comment '创建者', | ||
| 73 | - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', | ||
| 74 | - updater varchar(64) default '' null comment '更新者', | ||
| 75 | - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', | ||
| 76 | - deleted bit default b'0' not null comment '是否删除', | ||
| 77 | - tenant_id bigint default 0 not null comment '租户编号' | ||
| 78 | -) | ||
| 79 | - comment '佣金记录'; | ||
| 80 | - | ||
| 81 | -create index idx_user_id on trade_brokerage_record (user_id) comment '用户编号'; | ||
| 82 | -create index idx_biz on trade_brokerage_record (biz_type, biz_id) comment '业务'; | ||
| 83 | -create index idx_status on trade_brokerage_record (status) comment '状态'; | ||
| 84 | - | ||
| 85 | - | ||
| 86 | -create table trade_brokerage_withdraw | ||
| 87 | -( | ||
| 88 | - id bigint auto_increment comment '编号' | ||
| 89 | - primary key, | ||
| 90 | - user_id bigint not null comment '用户编号', | ||
| 91 | - price int default 0 not null comment '提现金额', | ||
| 92 | - fee_price int default 0 not null comment '提现手续费', | ||
| 93 | - total_price int default 0 not null comment '当前总佣金', | ||
| 94 | - type tinyint default 0 not null comment '提现类型:1-钱包;2-银行卡;3-微信;4-支付宝', | ||
| 95 | - name varchar(64) null comment '真实姓名', | ||
| 96 | - account_no varchar(64) null comment '账号', | ||
| 97 | - bank_name varchar(100) null comment '银行名称', | ||
| 98 | - bank_address varchar(200) null comment '开户地址', | ||
| 99 | - account_qr_code_url varchar(512) null comment '收款码', | ||
| 100 | - status tinyint(2) default 0 not null comment '状态:0-审核中,10-审核通过 20-审核不通过;预留:11 - 提现成功;21-提现失败', | ||
| 101 | - audit_reason varchar(128) null comment '审核驳回原因', | ||
| 102 | - audit_time datetime null comment '审核时间', | ||
| 103 | - remark varchar(500) null comment '备注', | ||
| 104 | - creator varchar(64) default '' null comment '创建者', | ||
| 105 | - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', | ||
| 106 | - updater varchar(64) default '' null comment '更新者', | ||
| 107 | - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', | ||
| 108 | - deleted bit default b'0' not null comment '是否删除', | ||
| 109 | - tenant_id bigint default 0 not null comment '租户编号' | ||
| 110 | -) | ||
| 111 | - comment '佣金提现'; | ||
| 112 | - | ||
| 113 | -create index idx_user_id on trade_brokerage_withdraw (user_id) comment '用户编号'; | ||
| 114 | -create index idx_audit_status on trade_brokerage_withdraw (status) comment '状态'; | ||
| 115 | - | ||
| 116 | --- 增加字典 | ||
| 117 | -insert into system_dict_type(type, name) | ||
| 118 | -values ('brokerage_enabled_condition', '分佣模式'); | ||
| 119 | -insert into system_dict_data(dict_type, label, value, sort, remark) | ||
| 120 | -values ('brokerage_enabled_condition', '人人分销', 1, 1, '所有用户都可以分销'), | ||
| 121 | - ('brokerage_enabled_condition', '指定分销', 2, 2, '仅可后台手动设置推广员'); | ||
| 122 | - | ||
| 123 | -insert into system_dict_type(type, name) | ||
| 124 | -values ('brokerage_bind_mode', '分销关系绑定模式'); | ||
| 125 | -insert into system_dict_data(dict_type, label, value, sort, remark) | ||
| 126 | -values ('brokerage_bind_mode', '没有推广人', 1, 1, '只要用户没有推广人,随时都可以绑定推广关系'), | ||
| 127 | - ('brokerage_bind_mode', '新用户', 2, 2, '仅新用户注册时才能绑定推广关系'), | ||
| 128 | - ('brokerage_bind_mode', '扫码覆盖', 3, 3, '如果用户已经有推广人,推广人会被变更'); | ||
| 129 | - | ||
| 130 | -insert into system_dict_type(type, name) | ||
| 131 | -values ('brokerage_withdraw_type', '佣金提现类型'); | ||
| 132 | -insert into system_dict_data(dict_type, label, value, sort) | ||
| 133 | -values ('brokerage_withdraw_type', '钱包', 1, 1), | ||
| 134 | - ('brokerage_withdraw_type', '银行卡', 2, 2), | ||
| 135 | - ('brokerage_withdraw_type', '微信', 3, 3), | ||
| 136 | - ('brokerage_withdraw_type', '支付宝', 4, 4); | ||
| 137 | - | ||
| 138 | -insert into system_dict_type(type, name) | ||
| 139 | -values ('brokerage_record_biz_type', '佣金记录业务类型'); | ||
| 140 | -insert into system_dict_data(dict_type, label, value, sort) | ||
| 141 | -values ('brokerage_record_biz_type', '订单返佣', 1, 1), | ||
| 142 | - ('brokerage_record_biz_type', '申请提现', 2, 2), | ||
| 143 | - ('brokerage_record_biz_type', '申请提现驳回', 3, 3); | ||
| 144 | - | ||
| 145 | -insert into system_dict_type(type, name) | ||
| 146 | -values ('brokerage_record_status', '佣金记录状态'); | ||
| 147 | -insert into system_dict_data(dict_type, label, value, sort) | ||
| 148 | -values ('brokerage_record_status', '待结算', 0, 0), | ||
| 149 | - ('brokerage_record_status', '已结算', 1, 1), | ||
| 150 | - ('brokerage_record_status', '已取消', 2, 2); | ||
| 151 | - | ||
| 152 | -insert into system_dict_type(type, name) | ||
| 153 | -values ('brokerage_withdraw_status', '佣金提现状态'); | ||
| 154 | -insert into system_dict_data(dict_type, label, value, sort, color_type) | ||
| 155 | -values ('brokerage_withdraw_status', '审核中', 0, 0, ''), | ||
| 156 | - ('brokerage_withdraw_status', '审核通过', 10, 10, 'success'), | ||
| 157 | - ('brokerage_withdraw_status', '提现成功', 11, 11, 'success'), | ||
| 158 | - ('brokerage_withdraw_status', '审核不通过', 20, 20, 'danger'), | ||
| 159 | - ('brokerage_withdraw_status', '提现失败', 21, 21, 'danger'); | ||
| 160 | - | ||
| 161 | -insert into system_dict_type(type, name) | ||
| 162 | -values ('brokerage_bank_name', '佣金提现银行'); | ||
| 163 | -insert into system_dict_data(dict_type, label, value, sort) | ||
| 164 | -values ('brokerage_bank_name', '工商银行', 0, 0), | ||
| 165 | - ('brokerage_bank_name', '建设银行', 1, 1), | ||
| 166 | - ('brokerage_bank_name', '农业银行', 2, 2), | ||
| 167 | - ('brokerage_bank_name', '中国银行', 3, 3), | ||
| 168 | - ('brokerage_bank_name', '交通银行', 4, 4), | ||
| 169 | - ('brokerage_bank_name', '招商银行', 5, 5); | ||
| 170 | - | ||
| 171 | - | ||
| 172 | --- 交易中心配置:菜单 SQL | ||
| 173 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) | ||
| 174 | -VALUES ('交易中心配置', '', 2, 0, 2072, 'config', 'ep:setting', 'trade/config/index', 0, 'TradeConfig'); | ||
| 175 | --- 按钮父菜单ID | ||
| 176 | --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 | ||
| 177 | -SELECT @parentId := LAST_INSERT_ID(); | ||
| 178 | --- 按钮 SQL | ||
| 179 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 180 | -VALUES ('交易中心配置查询', 'trade:config:query', 3, 1, @parentId, '', '', '', 0); | ||
| 181 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 182 | -VALUES ('交易中心配置保存', 'trade:config:save', 3, 2, @parentId, '', '', '', 0); | ||
| 183 | - | ||
| 184 | - | ||
| 185 | --- 增加菜单:分销 | ||
| 186 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) | ||
| 187 | -VALUES ('分销', '', 1, 5, 2072, 'brokerage', 'fa-solid:project-diagram', '', 0, ''); | ||
| 188 | --- 按钮父菜单ID | ||
| 189 | -SELECT @brokerageMenuId := LAST_INSERT_ID(); | ||
| 190 | - | ||
| 191 | --- 增加菜单:分销员 | ||
| 192 | --- 菜单 SQL | ||
| 193 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) | ||
| 194 | -VALUES ('分销用户', '', 2, 0, @brokerageMenuId, 'brokerage-user', 'fa-solid:user-tie', 'trade/brokerage/user/index', 0, | ||
| 195 | - 'TradeBrokerageUser'); | ||
| 196 | --- 按钮父菜单ID | ||
| 197 | --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 | ||
| 198 | -SELECT @parentId := LAST_INSERT_ID(); | ||
| 199 | --- 按钮 SQL | ||
| 200 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 201 | -VALUES ('分销用户查询', 'trade:brokerage-user:query', 3, 1, @parentId, '', '', '', 0); | ||
| 202 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 203 | -VALUES ('分销用户推广人查询', 'trade:brokerage-user:user-query', 3, 2, @parentId, '', '', '', 0); | ||
| 204 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 205 | -VALUES ('分销用户推广订单查询', 'trade:brokerage-user:order-query', 3, 3, @parentId, '', '', '', 0); | ||
| 206 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 207 | -VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0); | ||
| 208 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 209 | -VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-bind-user', 3, 5, @parentId, '', '', '', 0); | ||
| 210 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 211 | -VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-bind-user', 3, 6, @parentId, '', '', '', 0); | ||
| 212 | - | ||
| 213 | --- 增加菜单:佣金记录 | ||
| 214 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) | ||
| 215 | -VALUES ('佣金记录', '', 2, 1, @brokerageMenuId, 'brokerage-record', 'fa:money', 'trade/brokerage/record/index', 0, | ||
| 216 | - 'TradeBrokerageRecord'); | ||
| 217 | --- 按钮父菜单ID | ||
| 218 | --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 | ||
| 219 | -SELECT @parentId := LAST_INSERT_ID(); | ||
| 220 | --- 按钮 SQL | ||
| 221 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 222 | -VALUES ('佣金记录查询', 'trade:brokerage-record:query', 3, 1, @parentId, '', '', '', 0); | ||
| 223 | - | ||
| 224 | --- 增加菜单:佣金提现 | ||
| 225 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) | ||
| 226 | -VALUES ('佣金提现', '', 2, 2, @brokerageMenuId, 'brokerage-withdraw', 'fa:credit-card', | ||
| 227 | - 'trade/brokerage/withdraw/index', 0, 'TradeBrokerageWithdraw'); | ||
| 228 | --- 按钮父菜单ID | ||
| 229 | --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 | ||
| 230 | -SELECT @parentId := LAST_INSERT_ID(); | ||
| 231 | --- 按钮 SQL | ||
| 232 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 233 | -VALUES ('佣金提现查询', 'trade:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0); | ||
| 234 | -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 235 | -VALUES ('佣金提现审核', 'trade:brokerage-withdraw:audit', 3, 2, @parentId, '', '', '', 0); | ||
| 236 | - | ||
| 237 | --- 站内信模板 | ||
| 238 | -INSERT INTO `ruoyi-vue-pro`.system_notify_template (name, code, nickname, content, type, params, status) | ||
| 239 | -VALUES | ||
| 240 | - ('佣金提现(审核通过)', 'brokerage_withdraw_audit_approve', 'system', '您在{createTime}提现¥{price}元的申请已通过审核', 2, '["createTime","price"]', 0), | ||
| 241 | - ('佣金提现(审核不通过)', 'brokerage_withdraw_audit_reject', 'system', '您在{createTime}提现¥{price}元的申请未通过审核,原因:{reason}', 2, '["createTime","price","reason"]', 0); |
sql/mysql/optional/mall_trade_log.sql deleted
sql/mysql/pay_wallet.sql
| @@ -73,3 +73,81 @@ CREATE TABLE `pay_wallet_recharge` | @@ -73,3 +73,81 @@ CREATE TABLE `pay_wallet_recharge` | ||
| 73 | PRIMARY KEY (`id`) USING BTREE | 73 | PRIMARY KEY (`id`) USING BTREE |
| 74 | ) ENGINE=InnoDB COMMENT='会员钱包充值'; | 74 | ) ENGINE=InnoDB COMMENT='会员钱包充值'; |
| 75 | 75 | ||
| 76 | +-- ---------------------------- | ||
| 77 | +-- 转账单表 | ||
| 78 | +-- ---------------------------- | ||
| 79 | +DROP TABLE IF EXISTS `pay_transfer`; | ||
| 80 | +CREATE TABLE `pay_transfer` | ||
| 81 | +( | ||
| 82 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | ||
| 83 | + `type` int NOT NULL COMMENT '类型', | ||
| 84 | + `app_id` bigint NOT NULL COMMENT '应用编号', | ||
| 85 | + `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号', | ||
| 86 | + `price` int NOT NULL COMMENT '转账金额,单位:分', | ||
| 87 | + `title` varchar(512) NOT NULL COMMENT '转账标题', | ||
| 88 | + `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同', | ||
| 89 | + `status` tinyint NOT NULL COMMENT '转账状态', | ||
| 90 | + `success_time` datetime NULL COMMENT '转账成功时间', | ||
| 91 | + `extension_id` bigint NULL COMMENT '转账渠道编号', | ||
| 92 | + `no` varchar(64) NULL COMMENT '转账单号', | ||
| 93 | + `channel_id` bigint NULL COMMENT '转账渠道编号', | ||
| 94 | + `channel_code` varchar(32) NULL COMMENT '转账渠道编码', | ||
| 95 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | ||
| 96 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 97 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | ||
| 98 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 99 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||
| 100 | + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | ||
| 101 | + PRIMARY KEY (`id`) USING BTREE | ||
| 102 | +) ENGINE=InnoDB COMMENT='转账单表'; | ||
| 103 | + | ||
| 104 | +-- ---------------------------- | ||
| 105 | +-- 转账扩展单 | ||
| 106 | +-- ---------------------------- | ||
| 107 | +DROP TABLE IF EXISTS `pay_transfer_extension`; | ||
| 108 | +CREATE TABLE `pay_transfer_extension` | ||
| 109 | +( | ||
| 110 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | ||
| 111 | + `no` varchar(64) NOT NULL COMMENT '转账单号', | ||
| 112 | + `transfer_id` bigint NOT NULL COMMENT '转账单编号', | ||
| 113 | + `channel_id` bigint NOT NULL COMMENT '转账渠道编号', | ||
| 114 | + `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码', | ||
| 115 | + `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '支付渠道的额外参数', | ||
| 116 | + `status` tinyint NOT NULL COMMENT '转账状态', | ||
| 117 | + `channel_notify_data` varchar(4096) NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容', | ||
| 118 | + `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者', | ||
| 119 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 120 | + `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者', | ||
| 121 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 122 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||
| 123 | + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | ||
| 124 | + PRIMARY KEY (`id`) USING BTREE | ||
| 125 | +) ENGINE=InnoDB COMMENT='转账拓展单表'; | ||
| 126 | + | ||
| 127 | +-- ---------------------------- | ||
| 128 | +-- Table structure for pay_demo_transfer | ||
| 129 | +-- ---------------------------- | ||
| 130 | +DROP TABLE IF EXISTS `pay_demo_transfer`; | ||
| 131 | +CREATE TABLE `pay_demo_transfer` ( | ||
| 132 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号', | ||
| 133 | + `user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号', | ||
| 134 | + `price` int NOT NULL COMMENT '转账金额,单位:分', | ||
| 135 | + `type` int NOT NULL COMMENT '转账类型', | ||
| 136 | + `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同', | ||
| 137 | + `transfer_status` tinyint NOT NULL DEFAULT 0 COMMENT '转账状态', | ||
| 138 | + `pay_transfer_id` bigint NULL DEFAULT NULL COMMENT '转账订单编号', | ||
| 139 | + `pay_channel_code` varchar(16) NULL DEFAULT NULL COMMENT '转账支付成功渠道', | ||
| 140 | + `transfer_time` datetime NULL DEFAULT NULL COMMENT '转账支付时间', | ||
| 141 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '创建者', | ||
| 142 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 143 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '更新者', | ||
| 144 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 145 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||
| 146 | + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | ||
| 147 | + PRIMARY KEY (`id`) USING BTREE | ||
| 148 | +) ENGINE = InnoDB COMMENT = '示例业务转账订单\n'; | ||
| 149 | + | ||
| 150 | + | ||
| 151 | +ALTER TABLE `pay_channel` | ||
| 152 | + MODIFY COLUMN `config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置' AFTER `app_id`; | ||
| 153 | + |
sql/mysql/point.sql deleted
| 1 | -ALTER TABLE trade_order ADD COLUMN use_point int NOT NULL DEFAULT 0 COMMENT '使用的积分' AFTER point_price; | ||
| 2 | -ALTER TABLE trade_order ADD COLUMN refund_point int NOT NULL DEFAULT 0 COMMENT '退还的使用积分' AFTER use_point; | ||
| 3 | -ALTER TABLE trade_order ADD COLUMN give_point int NOT NULL DEFAULT 0 COMMENT '赠送的积分' AFTER refund_point; | ||
| 4 | - | ||
| 5 | -ALTER TABLE trade_order_item ADD COLUMN use_point int NOT NULL DEFAULT 0 COMMENT '使用的积分' AFTER point_price; | ||
| 6 | -ALTER TABLE trade_order_item ADD COLUMN give_point int NOT NULL DEFAULT 0 COMMENT '赠送的积分' AFTER use_point; |
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 |
| @@ -1188,8 +1197,8 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st | @@ -1188,8 +1197,8 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st | ||
| 1188 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1166, 2, '折扣', '2', 'promotion_discount_type', 0, 'primary', '', '优惠类型 - 折扣', '1', '2022-11-01 12:46:51', '1', '2022-11-01 12:50:08', b'0'); | 1197 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1166, 2, '折扣', '2', 'promotion_discount_type', 0, 'primary', '', '优惠类型 - 折扣', '1', '2022-11-01 12:46:51', '1', '2022-11-01 12:50:08', b'0'); |
| 1189 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1167, 1, '固定日期', '1', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 固定日期', '1', '2022-11-02 00:07:34', '1', '2022-11-04 00:07:49', b'0'); | 1198 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1167, 1, '固定日期', '1', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 固定日期', '1', '2022-11-02 00:07:34', '1', '2022-11-04 00:07:49', b'0'); |
| 1190 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1168, 2, '领取之后', '2', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 领取之后', '1', '2022-11-02 00:07:54', '1', '2022-11-04 00:07:52', b'0'); | 1199 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1168, 2, '领取之后', '2', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 领取之后', '1', '2022-11-02 00:07:54', '1', '2022-11-04 00:07:52', b'0'); |
| 1191 | -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1169, 1, '通用卷', '1', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 全部商品参与', '1', '2022-11-02 00:28:22', '1', '2023-09-01 23:42:49', b'0'); | ||
| 1192 | -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1170, 2, '商品卷', '2', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 指定商品参与', '1', '2022-11-02 00:28:34', '1', '2023-09-01 23:42:54', b'0'); | 1200 | +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1169, 1, '通用券', '1', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 全部商品参与', '1', '2022-11-02 00:28:22', '1', '2023-09-01 23:42:49', b'0'); |
| 1201 | +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1170, 2, '商品券', '2', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 指定商品参与', '1', '2022-11-02 00:28:34', '1', '2023-09-01 23:42:54', b'0'); | ||
| 1193 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1171, 1, '已领取', '1', 'promotion_coupon_status', 0, 'primary', '', '优惠劵的状态 - 已领取', '1', '2022-11-04 00:15:08', '1', '2022-11-04 19:16:04', b'0'); | 1202 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1171, 1, '已领取', '1', 'promotion_coupon_status', 0, 'primary', '', '优惠劵的状态 - 已领取', '1', '2022-11-04 00:15:08', '1', '2022-11-04 19:16:04', b'0'); |
| 1194 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1172, 2, '已使用', '2', 'promotion_coupon_status', 0, 'success', '', '优惠劵的状态 - 已使用', '1', '2022-11-04 00:15:21', '1', '2022-11-04 19:16:08', b'0'); | 1203 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1172, 2, '已使用', '2', 'promotion_coupon_status', 0, 'success', '', '优惠劵的状态 - 已使用', '1', '2022-11-04 00:15:21', '1', '2022-11-04 19:16:08', b'0'); |
| 1195 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1173, 3, '已过期', '3', 'promotion_coupon_status', 0, 'info', '', '优惠劵的状态 - 已过期', '1', '2022-11-04 00:15:43', '1', '2022-11-04 19:16:12', b'0'); | 1204 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1173, 3, '已过期', '3', 'promotion_coupon_status', 0, 'info', '', '优惠劵的状态 - 已过期', '1', '2022-11-04 00:15:43', '1', '2022-11-04 19:16:12', b'0'); |
| @@ -1284,7 +1293,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st | @@ -1284,7 +1293,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st | ||
| 1284 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1355, 5, '抽奖奖励', '5', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', b'0'); | 1293 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1355, 5, '抽奖奖励', '5', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', b'0'); |
| 1285 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1356, 1, '快递发货', '1', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:04:55', '1', '2023-08-23 00:04:55', b'0'); | 1294 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1356, 1, '快递发货', '1', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:04:55', '1', '2023-08-23 00:04:55', b'0'); |
| 1286 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1357, 2, '用户自提', '2', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:05:05', '1', '2023-08-23 00:05:05', b'0'); | 1295 | INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1357, 2, '用户自提', '2', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:05:05', '1', '2023-08-23 00:05:05', b'0'); |
| 1287 | -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1358, 3, '品类卷', '3', 'promotion_product_scope', 0, 'default', '', '', '1', '2023-09-01 23:43:07', '1', '2023-09-01 23:43:07', b'0'); | 1296 | +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1358, 3, '品类券', '3', 'promotion_product_scope', 0, 'default', '', '', '1', '2023-09-01 23:43:07', '1', '2023-09-01 23:43:07', b'0'); |
| 1288 | COMMIT; | 1297 | COMMIT; |
| 1289 | 1298 | ||
| 1290 | -- ---------------------------- | 1299 | -- ---------------------------- |
| @@ -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/mysql/statistics.sql
0 → 100644
| 1 | +-- 交易统计表 | ||
| 2 | +CREATE TABLE trade_statistics | ||
| 3 | +( | ||
| 4 | + id bigint AUTO_INCREMENT COMMENT '编号,主键自增' | ||
| 5 | + PRIMARY KEY, | ||
| 6 | + time datetime NOT NULL COMMENT '统计日期', | ||
| 7 | + order_create_count int DEFAULT 0 NOT NULL COMMENT '创建订单数', | ||
| 8 | + order_pay_count int DEFAULT 0 NOT NULL COMMENT '支付订单商品数', | ||
| 9 | + order_pay_price int DEFAULT 0 NOT NULL COMMENT '总支付金额,单位:分', | ||
| 10 | + order_wallet_pay_price int DEFAULT 0 NOT NULL COMMENT '总支付金额(余额),单位:分', | ||
| 11 | + after_sale_count int DEFAULT 0 NOT NULL COMMENT '退款订单数', | ||
| 12 | + after_sale_refund_price int DEFAULT 0 NOT NULL COMMENT '总退款金额,单位:分', | ||
| 13 | + brokerage_settlement_price int DEFAULT 0 NOT NULL COMMENT '佣金金额(已结算),单位:分', | ||
| 14 | + recharge_pay_count int DEFAULT 0 NOT NULL COMMENT '充值订单数', | ||
| 15 | + recharge_pay_price int DEFAULT 0 NOT NULL COMMENT '充值金额,单位:分', | ||
| 16 | + recharge_refund_count int DEFAULT 0 NOT NULL COMMENT '充值退款订单数', | ||
| 17 | + recharge_refund_price int DEFAULT 0 NOT NULL COMMENT '充值退款金额,单位:分', | ||
| 18 | + creator varchar(64) DEFAULT '' NULL COMMENT '创建者', | ||
| 19 | + create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间', | ||
| 20 | + updater varchar(64) DEFAULT '' NULL COMMENT '更新者', | ||
| 21 | + update_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 22 | + deleted bit DEFAULT b'0' NOT NULL COMMENT '是否删除', | ||
| 23 | + tenant_id bigint DEFAULT 0 NOT NULL COMMENT '租户编号' | ||
| 24 | +) | ||
| 25 | + COMMENT '交易统计表'; | ||
| 26 | + | ||
| 27 | +CREATE INDEX trade_statistics_time_index | ||
| 28 | + ON trade_statistics (time); | ||
| 29 | + | ||
| 30 | +-- 菜单 | ||
| 31 | +INSERT INTO `ruoyi-vue-pro`.system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) | ||
| 32 | +VALUES ('统计管理', '', 1, 4, 0, '/statistics', 'ep:data-line', '', ''); | ||
| 33 | +SELECT @parentId := LAST_INSERT_ID(); | ||
| 34 | +INSERT INTO `ruoyi-vue-pro`.system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) | ||
| 35 | +VALUES ('交易统计', '', 2, 4, @parentId, 'trade', 'fa-solid:credit-card', 'statistics/trade/index', 'TradeStatistics'); | ||
| 36 | +SELECT @parentId := LAST_INSERT_ID(); | ||
| 37 | +-- 按钮 | ||
| 38 | +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 39 | +VALUES ('交易统计查询', 'statistics:trade:query', 3, 1, @parentId, '', '', '', 0); | ||
| 40 | +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 41 | +VALUES ('交易统计导出', 'statistics:trade:export', 3, 2, @parentId, '', '', '', 0); | ||
| 42 | + | ||
| 43 | + |
sql/sqlserver/ruoyi-vue-pro.sql
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/date/LocalDateTimeUtils.java
| @@ -23,6 +23,10 @@ public class LocalDateTimeUtils { | @@ -23,6 +23,10 @@ public class LocalDateTimeUtils { | ||
| 23 | return LocalDateTime.now().plus(duration); | 23 | return LocalDateTime.now().plus(duration); |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | + public static LocalDateTime minusTime(Duration duration) { | ||
| 27 | + return LocalDateTime.now().minus(duration); | ||
| 28 | + } | ||
| 29 | + | ||
| 26 | public static boolean beforeNow(LocalDateTime date) { | 30 | public static boolean beforeNow(LocalDateTime date) { |
| 27 | return date.isBefore(LocalDateTime.now()); | 31 | return date.isBefore(LocalDateTime.now()); |
| 28 | } | 32 | } |
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/dto/transfer/PayTransferRespDTO.java
| @@ -64,12 +64,12 @@ public class PayTransferRespDTO { | @@ -64,12 +64,12 @@ public class PayTransferRespDTO { | ||
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | /** | 66 | /** |
| 67 | - * 创建【FAILURE】状态的转账返回 | 67 | + * 创建【CLOSED】状态的转账返回 |
| 68 | */ | 68 | */ |
| 69 | - public static PayTransferRespDTO failureOf(String channelErrorCode, String channelErrorMsg, | ||
| 70 | - String outTransferNo, Object rawData) { | 69 | + public static PayTransferRespDTO closedOf(String channelErrorCode, String channelErrorMsg, |
| 70 | + String outTransferNo, Object rawData) { | ||
| 71 | PayTransferRespDTO respDTO = new PayTransferRespDTO(); | 71 | PayTransferRespDTO respDTO = new PayTransferRespDTO(); |
| 72 | - respDTO.status = PayTransferStatusRespEnum.FAILURE.getStatus(); | 72 | + respDTO.status = PayTransferStatusRespEnum.CLOSED.getStatus(); |
| 73 | respDTO.channelErrorCode = channelErrorCode; | 73 | respDTO.channelErrorCode = channelErrorCode; |
| 74 | respDTO.channelErrorMsg = channelErrorMsg; | 74 | respDTO.channelErrorMsg = channelErrorMsg; |
| 75 | // 相对通用的字段 | 75 | // 相对通用的字段 |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java
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<Config extends PayClientConfig> implemen | @@ -50,7 +50,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> 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-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayTransferClient.java
| @@ -51,7 +51,7 @@ public class AlipayTransferClient extends AbstractAlipayPayClient { | @@ -51,7 +51,7 @@ public class AlipayTransferClient extends AbstractAlipayPayClient { | ||
| 51 | model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD | 51 | model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD |
| 52 | model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER。 | 52 | model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER。 |
| 53 | model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras())); | 53 | model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras())); |
| 54 | - PayTransferTypeEnum transferType = PayTransferTypeEnum.valueOf(reqDTO.getType()); | 54 | + PayTransferTypeEnum transferType = PayTransferTypeEnum.ofType(reqDTO.getType()); |
| 55 | switch(transferType){ | 55 | switch(transferType){ |
| 56 | case WX_BALANCE : | 56 | case WX_BALANCE : |
| 57 | case WALLET_BALANCE : { | 57 | case WALLET_BALANCE : { |
| @@ -84,7 +84,7 @@ public class AlipayTransferClient extends AbstractAlipayPayClient { | @@ -84,7 +84,7 @@ public class AlipayTransferClient extends AbstractAlipayPayClient { | ||
| 84 | if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) { | 84 | if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) { |
| 85 | return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response); | 85 | return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response); |
| 86 | } | 86 | } |
| 87 | - return PayTransferRespDTO.failureOf(response.getSubCode(), response.getSubMsg(), | 87 | + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(), |
| 88 | reqDTO.getOutTransferNo(), response); | 88 | reqDTO.getOutTransferNo(), response); |
| 89 | } | 89 | } |
| 90 | return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()), | 90 | return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()), |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferStatusRespEnum.java
| @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.pay.core.enums.transfer; | @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.pay.core.enums.transfer; | ||
| 3 | import lombok.AllArgsConstructor; | 3 | import lombok.AllArgsConstructor; |
| 4 | import lombok.Getter; | 4 | import lombok.Getter; |
| 5 | 5 | ||
| 6 | +import java.util.Objects; | ||
| 7 | + | ||
| 6 | /** | 8 | /** |
| 7 | * 渠道的转账状态枚举 | 9 | * 渠道的转账状态枚举 |
| 8 | * | 10 | * |
| @@ -12,10 +14,28 @@ import lombok.Getter; | @@ -12,10 +14,28 @@ import lombok.Getter; | ||
| 12 | @AllArgsConstructor | 14 | @AllArgsConstructor |
| 13 | public enum PayTransferStatusRespEnum { | 15 | public enum PayTransferStatusRespEnum { |
| 14 | 16 | ||
| 15 | - WAITING(0, "等待转账"), | ||
| 16 | - SUCCESS(10, "转账成功"), | ||
| 17 | - FAILURE(20, "转账失败"); | 17 | + WAITING(0, "转账中"), |
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * TODO 转账到银行卡. 会有T+0 T+1 到账的请情况。 还未实现 | ||
| 21 | + */ | ||
| 22 | + IN_PROGRESS(10, "转账进行中"), | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + SUCCESS(20, "转账成功"), | ||
| 26 | + /** | ||
| 27 | + * 转账关闭 (失败,或者其它情况) | ||
| 28 | + */ | ||
| 29 | + CLOSED(30, "转账关闭"); | ||
| 18 | 30 | ||
| 19 | private final Integer status; | 31 | private final Integer status; |
| 20 | private final String name; | 32 | private final String name; |
| 33 | + | ||
| 34 | + public static boolean isSuccess(Integer status) { | ||
| 35 | + return Objects.equals(status, SUCCESS.getStatus()); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public static boolean isClosed(Integer status) { | ||
| 39 | + return Objects.equals(status, CLOSED.getStatus()); | ||
| 40 | + } | ||
| 21 | } | 41 | } |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferTypeEnum.java
| @@ -20,6 +20,9 @@ public enum PayTransferTypeEnum implements IntArrayValuable { | @@ -20,6 +20,9 @@ public enum PayTransferTypeEnum implements IntArrayValuable { | ||
| 20 | BANK_CARD(3, "银行卡"), | 20 | BANK_CARD(3, "银行卡"), |
| 21 | WALLET_BALANCE(4, "钱包余额"); | 21 | WALLET_BALANCE(4, "钱包余额"); |
| 22 | 22 | ||
| 23 | + public static final String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID"; | ||
| 24 | + public static final String ALIPAY_ACCOUNT_NAME = "ALIPAY_ACCOUNT_NAME"; | ||
| 25 | + | ||
| 23 | private final Integer type; | 26 | private final Integer type; |
| 24 | private final String name; | 27 | private final String name; |
| 25 | 28 | ||
| @@ -30,7 +33,7 @@ public enum PayTransferTypeEnum implements IntArrayValuable { | @@ -30,7 +33,7 @@ public enum PayTransferTypeEnum implements IntArrayValuable { | ||
| 30 | return ARRAYS; | 33 | return ARRAYS; |
| 31 | } | 34 | } |
| 32 | 35 | ||
| 33 | - public static PayTransferTypeEnum valueOf(Integer type) { | 36 | + public static PayTransferTypeEnum ofType(Integer type) { |
| 34 | return ArrayUtil.firstMatch(item -> item.getType().equals(type), values()); | 37 | return ArrayUtil.firstMatch(item -> item.getType().equals(type), values()); |
| 35 | } | 38 | } |
| 36 | } | 39 | } |
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-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java
| @@ -11,40 +11,40 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | @@ -11,40 +11,40 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 11 | */ | 11 | */ |
| 12 | public interface SmsFrameworkErrorCodeConstants { | 12 | public interface SmsFrameworkErrorCodeConstants { |
| 13 | 13 | ||
| 14 | - ErrorCode SMS_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析"); | 14 | + ErrorCode SMS_UNKNOWN = new ErrorCode(2_001_000_000, "未知错误,需要解析"); |
| 15 | 15 | ||
| 16 | - // ========== 权限 / 限流等相关 2001000100 ========== | 16 | + // ========== 权限 / 限流等相关 2-001-000-100 ========== |
| 17 | 17 | ||
| 18 | - ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); | ||
| 19 | - ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); | 18 | + ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2_001_000_100, "没有发送短信的权限"); |
| 19 | + ErrorCode SMS_IP_DENY = new ErrorCode(2_001_000_100, "IP 不允许发送短信"); | ||
| 20 | 20 | ||
| 21 | // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 | 21 | // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 |
| 22 | - ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流"); | 22 | + ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2_001_000_102, "指定手机的发送限流"); |
| 23 | // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 | 23 | // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 |
| 24 | - ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流"); | 24 | + ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2_001_000_103, "每天的发送限流"); |
| 25 | 25 | ||
| 26 | - ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词"); | 26 | + ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2_001_000_104, "短信内容有敏感词"); |
| 27 | 27 | ||
| 28 | // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。 | 28 | // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。 |
| 29 | - ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2001000105, "营销短信发送时间限制"); | 29 | + ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2_001_000_105, "营销短信发送时间限制"); |
| 30 | 30 | ||
| 31 | - // ========== 模板相关 2001000200 ========== | ||
| 32 | - ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在 | ||
| 33 | - ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确"); | 31 | + // ========== 模板相关 2-001-000-200 ========== |
| 32 | + ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2_001_000_200, "短信模板不合法"); // 包括短信模板不存在 | ||
| 33 | + ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2_001_000_201, "模板参数不正确"); | ||
| 34 | 34 | ||
| 35 | - // ========== 签名相关 2001000300 ========== | ||
| 36 | - ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用"); | 35 | + // ========== 签名相关 2-001-000-300 ========== |
| 36 | + ErrorCode SMS_SIGN_INVALID = new ErrorCode(2_001_000_300, "短信签名不可用"); | ||
| 37 | 37 | ||
| 38 | - // ========== 账户相关 2001000400 ========== | ||
| 39 | - ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足"); | ||
| 40 | - ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在"); | 38 | + // ========== 账户相关 2-001-000-400 ========== |
| 39 | + ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2_001_000_400, "账户余额不足"); | ||
| 40 | + ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2_001_000_401, "apiKey 不存在"); | ||
| 41 | 41 | ||
| 42 | - // ========== 其它相关 2001000900 开头 ========== | ||
| 43 | - ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失"); | ||
| 44 | - ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确"); | ||
| 45 | - ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中"); | ||
| 46 | - ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2001000903, "SdkAppId不合法"); | 42 | + // ========== 其它相关 2-001-000-900 开头 ========== |
| 43 | + ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2_001_000_900, "请求参数缺失"); | ||
| 44 | + ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2_001_000_901, "手机格式不正确"); | ||
| 45 | + ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2_001_000_902, "手机号在黑名单中"); | ||
| 46 | + ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2_001_000_903, "SdkAppId不合法"); | ||
| 47 | 47 | ||
| 48 | - ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常"); | 48 | + ErrorCode EXCEPTION = new ErrorCode(2_001_000_999, "调用异常"); |
| 49 | 49 | ||
| 50 | } | 50 | } |
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<Config extends FileClientConfig> implem | @@ -30,7 +30,7 @@ public abstract class AbstractFileClient<Config extends FileClientConfig> 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<FileConfigDO> { | @@ -21,7 +18,8 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> { | ||
| 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 '@/utils/http/axios' | @@ -3,27 +3,27 @@ import { defHttp } from '@/utils/http/axios' | ||
| 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
yudao-module-mall/pom.xml
| @@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
| 15 | <name>${project.artifactId}</name> | 15 | <name>${project.artifactId}</name> |
| 16 | 16 | ||
| 17 | <description> | 17 | <description> |
| 18 | - 商城大模块,由 product 商品、promotion 营销、trade 交易等组成 | 18 | + 商城大模块,由 product 商品、promotion 营销、trade 交易、statistics 统计等组成 |
| 19 | </description> | 19 | </description> |
| 20 | <modules> | 20 | <modules> |
| 21 | <module>yudao-module-promotion-api</module> | 21 | <module>yudao-module-promotion-api</module> |
| @@ -24,6 +24,8 @@ | @@ -24,6 +24,8 @@ | ||
| 24 | <module>yudao-module-product-biz</module> | 24 | <module>yudao-module-product-biz</module> |
| 25 | <module>yudao-module-trade-api</module> | 25 | <module>yudao-module-trade-api</module> |
| 26 | <module>yudao-module-trade-biz</module> | 26 | <module>yudao-module-trade-biz</module> |
| 27 | + <module>yudao-module-statistics-api</module> | ||
| 28 | + <module>yudao-module-statistics-biz</module> | ||
| 27 | </modules> | 29 | </modules> |
| 28 | 30 | ||
| 29 | </project> | 31 | </project> |
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
| @@ -111,17 +111,19 @@ public class ProductSpuRespDTO { | @@ -111,17 +111,19 @@ public class ProductSpuRespDTO { | ||
| 111 | // ========== 物流相关字段 ========= | 111 | // ========== 物流相关字段 ========= |
| 112 | 112 | ||
| 113 | /** | 113 | /** |
| 114 | - * 赠送积分 | ||
| 115 | - */ | ||
| 116 | - private Integer giveIntegral; | ||
| 117 | - | ||
| 118 | - /** | ||
| 119 | * 物流配置模板编号 | 114 | * 物流配置模板编号 |
| 120 | * | 115 | * |
| 121 | * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 | 116 | * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 |
| 122 | */ | 117 | */ |
| 123 | private Long deliveryTemplateId; | 118 | private Long deliveryTemplateId; |
| 124 | 119 | ||
| 120 | + // ========== 营销相关字段 ========= | ||
| 121 | + | ||
| 122 | + /** | ||
| 123 | + * 赠送积分 | ||
| 124 | + */ | ||
| 125 | + private Integer giveIntegral; | ||
| 126 | + | ||
| 125 | // ========== 统计相关字段 ========= | 127 | // ========== 统计相关字段 ========= |
| 126 | 128 | ||
| 127 | /** | 129 | /** |
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-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java
| @@ -68,7 +68,7 @@ public class RewardActivityMatchRespDTO { | @@ -68,7 +68,7 @@ public class RewardActivityMatchRespDTO { | ||
| 68 | */ | 68 | */ |
| 69 | private List<Long> couponIds; | 69 | private List<Long> couponIds; |
| 70 | /** | 70 | /** |
| 71 | - * 赠送的优惠卷数量的数组 | 71 | + * 赠送的优惠券数量的数组 |
| 72 | */ | 72 | */ |
| 73 | private List<Integer> couponCounts; | 73 | private List<Integer> couponCounts; |
| 74 | 74 |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
| @@ -9,66 +9,75 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | @@ -9,66 +9,75 @@ 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 ========== | ||
| 53 | - ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在"); | ||
| 54 | - ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突"); | ||
| 55 | - ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); | ||
| 56 | - ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); | ||
| 57 | - ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); | ||
| 58 | - ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足"); | ||
| 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, "秒杀时段已关闭"); | ||
| 64 | - | ||
| 65 | - // ========== 拼团活动 1013010000 ========== | ||
| 66 | - ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); | ||
| 67 | - ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动"); | ||
| 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, "拼团活动未关闭或未结束,不能删除"); | ||
| 70 | - ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭"); | ||
| 71 | - | 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(1_013_008_000, "秒杀活动不存在"); | ||
| 54 | + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_008_002, "存在商品参加了其它秒杀活动,秒杀时段冲突"); | ||
| 55 | + ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_008_003, "秒杀活动已关闭,不能修改"); | ||
| 56 | + ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_008_004, "秒杀活动未关闭或未结束,不能删除"); | ||
| 57 | + ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_008_005, "秒杀活动已关闭,不能重复关闭"); | ||
| 58 | + ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_008_006, "秒杀失败,原因秒杀库存不足"); | ||
| 59 | + | ||
| 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 | + | ||
| 65 | + // ========== 拼团活动 1-013-010-000 ========== | ||
| 66 | + ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_010_000, "拼团活动不存在"); | ||
| 67 | + ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_010_001, "存在商品参加了其它拼团活动"); | ||
| 68 | + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1_013_010_002, "拼团活动已关闭不能修改"); | ||
| 69 | + ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_010_003, "拼团活动未关闭或未结束,不能删除"); | ||
| 70 | + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1_013_010_004, "拼团失败,原因:拼团活动已关闭"); | ||
| 71 | + | ||
| 72 | + // ========== 拼团记录 1-013-011-000 ========== | ||
| 73 | + ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1_013_011_000, "拼团不存在"); | ||
| 74 | + ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1_013_011_001, "拼团失败,已参与过该拼团"); | ||
| 75 | + ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在"); | ||
| 76 | + ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满"); | ||
| 77 | + ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团"); | ||
| 78 | + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_005, "拼团失败,活动已经结束"); | ||
| 79 | + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_006, "拼团失败,原因:单次限购超出"); | ||
| 80 | + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:超出总购买次数"); | ||
| 72 | // ========== 拼团记录 1013011000 ========== | 81 | // ========== 拼团记录 1013011000 ========== |
| 73 | ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在"); | 82 | ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在"); |
| 74 | ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团"); | 83 | ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团"); |
| @@ -80,17 +89,17 @@ public interface ErrorCodeConstants { | @@ -80,17 +89,17 @@ public interface ErrorCodeConstants { | ||
| 80 | ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出"); | 89 | ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出"); |
| 81 | ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数"); | 90 | ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数"); |
| 82 | 91 | ||
| 83 | - // ========== 砍价活动 1013012000 ========== | ||
| 84 | - ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在"); | ||
| 85 | - ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动"); | ||
| 86 | - ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改"); | ||
| 87 | - ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除"); | ||
| 88 | - ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足"); | ||
| 89 | - | ||
| 90 | - // ========== 砍价记录 1013013000 ========== | ||
| 91 | - ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在"); | ||
| 92 | - ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1013013001, "砍价失败,已参与过该砍价"); | ||
| 93 | - ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013013002, "砍价失败,父砍价不存在"); | ||
| 94 | - ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1013013003, "砍价失败,砍价人数已满"); | 92 | + // ========== 砍价活动 1-013-012-000 ========== |
| 93 | + ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_012_000, "砍价活动不存在"); | ||
| 94 | + ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_012_001, "存在商品参加了其它砍价活动"); | ||
| 95 | + ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1_013_012_002, "砍价活动已关闭不能修改"); | ||
| 96 | + ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_012_003, "砍价活动未关闭或未结束,不能删除"); | ||
| 97 | + ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_012_004, "砍价失败,原因:该砍价活动库存不足"); | ||
| 98 | + | ||
| 99 | + // ========== 砍价记录 1-013-013-000 ========== | ||
| 100 | + ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1_013_013_000, "砍价记录不存在"); | ||
| 101 | + ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1_013_013_001, "砍价失败,已参与过该砍价"); | ||
| 102 | + ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_013_002, "砍价失败,父砍价不存在"); | ||
| 103 | + ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1_013_013_003, "砍价失败,砍价人数已满"); | ||
| 95 | 104 | ||
| 96 | } | 105 | } |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionProductScopeEnum.java
| @@ -15,9 +15,9 @@ import java.util.Arrays; | @@ -15,9 +15,9 @@ import java.util.Arrays; | ||
| 15 | @AllArgsConstructor | 15 | @AllArgsConstructor |
| 16 | public enum PromotionProductScopeEnum implements IntArrayValuable { | 16 | public enum PromotionProductScopeEnum implements IntArrayValuable { |
| 17 | 17 | ||
| 18 | - ALL(1, "通用卷"), // 全部商品 | ||
| 19 | - SPU(2, "商品卷"), // 指定商品 | ||
| 20 | - CATEGORY(3, "品类卷"), // 指定商品 | 18 | + ALL(1, "通用券"), // 全部商品 |
| 19 | + SPU(2, "商品券"), // 指定商品 | ||
| 20 | + CATEGORY(3, "品类券"), // 指定品类 | ||
| 21 | ; | 21 | ; |
| 22 | 22 | ||
| 23 | public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray(); | 23 | public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray(); |
yudao-module-mall/yudao-module-promotion-biz/pom.xml
| @@ -47,6 +47,10 @@ | @@ -47,6 +47,10 @@ | ||
| 47 | </dependency> | 47 | </dependency> |
| 48 | <dependency> | 48 | <dependency> |
| 49 | <groupId>cn.iocoder.boot</groupId> | 49 | <groupId>cn.iocoder.boot</groupId> |
| 50 | + <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> | ||
| 51 | + </dependency> | ||
| 52 | + <dependency> | ||
| 53 | + <groupId>cn.iocoder.boot</groupId> | ||
| 50 | <artifactId>yudao-spring-boot-starter-biz-weixin</artifactId> | 54 | <artifactId>yudao-spring-boot-starter-biz-weixin</artifactId> |
| 51 | </dependency> | 55 | </dependency> |
| 52 | 56 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponController.java
| @@ -37,15 +37,6 @@ public class CouponController { | @@ -37,15 +37,6 @@ public class CouponController { | ||
| 37 | @Resource | 37 | @Resource |
| 38 | private MemberUserApi memberUserApi; | 38 | private MemberUserApi memberUserApi; |
| 39 | 39 | ||
| 40 | -// @GetMapping("/get") | ||
| 41 | -// @Operation(summary = "获得优惠劵") | ||
| 42 | -// @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||
| 43 | -// @PreAuthorize("@ss.hasPermission('promotion:coupon:query')") | ||
| 44 | -// public CommonResult<CouponRespVO> getCoupon(@RequestParam("id") Long id) { | ||
| 45 | -// CouponDO coupon = couponService.getCoupon(id); | ||
| 46 | -// return success(CouponConvert.INSTANCE.convert(coupon)); | ||
| 47 | -// } | ||
| 48 | - | ||
| 49 | @DeleteMapping("/delete") | 40 | @DeleteMapping("/delete") |
| 50 | @Operation(summary = "回收优惠劵") | 41 | @Operation(summary = "回收优惠劵") |
| 51 | @Parameter(name = "id", description = "编号", required = true) | 42 | @Parameter(name = "id", description = "编号", required = true) |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponPageReqVO.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon; | 1 | package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | ||
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | import lombok.Data; | 7 | import lombok.Data; |
| 6 | import lombok.EqualsAndHashCode; | 8 | import lombok.EqualsAndHashCode; |
| @@ -8,6 +10,7 @@ import lombok.ToString; | @@ -8,6 +10,7 @@ import lombok.ToString; | ||
| 8 | import org.springframework.format.annotation.DateTimeFormat; | 10 | import org.springframework.format.annotation.DateTimeFormat; |
| 9 | 11 | ||
| 10 | import java.time.LocalDateTime; | 12 | import java.time.LocalDateTime; |
| 13 | +import java.util.Collection; | ||
| 11 | 14 | ||
| 12 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 15 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 13 | 16 | ||
| @@ -21,6 +24,7 @@ public class CouponPageReqVO extends PageParam { | @@ -21,6 +24,7 @@ public class CouponPageReqVO extends PageParam { | ||
| 21 | private Long templateId; | 24 | private Long templateId; |
| 22 | 25 | ||
| 23 | @Schema(description = "优惠码状态", example = "1") | 26 | @Schema(description = "优惠码状态", example = "1") |
| 27 | + @InEnum(value = CouponStatusEnum.class, message = "优惠劵状态,必须是 {value}") | ||
| 24 | private Integer status; | 28 | private Integer status; |
| 25 | 29 | ||
| 26 | @Schema(description = "创建时间") | 30 | @Schema(description = "创建时间") |
| @@ -30,4 +34,7 @@ public class CouponPageReqVO extends PageParam { | @@ -30,4 +34,7 @@ public class CouponPageReqVO extends PageParam { | ||
| 30 | @Schema(description = "用户昵称", example = "芋艿") | 34 | @Schema(description = "用户昵称", example = "芋艿") |
| 31 | private String nickname; | 35 | private String nickname; |
| 32 | 36 | ||
| 37 | + @Schema(description = "用户编号", example = "1") | ||
| 38 | + private Collection<Long> userIds; | ||
| 39 | + | ||
| 33 | } | 40 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | import cn.iocoder.yudao.framework.common.validation.InEnum; | 4 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 5 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | ||
| 5 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | 6 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; |
| 6 | import io.swagger.v3.oas.annotations.media.Schema; | 7 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | import lombok.Data; | 8 | import lombok.Data; |
| @@ -33,8 +34,15 @@ public class CouponTemplatePageReqVO extends PageParam { | @@ -33,8 +34,15 @@ public class CouponTemplatePageReqVO extends PageParam { | ||
| 33 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 34 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 34 | private LocalDateTime[] createTime; | 35 | private LocalDateTime[] createTime; |
| 35 | 36 | ||
| 36 | - @Schema(description = "可以领取的类型", example = "[1,2, 3]") | 37 | + @Schema(description = "可以领取的类型", example = "[1, 2, 3]") |
| 37 | @InEnum(value = CouponTakeTypeEnum.class, message = "可以领取的类型,必须是 {value}") | 38 | @InEnum(value = CouponTakeTypeEnum.class, message = "可以领取的类型,必须是 {value}") |
| 38 | private List<Integer> canTakeTypes; | 39 | private List<Integer> canTakeTypes; |
| 39 | 40 | ||
| 41 | + @Schema(description = "商品范围", example = "1") | ||
| 42 | + @InEnum(value = PromotionProductScopeEnum.class, message = "商品范围,必须是 {value}") | ||
| 43 | + private Integer productScope; | ||
| 44 | + | ||
| 45 | + @Schema(description = "商品范围编号", example = "1") | ||
| 46 | + private Long productScopeValue; | ||
| 47 | + | ||
| 40 | } | 48 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/reward/vo/RewardActivityBaseVO.java
| @@ -84,7 +84,7 @@ public class RewardActivityBaseVO { | @@ -84,7 +84,7 @@ public class RewardActivityBaseVO { | ||
| 84 | @Schema(description = "赠送的优惠劵编号的数组", example = "1,2,3") | 84 | @Schema(description = "赠送的优惠劵编号的数组", example = "1,2,3") |
| 85 | private List<Long> couponIds; | 85 | private List<Long> couponIds; |
| 86 | 86 | ||
| 87 | - @Schema(description = "赠送的优惠卷数量的数组", example = "1,2,3") | 87 | + @Schema(description = "赠送的优惠券数量的数组", example = "1,2,3") |
| 88 | private List<Integer> couponCounts; | 88 | private List<Integer> couponCounts; |
| 89 | 89 | ||
| 90 | @AssertTrue(message = "优惠劵和数量必须一一对应") | 90 | @AssertTrue(message = "优惠劵和数量必须一一对应") |
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-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; | 6 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; |
| 6 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; | ||
| 7 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO; | ||
| 8 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; | ||
| 9 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; | ||
| 10 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO; | 7 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*; |
| 8 | +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; | ||
| 9 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | ||
| 10 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | ||
| 11 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | ||
| 11 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; | 12 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; |
| 13 | +import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; | ||
| 12 | import io.swagger.v3.oas.annotations.Operation; | 14 | import io.swagger.v3.oas.annotations.Operation; |
| 15 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | import io.swagger.v3.oas.annotations.tags.Tag; | 16 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 14 | import org.springframework.validation.annotation.Validated; | 17 | import org.springframework.validation.annotation.Validated; |
| 15 | import org.springframework.web.bind.annotation.*; | 18 | import org.springframework.web.bind.annotation.*; |
| 16 | 19 | ||
| 17 | import javax.annotation.Resource; | 20 | import javax.annotation.Resource; |
| 18 | -import java.time.LocalDateTime; | ||
| 19 | -import java.util.ArrayList; | 21 | +import javax.validation.Valid; |
| 22 | +import java.util.Collections; | ||
| 20 | import java.util.List; | 23 | import java.util.List; |
| 21 | -import java.util.Random; | ||
| 22 | 24 | ||
| 23 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 25 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 24 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 26 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| @@ -31,73 +33,42 @@ public class AppCouponController { | @@ -31,73 +33,42 @@ public class AppCouponController { | ||
| 31 | 33 | ||
| 32 | @Resource | 34 | @Resource |
| 33 | private CouponService couponService; | 35 | private CouponService couponService; |
| 36 | + @Resource | ||
| 37 | + private CouponTemplateService couponTemplateService; | ||
| 34 | 38 | ||
| 35 | - // TODO 芋艿:待实现 | ||
| 36 | @PostMapping("/take") | 39 | @PostMapping("/take") |
| 37 | @Operation(summary = "领取优惠劵") | 40 | @Operation(summary = "领取优惠劵") |
| 38 | - public CommonResult<Long> takeCoupon(@RequestBody AppCouponTemplatePageReqVO pageReqVO) { | ||
| 39 | - return success(1L); | 41 | + @Parameter(name = "templateId", description = "优惠券模板编号", required = true, example = "1024") |
| 42 | + @PreAuthenticated | ||
| 43 | + public CommonResult<Boolean> takeCoupon(@Valid @RequestBody AppCouponTakeReqVO reqVO) { | ||
| 44 | + // 1. 领取优惠劵 | ||
| 45 | + Long userId = getLoginUserId(); | ||
| 46 | + couponService.takeCoupon(reqVO.getTemplateId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.USER); | ||
| 47 | + | ||
| 48 | + // 2. 检查是否可以继续领取 | ||
| 49 | + CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(reqVO.getTemplateId()); | ||
| 50 | + boolean canTakeAgain = true; | ||
| 51 | + if (couponTemplate.getTakeLimitCount() != null && couponTemplate.getTakeLimitCount() > 0) { | ||
| 52 | + Integer takeCount = couponService.getTakeCount(reqVO.getTemplateId(), userId); | ||
| 53 | + canTakeAgain = takeCount < couponTemplate.getTakeLimitCount(); | ||
| 54 | + } | ||
| 55 | + return success(canTakeAgain); | ||
| 40 | } | 56 | } |
| 41 | 57 | ||
| 42 | - // TODO 芋艿:待实现 | ||
| 43 | @GetMapping("/match-list") | 58 | @GetMapping("/match-list") |
| 44 | - @Operation(summary = "获得匹配指定商品的优惠劵列表") | 59 | + @Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表") |
| 45 | public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) { | 60 | public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) { |
| 46 | - List<AppCouponMatchRespVO> list = new ArrayList<>(); | ||
| 47 | - Random random = new Random(); | ||
| 48 | - for (int i = 0; i < 10; i++) { | ||
| 49 | - AppCouponMatchRespVO vo = new AppCouponMatchRespVO(); | ||
| 50 | - vo.setId(i + 1L); | ||
| 51 | - vo.setName("优惠劵" + (i + 1)); | ||
| 52 | - vo.setUsePrice(random.nextInt(100) * 100); | ||
| 53 | - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10))); | ||
| 54 | - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10)); | ||
| 55 | - vo.setDiscountType(random.nextInt(2) + 1); | ||
| 56 | - if (vo.getDiscountType() == 1) { | ||
| 57 | - vo.setDiscountPercent(null); | ||
| 58 | - vo.setDiscountPrice(random.nextInt(50) * 100); | ||
| 59 | - vo.setDiscountLimitPrice(null); | ||
| 60 | - } else { | ||
| 61 | - vo.setDiscountPercent(random.nextInt(90) + 10); | ||
| 62 | - vo.setDiscountPrice(null); | ||
| 63 | - vo.setDiscountLimitPrice(random.nextInt(200) * 100); | ||
| 64 | - } | ||
| 65 | - vo.setMatch(random.nextBoolean()); | ||
| 66 | - if (!vo.getMatch()) { | ||
| 67 | - vo.setDescription("不符合条件噢"); | ||
| 68 | - } | ||
| 69 | - list.add(vo); | ||
| 70 | - } | ||
| 71 | - return success(list); | 61 | + // todo: 优化:优惠金额倒序 |
| 62 | + return success(CouponConvert.INSTANCE.convertList(couponService.getMatchCouponList(getLoginUserId(), matchReqVO))); | ||
| 72 | } | 63 | } |
| 73 | 64 | ||
| 74 | - // TODO 芋艿:待实现 | ||
| 75 | @GetMapping("/page") | 65 | @GetMapping("/page") |
| 76 | - @Operation(summary = "优惠劵列表", description = "我的优惠劵") | ||
| 77 | - public CommonResult<PageResult<AppCouponRespVO>> takeCoupon(AppCouponPageReqVO pageReqVO) { | ||
| 78 | - List<AppCouponRespVO> list = new ArrayList<>(); | ||
| 79 | - Random random = new Random(); | ||
| 80 | - for (int i = 0; i < 10; i++) { | ||
| 81 | - AppCouponRespVO vo = new AppCouponRespVO(); | ||
| 82 | - vo.setId(i + 1L); | ||
| 83 | - vo.setName("优惠劵" + (i + 1)); | ||
| 84 | - vo.setStatus(pageReqVO.getStatus()); | ||
| 85 | - vo.setUsePrice(random.nextInt(100) * 100); | ||
| 86 | - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10))); | ||
| 87 | - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10)); | ||
| 88 | - vo.setDiscountType(random.nextInt(2) + 1); | ||
| 89 | - if (vo.getDiscountType() == 1) { | ||
| 90 | - vo.setDiscountPercent(null); | ||
| 91 | - vo.setDiscountPrice(random.nextInt(50) * 100); | ||
| 92 | - vo.setDiscountLimitPrice(null); | ||
| 93 | - } else { | ||
| 94 | - vo.setDiscountPercent(random.nextInt(90) + 10); | ||
| 95 | - vo.setDiscountPrice(null); | ||
| 96 | - vo.setDiscountLimitPrice(random.nextInt(200) * 100); | ||
| 97 | - } | ||
| 98 | - list.add(vo); | ||
| 99 | - } | ||
| 100 | - return success(new PageResult<>(list, 20L)); | 66 | + @Operation(summary = "我的优惠劵列表") |
| 67 | + @PreAuthenticated | ||
| 68 | + public CommonResult<PageResult<AppCouponRespVO>> getCouponPage(AppCouponPageReqVO pageReqVO) { | ||
| 69 | + PageResult<CouponDO> pageResult = couponService.getCouponPage( | ||
| 70 | + CouponConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId()))); | ||
| 71 | + return success(CouponConvert.INSTANCE.convertAppPage(pageResult)); | ||
| 101 | } | 72 | } |
| 102 | 73 | ||
| 103 | @GetMapping(value = "/get-unused-count") | 74 | @GetMapping(value = "/get-unused-count") |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.ObjUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 7 | +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 8 | +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||
| 5 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO; | 9 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplateRespVO; | 10 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplateRespVO; |
| 11 | +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; | ||
| 12 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | ||
| 13 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | ||
| 14 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | ||
| 15 | +import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; | ||
| 7 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; | 16 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; |
| 8 | import io.swagger.v3.oas.annotations.Operation; | 17 | import io.swagger.v3.oas.annotations.Operation; |
| 9 | import io.swagger.v3.oas.annotations.Parameter; | 18 | import io.swagger.v3.oas.annotations.Parameter; |
| @@ -17,11 +26,11 @@ import org.springframework.web.bind.annotation.RestController; | @@ -17,11 +26,11 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 17 | 26 | ||
| 18 | import javax.annotation.Resource; | 27 | import javax.annotation.Resource; |
| 19 | import java.time.LocalDateTime; | 28 | import java.time.LocalDateTime; |
| 20 | -import java.util.ArrayList; | ||
| 21 | -import java.util.List; | ||
| 22 | -import java.util.Random; | 29 | +import java.util.*; |
| 23 | 30 | ||
| 24 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 31 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 32 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 33 | +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; | ||
| 25 | 34 | ||
| 26 | @Tag(name = "用户 App - 优惠劵模板") | 35 | @Tag(name = "用户 App - 优惠劵模板") |
| 27 | @RestController | 36 | @RestController |
| @@ -31,8 +40,13 @@ public class AppCouponTemplateController { | @@ -31,8 +40,13 @@ public class AppCouponTemplateController { | ||
| 31 | 40 | ||
| 32 | @Resource | 41 | @Resource |
| 33 | private CouponTemplateService couponTemplateService; | 42 | private CouponTemplateService couponTemplateService; |
| 43 | + @Resource | ||
| 44 | + private CouponService couponService; | ||
| 45 | + | ||
| 46 | + @Resource | ||
| 47 | + private ProductSpuApi productSpuApi; | ||
| 34 | 48 | ||
| 35 | - // TODO 芋艿:待实现 | 49 | + // TODO 疯狂:这里应该还有个 list 接口哈;获得优惠劵模版列表,用于首页、商品页的优惠劵 |
| 36 | @GetMapping("/list") | 50 | @GetMapping("/list") |
| 37 | @Operation(summary = "获得优惠劵模版列表") | 51 | @Operation(summary = "获得优惠劵模版列表") |
| 38 | @Parameters({ | 52 | @Parameters({ |
| @@ -40,9 +54,10 @@ public class AppCouponTemplateController { | @@ -40,9 +54,10 @@ public class AppCouponTemplateController { | ||
| 40 | @Parameter(name = "useType", description = "使用类型"), | 54 | @Parameter(name = "useType", description = "使用类型"), |
| 41 | @Parameter(name = "count", description = "数量", required = true) | 55 | @Parameter(name = "count", description = "数量", required = true) |
| 42 | }) | 56 | }) |
| 43 | - public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList(@RequestParam(value = "spuId", required = false) Long spuId, | ||
| 44 | - @RequestParam(value = "useType", required = false) Integer useType, | ||
| 45 | - @RequestParam(value = "count", required = false, defaultValue = "10") Integer count) { | 57 | + public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList( |
| 58 | + @RequestParam(value = "spuId", required = false) Long spuId, | ||
| 59 | + @RequestParam(value = "useType", required = false) Integer useType, | ||
| 60 | + @RequestParam(value = "count", required = false, defaultValue = "10") Integer count) { | ||
| 46 | List<AppCouponTemplateRespVO> list = new ArrayList<>(); | 61 | List<AppCouponTemplateRespVO> list = new ArrayList<>(); |
| 47 | Random random = new Random(); | 62 | Random random = new Random(); |
| 48 | for (int i = 0; i < 10; i++) { | 63 | for (int i = 0; i < 10; i++) { |
| @@ -69,46 +84,55 @@ public class AppCouponTemplateController { | @@ -69,46 +84,55 @@ public class AppCouponTemplateController { | ||
| 69 | vo.setDiscountPrice(null); | 84 | vo.setDiscountPrice(null); |
| 70 | vo.setDiscountLimitPrice(random.nextInt(200) * 100); | 85 | vo.setDiscountLimitPrice(random.nextInt(200) * 100); |
| 71 | } | 86 | } |
| 87 | + // TODO @疯狂:是否已领取,要不在 TemplateService 搞个 static 方法,让它基于 countMap 这种去计算,这样好点? | ||
| 72 | vo.setTakeStatus(random.nextBoolean()); | 88 | vo.setTakeStatus(random.nextBoolean()); |
| 73 | list.add(vo); | 89 | list.add(vo); |
| 74 | } | 90 | } |
| 75 | return success(list); | 91 | return success(list); |
| 76 | } | 92 | } |
| 77 | 93 | ||
| 78 | - // TODO 芋艿:待实现;和 getCouponTemplateList 类似 | ||
| 79 | @GetMapping("/page") | 94 | @GetMapping("/page") |
| 80 | @Operation(summary = "获得优惠劵模版分页") | 95 | @Operation(summary = "获得优惠劵模版分页") |
| 81 | public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) { | 96 | public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) { |
| 82 | - List<AppCouponTemplateRespVO> list = new ArrayList<>(); | ||
| 83 | - Random random = new Random(); | ||
| 84 | - for (int i = 0; i < 10; i++) { | ||
| 85 | - AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO(); | ||
| 86 | - vo.setId(i + 1L); | ||
| 87 | - vo.setName("优惠劵" + (i + 1)); | ||
| 88 | - vo.setTakeLimitCount(random.nextInt(10) + 1); | ||
| 89 | - vo.setUsePrice(random.nextInt(100) * 100); | ||
| 90 | - vo.setValidityType(random.nextInt(2) + 1); | ||
| 91 | - if (vo.getValidityType() == 1) { | ||
| 92 | - vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10))); | ||
| 93 | - vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10)); | ||
| 94 | - } else { | ||
| 95 | - vo.setFixedStartTerm(random.nextInt(10)); | ||
| 96 | - vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1); | ||
| 97 | - } | ||
| 98 | - vo.setDiscountType(random.nextInt(2) + 1); | ||
| 99 | - if (vo.getDiscountType() == 1) { | ||
| 100 | - vo.setDiscountPercent(null); | ||
| 101 | - vo.setDiscountPrice(random.nextInt(50) * 100); | ||
| 102 | - vo.setDiscountLimitPrice(null); | ||
| 103 | - } else { | ||
| 104 | - vo.setDiscountPercent(random.nextInt(90) + 10); | ||
| 105 | - vo.setDiscountPrice(null); | ||
| 106 | - vo.setDiscountLimitPrice(random.nextInt(200) * 100); | ||
| 107 | - } | ||
| 108 | - vo.setTakeStatus(random.nextBoolean()); | ||
| 109 | - list.add(vo); | 97 | + // 1.1 处理查询条件:商品范围编号 |
| 98 | + Long productScopeValue = getProductScopeValue(pageReqVO); | ||
| 99 | + // 1.2 处理查询条件:领取方式 = 直接领取 | ||
| 100 | + List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue()); | ||
| 101 | + | ||
| 102 | + // 2. 分页查询 | ||
| 103 | + PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage( | ||
| 104 | + CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue)); | ||
| 105 | + | ||
| 106 | + // 3.1 领取数量 | ||
| 107 | + Map<Long, Integer> couponTakeCountMap = new HashMap<>(0); | ||
| 108 | + Long userId = getLoginUserId(); | ||
| 109 | + if (userId != null) { | ||
| 110 | + List<Long> templateIds = convertList(pageResult.getList(), CouponTemplateDO::getId, | ||
| 111 | + t -> ObjUtil.notEqual(t.getTakeLimitCount(), -1)); // 只查有设置“每人限领个数”的 | ||
| 112 | + couponTakeCountMap = couponService.getTakeCountMapByTemplateIds(templateIds, userId); | ||
| 113 | + } | ||
| 114 | + // 3.2 拼接返回 | ||
| 115 | + return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap)); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * 获得分页查询的商品范围 | ||
| 120 | + * | ||
| 121 | + * @param pageReqVO 分页查询 | ||
| 122 | + * @return 商品范围 | ||
| 123 | + */ | ||
| 124 | + private Long getProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) { | ||
| 125 | + // 通用券:清除商品范围 | ||
| 126 | + if (pageReqVO.getProductScope() == null || ObjectUtils.equalsAny(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope(), null)) { | ||
| 127 | + return null; | ||
| 128 | + } | ||
| 129 | + // 品类券:查询商品的品类 | ||
| 130 | + if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) { | ||
| 131 | + return Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId())) | ||
| 132 | + .map(ProductSpuRespDTO::getCategoryId).orElse(null); | ||
| 110 | } | 133 | } |
| 111 | - return success(new PageResult<>(list, 20L)); | 134 | + // 商品卷:直接返回 |
| 135 | + return pageReqVO.getSpuId(); | ||
| 112 | } | 136 | } |
| 113 | 137 | ||
| 114 | } | 138 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java
| @@ -15,15 +15,15 @@ public class AppCouponMatchReqVO { | @@ -15,15 +15,15 @@ public class AppCouponMatchReqVO { | ||
| 15 | @NotNull(message = "商品金额不能为空") | 15 | @NotNull(message = "商品金额不能为空") |
| 16 | private Integer price; | 16 | private Integer price; |
| 17 | 17 | ||
| 18 | - @Schema(description = "商品 SPU 编号的数组", required = true, example = "[1, 2]") | 18 | + @Schema(description = "商品 SPU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") |
| 19 | @NotEmpty(message = "商品 SPU 编号不能为空") | 19 | @NotEmpty(message = "商品 SPU 编号不能为空") |
| 20 | private List<Long> spuIds; | 20 | private List<Long> spuIds; |
| 21 | 21 | ||
| 22 | - @Schema(description = "商品 SKU 编号的数组", required = true, example = "[1, 2]") | 22 | + @Schema(description = "商品 SKU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") |
| 23 | @NotEmpty(message = "商品 SKU 编号不能为空") | 23 | @NotEmpty(message = "商品 SKU 编号不能为空") |
| 24 | private List<Long> skuIds; | 24 | private List<Long> skuIds; |
| 25 | 25 | ||
| 26 | - @Schema(description = "分类编号的数组", required = true, example = "[10, 20]") | 26 | + @Schema(description = "分类编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[10, 20]") |
| 27 | @NotEmpty(message = "分类编号不能为空") | 27 | @NotEmpty(message = "分类编号不能为空") |
| 28 | private List<Long> categoryIds; | 28 | private List<Long> categoryIds; |
| 29 | 29 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponPageReqVO.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | ||
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | import lombok.Data; | 7 | import lombok.Data; |
| 6 | import lombok.EqualsAndHashCode; | 8 | import lombok.EqualsAndHashCode; |
| @@ -13,6 +15,7 @@ import lombok.ToString; | @@ -13,6 +15,7 @@ import lombok.ToString; | ||
| 13 | public class AppCouponPageReqVO extends PageParam { | 15 | public class AppCouponPageReqVO extends PageParam { |
| 14 | 16 | ||
| 15 | @Schema(description = "优惠劵状态", example = "1") | 17 | @Schema(description = "优惠劵状态", example = "1") |
| 18 | + @InEnum(value = CouponStatusEnum.class, message = "优惠劵状态,必须是 {value}") | ||
| 16 | private Integer status; | 19 | private Integer status; |
| 17 | 20 | ||
| 18 | } | 21 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplatePageReqVO.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | ||
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | import lombok.Data; | 7 | import lombok.Data; |
| 6 | import lombok.EqualsAndHashCode; | 8 | import lombok.EqualsAndHashCode; |
| @@ -12,8 +14,11 @@ import lombok.ToString; | @@ -12,8 +14,11 @@ import lombok.ToString; | ||
| 12 | @ToString(callSuper = true) | 14 | @ToString(callSuper = true) |
| 13 | public class AppCouponTemplatePageReqVO extends PageParam { | 15 | public class AppCouponTemplatePageReqVO extends PageParam { |
| 14 | 16 | ||
| 15 | - @Schema(description = "使用类型", example = "1") | ||
| 16 | - // TODO 芋艿:这里要限制下枚举的使用 | ||
| 17 | - private Integer useType; | 17 | + @Schema(description = "商品范围", example = "1") |
| 18 | + @InEnum(value = PromotionProductScopeEnum.class, message = "商品范围,必须是 {value}") | ||
| 19 | + private Integer productScope; | ||
| 20 | + | ||
| 21 | + @Schema(description = "商品标号", example = "1") | ||
| 22 | + private Long spuId; | ||
| 18 | 23 | ||
| 19 | } | 24 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java
| @@ -23,14 +23,6 @@ public class AppCouponTemplateRespVO { | @@ -23,14 +23,6 @@ public class AppCouponTemplateRespVO { | ||
| 23 | // 单位:分;0 - 不限制 | 23 | // 单位:分;0 - 不限制 |
| 24 | private Integer usePrice; | 24 | private Integer usePrice; |
| 25 | 25 | ||
| 26 | - // TODO 芋艿:这两要改的 | ||
| 27 | -// @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 28 | -// @InEnum(PromotionProductScopeEnum.class) | ||
| 29 | -// private Integer productScope; | ||
| 30 | -// | ||
| 31 | -// @Schema(description = "商品范围编号的数组", example = "1,3") | ||
| 32 | -// private List<Long> productScopeValues; | ||
| 33 | - | ||
| 34 | @Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 26 | @Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 35 | private Integer validityType; | 27 | private Integer validityType; |
| 36 | 28 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java
| @@ -3,6 +3,10 @@ package cn.iocoder.yudao.module.promotion.convert.coupon; | @@ -3,6 +3,10 @@ package cn.iocoder.yudao.module.promotion.convert.coupon; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; |
| 6 | +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; | ||
| 6 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 8 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | 12 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; |
| @@ -11,6 +15,8 @@ import org.mapstruct.Mapper; | @@ -11,6 +15,8 @@ import org.mapstruct.Mapper; | ||
| 11 | import org.mapstruct.factory.Mappers; | 15 | import org.mapstruct.factory.Mappers; |
| 12 | 16 | ||
| 13 | import java.time.LocalDateTime; | 17 | import java.time.LocalDateTime; |
| 18 | +import java.util.Collection; | ||
| 19 | +import java.util.List; | ||
| 14 | 20 | ||
| 15 | /** | 21 | /** |
| 16 | * 优惠劵 Convert | 22 | * 优惠劵 Convert |
| @@ -49,4 +55,11 @@ public interface CouponConvert { | @@ -49,4 +55,11 @@ public interface CouponConvert { | ||
| 49 | } | 55 | } |
| 50 | return couponDO; | 56 | return couponDO; |
| 51 | } | 57 | } |
| 58 | + | ||
| 59 | + CouponPageReqVO convert(AppCouponPageReqVO pageReqVO, Collection<Long> userIds); | ||
| 60 | + | ||
| 61 | + PageResult<AppCouponRespVO> convertAppPage(PageResult<CouponDO> pageResult); | ||
| 62 | + | ||
| 63 | + List<AppCouponMatchRespVO> convertList(List<CouponDO> list); | ||
| 64 | + | ||
| 52 | } | 65 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponTemplateConvert.java
| 1 | package cn.iocoder.yudao.module.promotion.convert.coupon; | 1 | package cn.iocoder.yudao.module.promotion.convert.coupon; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.map.MapUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateCreateReqVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateCreateReqVO; |
| 6 | +import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO; | ||
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateRespVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateRespVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; |
| 9 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplateRespVO; | ||
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 8 | import org.mapstruct.Mapper; | 12 | import org.mapstruct.Mapper; |
| 9 | import org.mapstruct.factory.Mappers; | 13 | import org.mapstruct.factory.Mappers; |
| 10 | 14 | ||
| 15 | +import java.util.List; | ||
| 16 | +import java.util.Map; | ||
| 17 | + | ||
| 11 | /** | 18 | /** |
| 12 | * 优惠劵模板 Convert | 19 | * 优惠劵模板 Convert |
| 13 | * | 20 | * |
| @@ -26,4 +33,25 @@ public interface CouponTemplateConvert { | @@ -26,4 +33,25 @@ public interface CouponTemplateConvert { | ||
| 26 | 33 | ||
| 27 | PageResult<CouponTemplateRespVO> convertPage(PageResult<CouponTemplateDO> page); | 34 | PageResult<CouponTemplateRespVO> convertPage(PageResult<CouponTemplateDO> page); |
| 28 | 35 | ||
| 36 | + CouponTemplatePageReqVO convert(AppCouponTemplatePageReqVO pageReqVO, List<Integer> canTakeTypes, Integer productScope, Long productScopeValue); | ||
| 37 | + | ||
| 38 | + PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult); | ||
| 39 | + | ||
| 40 | + default PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult, Map<Long, Integer> couponTakeCountMap) { | ||
| 41 | + PageResult<AppCouponTemplateRespVO> result = convertAppPage(pageResult); | ||
| 42 | + if (MapUtil.isEmpty(couponTakeCountMap)) { | ||
| 43 | + return result; | ||
| 44 | + } | ||
| 45 | + for (AppCouponTemplateRespVO template : result.getList()) { | ||
| 46 | + // 每人领取数量无限制 | ||
| 47 | + if (template.getTakeLimitCount() == -1) { | ||
| 48 | + template.setTakeStatus(false); | ||
| 49 | + continue; | ||
| 50 | + } | ||
| 51 | + // 检查已领取数量是否超过限领数量 | ||
| 52 | + template.setTakeStatus(MapUtil.getInt(couponTakeCountMap, template.getId(), 0) >= template.getTakeLimitCount()); | ||
| 53 | + } | ||
| 54 | + return result; | ||
| 55 | + } | ||
| 56 | + | ||
| 29 | } | 57 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java
| @@ -110,7 +110,7 @@ public class RewardActivityDO extends BaseDO { | @@ -110,7 +110,7 @@ public class RewardActivityDO extends BaseDO { | ||
| 110 | */ | 110 | */ |
| 111 | private List<Long> couponIds; | 111 | private List<Long> couponIds; |
| 112 | /** | 112 | /** |
| 113 | - * 赠送的优惠卷数量的数组 | 113 | + * 赠送的优惠券数量的数组 |
| 114 | */ | 114 | */ |
| 115 | private List<Integer> couponCounts; | 115 | private List<Integer> couponCounts; |
| 116 | 116 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.bean.BeanUtil; | ||
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 7 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 10 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | ||
| 11 | +import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO; | ||
| 8 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 12 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 13 | +import com.github.yulichang.toolkit.MPJWrappers; | ||
| 9 | import org.apache.ibatis.annotations.Mapper; | 14 | import org.apache.ibatis.annotations.Mapper; |
| 10 | 15 | ||
| 16 | +import java.time.LocalDateTime; | ||
| 11 | import java.util.Collection; | 17 | import java.util.Collection; |
| 12 | import java.util.List; | 18 | import java.util.List; |
| 19 | +import java.util.function.Function; | ||
| 20 | +import java.util.stream.Collectors; | ||
| 13 | 21 | ||
| 14 | /** | 22 | /** |
| 15 | * 优惠劵 Mapper | 23 | * 优惠劵 Mapper |
| @@ -19,11 +27,11 @@ import java.util.List; | @@ -19,11 +27,11 @@ import java.util.List; | ||
| 19 | @Mapper | 27 | @Mapper |
| 20 | public interface CouponMapper extends BaseMapperX<CouponDO> { | 28 | public interface CouponMapper extends BaseMapperX<CouponDO> { |
| 21 | 29 | ||
| 22 | - default PageResult<CouponDO> selectPage(CouponPageReqVO reqVO, Collection<Long> userIds) { | 30 | + default PageResult<CouponDO> selectPage(CouponPageReqVO reqVO) { |
| 23 | return selectPage(reqVO, new LambdaQueryWrapperX<CouponDO>() | 31 | return selectPage(reqVO, new LambdaQueryWrapperX<CouponDO>() |
| 24 | .eqIfPresent(CouponDO::getTemplateId, reqVO.getTemplateId()) | 32 | .eqIfPresent(CouponDO::getTemplateId, reqVO.getTemplateId()) |
| 25 | .eqIfPresent(CouponDO::getStatus, reqVO.getStatus()) | 33 | .eqIfPresent(CouponDO::getStatus, reqVO.getStatus()) |
| 26 | - .inIfPresent(CouponDO::getUserId, userIds) | 34 | + .inIfPresent(CouponDO::getUserId, reqVO.getUserIds()) |
| 27 | .betweenIfPresent(CouponDO::getCreateTime, reqVO.getCreateTime()) | 35 | .betweenIfPresent(CouponDO::getCreateTime, reqVO.getCreateTime()) |
| 28 | .orderByDesc(CouponDO::getId)); | 36 | .orderByDesc(CouponDO::getId)); |
| 29 | } | 37 | } |
| @@ -62,4 +70,37 @@ public interface CouponMapper extends BaseMapperX<CouponDO> { | @@ -62,4 +70,37 @@ public interface CouponMapper extends BaseMapperX<CouponDO> { | ||
| 62 | ); | 70 | ); |
| 63 | } | 71 | } |
| 64 | 72 | ||
| 73 | + // TODO @疯狂:这个是不是搞个 Map 就可以呀? | ||
| 74 | + default List<CouponTakeCountBO> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) { | ||
| 75 | + return BeanUtil.copyToList(selectMaps(MPJWrappers.lambdaJoin(CouponDO.class) | ||
| 76 | + .select(CouponDO::getTemplateId) | ||
| 77 | + .selectCount(CouponDO::getId, CouponTakeCountBO::getCount) | ||
| 78 | + .eq(CouponDO::getUserId, userId) | ||
| 79 | + .in(CouponDO::getTemplateId, templateIds) | ||
| 80 | + .groupBy(CouponDO::getTemplateId)), CouponTakeCountBO.class); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope( | ||
| 84 | + Long userId, Integer status, Integer usePrice, List<Long> spuIds, List<Long> categoryIds) { | ||
| 85 | + Function<List<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream() | ||
| 86 | + .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) | ||
| 87 | + .collect(Collectors.joining(" OR ")); | ||
| 88 | + return selectList(new LambdaQueryWrapperX<CouponDO>() | ||
| 89 | + .eq(CouponDO::getUserId, userId) | ||
| 90 | + .eq(CouponDO::getStatus, status) | ||
| 91 | + .le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件 | ||
| 92 | + .and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部 | ||
| 93 | + .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品 | ||
| 94 | + .apply(productScopeValuesFindInSetFunc.apply(spuIds))) | ||
| 95 | + .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类 | ||
| 96 | + .apply(productScopeValuesFindInSetFunc.apply(categoryIds))))); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + default List<CouponDO> selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) { | ||
| 100 | + return selectList(new LambdaQueryWrapperX<CouponDO>() | ||
| 101 | + .eq(CouponDO::getStatus, status) | ||
| 102 | + .le(CouponDO::getValidEndTime, validEndTime) | ||
| 103 | + ); | ||
| 104 | + } | ||
| 105 | + | ||
| 65 | } | 106 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
| @@ -39,6 +39,9 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { | @@ -39,6 +39,9 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { | ||
| 39 | .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus()) | 39 | .eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus()) |
| 40 | .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType()) | 40 | .eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType()) |
| 41 | .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime()) | 41 | .betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime()) |
| 42 | + .eqIfPresent(CouponTemplateDO::getProductScope, reqVO.getProductScope()) | ||
| 43 | + .and(reqVO.getProductScopeValue() != null, w -> w.apply("FIND_IN_SET({0}, product_scope_values)", | ||
| 44 | + reqVO.getProductScopeValue())) | ||
| 42 | .and(canTakeConsumer != null, canTakeConsumer) | 45 | .and(canTakeConsumer != null, canTakeConsumer) |
| 43 | .orderByDesc(CouponTemplateDO::getId)); | 46 | .orderByDesc(CouponTemplateDO::getId)); |
| 44 | } | 47 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/job/coupon/CouponExpireJob.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.job.coupon; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; | ||
| 5 | +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; | ||
| 6 | +import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +// TODO 芋艿:配置一个 Job | ||
| 12 | +/** | ||
| 13 | + * 优惠券过期 Job | ||
| 14 | + * | ||
| 15 | + * @author owen | ||
| 16 | + */ | ||
| 17 | +@Component | ||
| 18 | +public class CouponExpireJob implements JobHandler { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private CouponService couponService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + @TenantJob | ||
| 25 | + public String execute(String param) { | ||
| 26 | + int count = couponService.expireCoupon(); | ||
| 27 | + return StrUtil.format("过期优惠券 {} 个", count); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/package-info.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/job/package-info.java