Merge remote-tracking branch 'origin/feature/mall_product' into feature/mall_product
This commit is contained in:
commit
929ff4286a
58
README.md
58
README.md
|
@ -15,6 +15,8 @@
|
||||||
* 启动文档:<https://doc.iocoder.cn/quick-start/>
|
* 启动文档:<https://doc.iocoder.cn/quick-start/>
|
||||||
* 视频教程:<https://doc.iocoder.cn/video/>
|
* 视频教程:<https://doc.iocoder.cn/video/>
|
||||||
|
|
||||||
|
已支持 Spring Boot 3.X + JDK 17 版本,可见 [master-boot3](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/README.md) 分支。
|
||||||
|
|
||||||
## 🐯 平台简介
|
## 🐯 平台简介
|
||||||
|
|
||||||
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
||||||
|
@ -62,18 +64,18 @@
|
||||||
| [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 |
|
| [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 |
|
||||||
| [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 |
|
| [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 |
|
||||||
| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 |
|
| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 |
|
||||||
| [yudao-ui-app](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-app) | 基于 uni-app + uview 实现的用户 App |
|
| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 |
|
||||||
|
|
||||||
## 🐰 分支说明
|
## 🐰 分支说明
|
||||||
|
|
||||||
| | JDK 8 完整版 | JDK 8 精简版 | JDK 17 完整版 |
|
| | JDK 8 完整版 | JDK 8 精简版 | JDK 17 完整版 |
|
||||||
|-------|-----------------------------------------------------------|--------------------------------------------------------------------|-----------------------------------------------------------------------------|
|
|-------|-----------------------------------------------------------|--------------------------------------------------------------------|-----------------------------------------------------------------------------|
|
||||||
| 分支 | [`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/) |
|
| 分支 | [`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/) |
|
||||||
| 说明 | 包括所有功能 | 只保留核心功能 | 适配 Spring Boot 3.X |
|
| 说明 | 包括所有功能 | 只保留核心功能 | 适配 Spring Boot 3.X |
|
||||||
| 系统功能 | √ | √ | √ |
|
| 系统功能 | √ | √ | √ |
|
||||||
| 基础设施 | √ | √ | √ |
|
| 基础设施 | √ | √ | √ |
|
||||||
| 会员中心 | √ | √ | √ |
|
| 会员中心 | √ | √ | √ |
|
||||||
| 工作流程 | √ | x | 适配中 |
|
| 工作流程 | √ | x | √ |
|
||||||
| 数据报表 | √ | x | 适配中 |
|
| 数据报表 | √ | x | 适配中 |
|
||||||
| 商城系统 | √ | x | √ |
|
| 商城系统 | √ | x | √ |
|
||||||
| 微信公众号 | √ | x | √ |
|
| 微信公众号 | √ | x | √ |
|
||||||
|
@ -218,6 +220,10 @@
|
||||||
|
|
||||||
![功能图](/.image/common/mall-preview.png)
|
![功能图](/.image/common/mall-preview.png)
|
||||||
|
|
||||||
|
_前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋道快速开发平台_
|
||||||
|
|
||||||
|
演示地址:<https://doc.iocoder.cn/mall-preview/>
|
||||||
|
|
||||||
### 会员中心
|
### 会员中心
|
||||||
|
|
||||||
| | 功能 | 描述 |
|
| | 功能 | 描述 |
|
||||||
|
@ -248,29 +254,29 @@
|
||||||
|
|
||||||
### 框架
|
### 框架
|
||||||
|
|
||||||
| 框架 | 说明 | 版本 | 学习指南 |
|
| 框架 | 说明 | 版本 | 学习指南 |
|
||||||
|---------------------------------------------------------------------------------------------|------------------|-------------|----------------------------------------------------------------|
|
|---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------|
|
||||||
| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.14 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.16 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
||||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.18 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.19 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||||
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
||||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||||
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
|
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 /7.0 | |
|
||||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.6 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.11 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||||
| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
|
| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
|
||||||
| [Springdoc](https://springdoc.org/) | Swagger 文档 | 1.6.15 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
| [Springdoc](https://springdoc.org/) | Swagger 文档 | 1.6.15 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||||
| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
|
| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
|
||||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
|
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
|
||||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.5.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.5.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.28 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.30 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
||||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
||||||
|
|
||||||
## 🐷 演示图
|
## 🐷 演示图
|
||||||
|
|
||||||
|
|
6
pom.xml
6
pom.xml
|
@ -30,7 +30,7 @@
|
||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>1.8.1-snapshot</revision>
|
<revision>1.8.2-snapshot</revision>
|
||||||
<!-- Maven 相关 -->
|
<!-- Maven 相关 -->
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
@ -39,8 +39,8 @@
|
||||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||||
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
|
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
|
||||||
<!-- 看看咋放到 bom 里 -->
|
<!-- 看看咋放到 bom 里 -->
|
||||||
<lombok.version>1.18.28</lombok.version>
|
<lombok.version>1.18.30</lombok.version>
|
||||||
<spring.boot.version>2.7.14</spring.boot.version>
|
<spring.boot.version>2.7.16</spring.boot.version>
|
||||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -1,241 +0,0 @@
|
||||||
-- 增加配置表
|
|
||||||
CREATE TABLE trade_config
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT COMMENT '自增主键' PRIMARY KEY,
|
|
||||||
brokerage_enabled BIT DEFAULT 1 NOT NULL COMMENT '是否启用分佣',
|
|
||||||
brokerage_enabled_condition TINYINT DEFAULT 1 NOT NULL COMMENT '分佣模式:1-人人分销 2-指定分销',
|
|
||||||
brokerage_bind_mode TINYINT DEFAULT 1 NOT NULL COMMENT '分销关系绑定模式: 1-没有推广人,2-新用户, 3-扫码覆盖',
|
|
||||||
brokerage_poster_urls VARCHAR(2000) DEFAULT '' NULL COMMENT '分销海报图地址数组',
|
|
||||||
brokerage_first_percent INT DEFAULT 0 NOT NULL COMMENT '一级返佣比例',
|
|
||||||
brokerage_second_percent INT DEFAULT 0 NOT NULL COMMENT '二级返佣比例',
|
|
||||||
brokerage_withdraw_min_price INT DEFAULT 0 NOT NULL COMMENT '用户提现最低金额',
|
|
||||||
brokerage_withdraw_fee_percent INT DEFAULT 0 NOT NULL COMMENT '提现手续费百分比',
|
|
||||||
brokerage_bank_names VARCHAR(200) DEFAULT '' NOT NULL COMMENT '提现银行(字典类型=brokerage_bank_name)',
|
|
||||||
brokerage_frozen_days INT DEFAULT 7 NOT NULL COMMENT '佣金冻结时间(天)',
|
|
||||||
brokerage_withdraw_types VARCHAR(32) DEFAULT '1,2,3,4' NOT NULL COMMENT '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝',
|
|
||||||
creator VARCHAR(64) DEFAULT '' NULL COMMENT '创建者',
|
|
||||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间',
|
|
||||||
updater VARCHAR(64) DEFAULT '' NULL COMMENT '更新者',
|
|
||||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
||||||
deleted BIT DEFAULT b'0' NOT NULL COMMENT '是否删除',
|
|
||||||
tenant_id BIGINT DEFAULT 0 NOT NULL COMMENT '租户编号'
|
|
||||||
) COMMENT '交易中心配置';
|
|
||||||
|
|
||||||
# alter table trade_config
|
|
||||||
# add brokerage_withdraw_fee_percent int default 0 not null comment '提现手续费百分比' after brokerage_withdraw_min_price;
|
|
||||||
|
|
||||||
# alter table trade_brokerage_user
|
|
||||||
# add level int not null default 1 comment '等级' after frozen_price;
|
|
||||||
# alter table trade_brokerage_user
|
|
||||||
# add path varchar(2000) null comment '路径' after level;
|
|
||||||
|
|
||||||
|
|
||||||
-- 增加分销用户扩展表
|
|
||||||
create table trade_brokerage_user
|
|
||||||
(
|
|
||||||
id bigint auto_increment comment '用户编号' primary key,
|
|
||||||
bind_user_id bigint null comment '推广员编号',
|
|
||||||
bind_user_time datetime null comment '推广员绑定时间',
|
|
||||||
brokerage_enabled bit default 1 not null comment '是否成为推广员',
|
|
||||||
brokerage_time datetime null comment '成为分销员时间',
|
|
||||||
price int default 0 not null comment '可用佣金',
|
|
||||||
frozen_price int default 0 not null comment '冻结佣金',
|
|
||||||
creator varchar(64) default '' null comment '创建者',
|
|
||||||
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
|
|
||||||
updater varchar(64) default '' null comment '更新者',
|
|
||||||
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
|
|
||||||
deleted bit default b'0' not null comment '是否删除',
|
|
||||||
tenant_id bigint default 0 not null comment '租户编号'
|
|
||||||
)
|
|
||||||
comment '分销用户';
|
|
||||||
|
|
||||||
create index idx_invite_user_id on trade_brokerage_user (bind_user_id) comment '推广员编号';
|
|
||||||
create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是否成为推广员';
|
|
||||||
|
|
||||||
|
|
||||||
create table trade_brokerage_record
|
|
||||||
(
|
|
||||||
id int auto_increment comment '编号'
|
|
||||||
primary key,
|
|
||||||
user_id bigint not null comment '用户编号',
|
|
||||||
biz_id varchar(64) default '' not null comment '业务编号',
|
|
||||||
biz_type tinyint default 0 not null comment '业务类型:1-订单,2-提现',
|
|
||||||
title varchar(64) default '' not null comment '标题',
|
|
||||||
price int default 0 not null comment '金额',
|
|
||||||
total_price int default 0 not null comment '当前总佣金',
|
|
||||||
description varchar(500) default '' not null comment '说明',
|
|
||||||
status tinyint default 0 not null comment '状态:0-待结算,1-已结算,2-已取消',
|
|
||||||
frozen_days int default 0 not null comment '冻结时间(天)',
|
|
||||||
unfreeze_time datetime null comment '解冻时间',
|
|
||||||
source_user_level int not null comment '来源用户等级',
|
|
||||||
source_user_id bigint not null comment '来源用户编号',
|
|
||||||
creator varchar(64) default '' null comment '创建者',
|
|
||||||
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
|
|
||||||
updater varchar(64) default '' null comment '更新者',
|
|
||||||
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
|
|
||||||
deleted bit default b'0' not null comment '是否删除',
|
|
||||||
tenant_id bigint default 0 not null comment '租户编号'
|
|
||||||
)
|
|
||||||
comment '佣金记录';
|
|
||||||
|
|
||||||
create index idx_user_id on trade_brokerage_record (user_id) comment '用户编号';
|
|
||||||
create index idx_biz on trade_brokerage_record (biz_type, biz_id) comment '业务';
|
|
||||||
create index idx_status on trade_brokerage_record (status) comment '状态';
|
|
||||||
|
|
||||||
|
|
||||||
create table trade_brokerage_withdraw
|
|
||||||
(
|
|
||||||
id bigint auto_increment comment '编号'
|
|
||||||
primary key,
|
|
||||||
user_id bigint not null comment '用户编号',
|
|
||||||
price int default 0 not null comment '提现金额',
|
|
||||||
fee_price int default 0 not null comment '提现手续费',
|
|
||||||
total_price int default 0 not null comment '当前总佣金',
|
|
||||||
type tinyint default 0 not null comment '提现类型:1-钱包;2-银行卡;3-微信;4-支付宝',
|
|
||||||
name varchar(64) null comment '真实姓名',
|
|
||||||
account_no varchar(64) null comment '账号',
|
|
||||||
bank_name varchar(100) null comment '银行名称',
|
|
||||||
bank_address varchar(200) null comment '开户地址',
|
|
||||||
account_qr_code_url varchar(512) null comment '收款码',
|
|
||||||
status tinyint(2) default 0 not null comment '状态:0-审核中,10-审核通过 20-审核不通过;预留:11 - 提现成功;21-提现失败',
|
|
||||||
audit_reason varchar(128) null comment '审核驳回原因',
|
|
||||||
audit_time datetime null comment '审核时间',
|
|
||||||
remark varchar(500) null comment '备注',
|
|
||||||
creator varchar(64) default '' null comment '创建者',
|
|
||||||
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
|
|
||||||
updater varchar(64) default '' null comment '更新者',
|
|
||||||
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
|
|
||||||
deleted bit default b'0' not null comment '是否删除',
|
|
||||||
tenant_id bigint default 0 not null comment '租户编号'
|
|
||||||
)
|
|
||||||
comment '佣金提现';
|
|
||||||
|
|
||||||
create index idx_user_id on trade_brokerage_withdraw (user_id) comment '用户编号';
|
|
||||||
create index idx_audit_status on trade_brokerage_withdraw (status) comment '状态';
|
|
||||||
|
|
||||||
-- 增加字典
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_enabled_condition', '分佣模式');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort, remark)
|
|
||||||
values ('brokerage_enabled_condition', '人人分销', 1, 1, '所有用户都可以分销'),
|
|
||||||
('brokerage_enabled_condition', '指定分销', 2, 2, '仅可后台手动设置推广员');
|
|
||||||
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_bind_mode', '分销关系绑定模式');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort, remark)
|
|
||||||
values ('brokerage_bind_mode', '没有推广人', 1, 1, '只要用户没有推广人,随时都可以绑定推广关系'),
|
|
||||||
('brokerage_bind_mode', '新用户', 2, 2, '仅新用户注册时才能绑定推广关系'),
|
|
||||||
('brokerage_bind_mode', '扫码覆盖', 3, 3, '如果用户已经有推广人,推广人会被变更');
|
|
||||||
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_withdraw_type', '佣金提现类型');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort)
|
|
||||||
values ('brokerage_withdraw_type', '钱包', 1, 1),
|
|
||||||
('brokerage_withdraw_type', '银行卡', 2, 2),
|
|
||||||
('brokerage_withdraw_type', '微信', 3, 3),
|
|
||||||
('brokerage_withdraw_type', '支付宝', 4, 4);
|
|
||||||
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_record_biz_type', '佣金记录业务类型');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort)
|
|
||||||
values ('brokerage_record_biz_type', '订单返佣', 1, 1),
|
|
||||||
('brokerage_record_biz_type', '申请提现', 2, 2),
|
|
||||||
('brokerage_record_biz_type', '申请提现驳回', 3, 3);
|
|
||||||
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_record_status', '佣金记录状态');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort)
|
|
||||||
values ('brokerage_record_status', '待结算', 0, 0),
|
|
||||||
('brokerage_record_status', '已结算', 1, 1),
|
|
||||||
('brokerage_record_status', '已取消', 2, 2);
|
|
||||||
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_withdraw_status', '佣金提现状态');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort, color_type)
|
|
||||||
values ('brokerage_withdraw_status', '审核中', 0, 0, ''),
|
|
||||||
('brokerage_withdraw_status', '审核通过', 10, 10, 'success'),
|
|
||||||
('brokerage_withdraw_status', '提现成功', 11, 11, 'success'),
|
|
||||||
('brokerage_withdraw_status', '审核不通过', 20, 20, 'danger'),
|
|
||||||
('brokerage_withdraw_status', '提现失败', 21, 21, 'danger');
|
|
||||||
|
|
||||||
insert into system_dict_type(type, name)
|
|
||||||
values ('brokerage_bank_name', '佣金提现银行');
|
|
||||||
insert into system_dict_data(dict_type, label, value, sort)
|
|
||||||
values ('brokerage_bank_name', '工商银行', 0, 0),
|
|
||||||
('brokerage_bank_name', '建设银行', 1, 1),
|
|
||||||
('brokerage_bank_name', '农业银行', 2, 2),
|
|
||||||
('brokerage_bank_name', '中国银行', 3, 3),
|
|
||||||
('brokerage_bank_name', '交通银行', 4, 4),
|
|
||||||
('brokerage_bank_name', '招商银行', 5, 5);
|
|
||||||
|
|
||||||
|
|
||||||
-- 交易中心配置:菜单 SQL
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name)
|
|
||||||
VALUES ('交易中心配置', '', 2, 0, 2072, 'config', 'ep:setting', 'trade/config/index', 0, 'TradeConfig');
|
|
||||||
-- 按钮父菜单ID
|
|
||||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
|
||||||
SELECT @parentId := LAST_INSERT_ID();
|
|
||||||
-- 按钮 SQL
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('交易中心配置查询', 'trade:config:query', 3, 1, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('交易中心配置保存', 'trade:config:save', 3, 2, @parentId, '', '', '', 0);
|
|
||||||
|
|
||||||
|
|
||||||
-- 增加菜单:分销
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name)
|
|
||||||
VALUES ('分销', '', 1, 5, 2072, 'brokerage', 'fa-solid:project-diagram', '', 0, '');
|
|
||||||
-- 按钮父菜单ID
|
|
||||||
SELECT @brokerageMenuId := LAST_INSERT_ID();
|
|
||||||
|
|
||||||
-- 增加菜单:分销员
|
|
||||||
-- 菜单 SQL
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name)
|
|
||||||
VALUES ('分销用户', '', 2, 0, @brokerageMenuId, 'brokerage-user', 'fa-solid:user-tie', 'trade/brokerage/user/index', 0,
|
|
||||||
'TradeBrokerageUser');
|
|
||||||
-- 按钮父菜单ID
|
|
||||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
|
||||||
SELECT @parentId := LAST_INSERT_ID();
|
|
||||||
-- 按钮 SQL
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('分销用户查询', 'trade:brokerage-user:query', 3, 1, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('分销用户推广人查询', 'trade:brokerage-user:user-query', 3, 2, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('分销用户推广订单查询', 'trade:brokerage-user:order-query', 3, 3, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-bind-user', 3, 5, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-bind-user', 3, 6, @parentId, '', '', '', 0);
|
|
||||||
|
|
||||||
-- 增加菜单:佣金记录
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name)
|
|
||||||
VALUES ('佣金记录', '', 2, 1, @brokerageMenuId, 'brokerage-record', 'fa:money', 'trade/brokerage/record/index', 0,
|
|
||||||
'TradeBrokerageRecord');
|
|
||||||
-- 按钮父菜单ID
|
|
||||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
|
||||||
SELECT @parentId := LAST_INSERT_ID();
|
|
||||||
-- 按钮 SQL
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('佣金记录查询', 'trade:brokerage-record:query', 3, 1, @parentId, '', '', '', 0);
|
|
||||||
|
|
||||||
-- 增加菜单:佣金提现
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name)
|
|
||||||
VALUES ('佣金提现', '', 2, 2, @brokerageMenuId, 'brokerage-withdraw', 'fa:credit-card',
|
|
||||||
'trade/brokerage/withdraw/index', 0, 'TradeBrokerageWithdraw');
|
|
||||||
-- 按钮父菜单ID
|
|
||||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
|
||||||
SELECT @parentId := LAST_INSERT_ID();
|
|
||||||
-- 按钮 SQL
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('佣金提现查询', 'trade:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0);
|
|
||||||
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
|
|
||||||
VALUES ('佣金提现审核', 'trade:brokerage-withdraw:audit', 3, 2, @parentId, '', '', '', 0);
|
|
||||||
|
|
||||||
-- 站内信模板
|
|
||||||
INSERT INTO `ruoyi-vue-pro`.system_notify_template (name, code, nickname, content, type, params, status)
|
|
||||||
VALUES
|
|
||||||
('佣金提现(审核通过)', 'brokerage_withdraw_audit_approve', 'system', '您在{createTime}提现¥{price}元的申请已通过审核', 2, '["createTime","price"]', 0),
|
|
||||||
('佣金提现(审核不通过)', 'brokerage_withdraw_audit_reject', 'system', '您在{createTime}提现¥{price}元的申请未通过审核,原因:{reason}', 2, '["createTime","price","reason"]', 0);
|
|
|
@ -1,3 +0,0 @@
|
||||||
ALTER TABLE `ruoyi-vue-pro`.`trade_after_sale_log`
|
|
||||||
ADD COLUMN `before_status` int NOT NULL COMMENT '售前状态' AFTER `id`,
|
|
||||||
ADD COLUMN `after_status` int NOT NULL COMMENT '售后状态' AFTER `before_status`;
|
|
|
@ -73,3 +73,81 @@ CREATE TABLE `pay_wallet_recharge`
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB COMMENT='会员钱包充值';
|
) ENGINE=InnoDB COMMENT='会员钱包充值';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- 转账单表
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `pay_transfer`;
|
||||||
|
CREATE TABLE `pay_transfer`
|
||||||
|
(
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||||
|
`type` int NOT NULL COMMENT '类型',
|
||||||
|
`app_id` bigint NOT NULL COMMENT '应用编号',
|
||||||
|
`merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号',
|
||||||
|
`price` int NOT NULL COMMENT '转账金额,单位:分',
|
||||||
|
`title` varchar(512) NOT NULL COMMENT '转账标题',
|
||||||
|
`payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同',
|
||||||
|
`status` tinyint NOT NULL COMMENT '转账状态',
|
||||||
|
`success_time` datetime NULL COMMENT '转账成功时间',
|
||||||
|
`extension_id` bigint NULL COMMENT '转账渠道编号',
|
||||||
|
`no` varchar(64) NULL COMMENT '转账单号',
|
||||||
|
`channel_id` bigint NULL COMMENT '转账渠道编号',
|
||||||
|
`channel_code` varchar(32) NULL COMMENT '转账渠道编码',
|
||||||
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB COMMENT='转账单表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- 转账扩展单
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `pay_transfer_extension`;
|
||||||
|
CREATE TABLE `pay_transfer_extension`
|
||||||
|
(
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||||
|
`no` varchar(64) NOT NULL COMMENT '转账单号',
|
||||||
|
`transfer_id` bigint NOT NULL COMMENT '转账单编号',
|
||||||
|
`channel_id` bigint NOT NULL COMMENT '转账渠道编号',
|
||||||
|
`channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码',
|
||||||
|
`channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '支付渠道的额外参数',
|
||||||
|
`status` tinyint NOT NULL COMMENT '转账状态',
|
||||||
|
`channel_notify_data` varchar(4096) NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容',
|
||||||
|
`creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB COMMENT='转账拓展单表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for pay_demo_transfer
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `pay_demo_transfer`;
|
||||||
|
CREATE TABLE `pay_demo_transfer` (
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号',
|
||||||
|
`user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号',
|
||||||
|
`price` int NOT NULL COMMENT '转账金额,单位:分',
|
||||||
|
`type` int NOT NULL COMMENT '转账类型',
|
||||||
|
`payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同',
|
||||||
|
`transfer_status` tinyint NOT NULL DEFAULT 0 COMMENT '转账状态',
|
||||||
|
`pay_transfer_id` bigint NULL DEFAULT NULL COMMENT '转账订单编号',
|
||||||
|
`pay_channel_code` varchar(16) NULL DEFAULT NULL COMMENT '转账支付成功渠道',
|
||||||
|
`transfer_time` datetime NULL DEFAULT NULL COMMENT '转账支付时间',
|
||||||
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '更新者',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB COMMENT = '示例业务转账订单\n';
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE `pay_channel`
|
||||||
|
MODIFY COLUMN `config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置' AFTER `app_id`;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
ALTER TABLE trade_order ADD COLUMN use_point int NOT NULL DEFAULT 0 COMMENT '使用的积分' AFTER point_price;
|
|
||||||
ALTER TABLE trade_order ADD COLUMN refund_point int NOT NULL DEFAULT 0 COMMENT '退还的使用积分' AFTER use_point;
|
|
||||||
ALTER TABLE trade_order ADD COLUMN give_point int NOT NULL DEFAULT 0 COMMENT '赠送的积分' AFTER refund_point;
|
|
||||||
|
|
||||||
ALTER TABLE trade_order_item ADD COLUMN use_point int NOT NULL DEFAULT 0 COMMENT '使用的积分' AFTER point_price;
|
|
||||||
ALTER TABLE trade_order_item ADD COLUMN give_point int NOT NULL DEFAULT 0 COMMENT '赠送的积分' AFTER use_point;
|
|
|
@ -11,7 +11,7 @@
|
||||||
Target Server Version : 80034
|
Target Server Version : 80034
|
||||||
File Encoding : 65001
|
File Encoding : 65001
|
||||||
|
|
||||||
Date: 03/09/2023 19:13:55
|
Date: 24/09/2023 23:23:06
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SET NAMES utf8mb4;
|
SET NAMES utf8mb4;
|
||||||
|
@ -72,6 +72,7 @@ CREATE TABLE `QRTZ_CRON_TRIGGERS` (
|
||||||
-- Records of QRTZ_CRON_TRIGGERS
|
-- Records of QRTZ_CRON_TRIGGERS
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
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');
|
||||||
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
|
INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
|
||||||
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');
|
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');
|
||||||
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');
|
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` (
|
||||||
-- Records of QRTZ_JOB_DETAILS
|
-- Records of QRTZ_JOB_DETAILS
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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` (
|
||||||
-- Records of QRTZ_SCHEDULER_STATE
|
-- Records of QRTZ_SCHEDULER_STATE
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai1690117495401', 1690119854263, 15000);
|
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'Yunai.local1694844151505', 1694844218609, 15000);
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
@ -285,6 +287,7 @@ CREATE TABLE `QRTZ_TRIGGERS` (
|
||||||
-- Records of QRTZ_TRIGGERS
|
-- Records of QRTZ_TRIGGERS
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 1497 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
) ENGINE = InnoDB AUTO_INCREMENT = 1544 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of infra_api_error_log
|
-- Records of infra_api_error_log
|
||||||
|
@ -398,7 +401,7 @@ CREATE TABLE `infra_codegen_column` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 1756 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
) ENGINE = InnoDB AUTO_INCREMENT = 1755 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of infra_codegen_column
|
-- Records of infra_codegen_column
|
||||||
|
@ -514,7 +517,7 @@ CREATE TABLE `infra_file` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 1054 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 1055 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of infra_file
|
-- Records of infra_file
|
||||||
|
@ -545,12 +548,7 @@ CREATE TABLE `infra_file_config` (
|
||||||
-- Records of infra_file_config
|
-- Records of infra_file_config
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
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');
|
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');
|
||||||
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');
|
|
||||||
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');
|
|
||||||
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');
|
|
||||||
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');
|
|
||||||
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');
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
@ -568,7 +566,7 @@ CREATE TABLE `infra_file_content` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 145 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 149 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of infra_file_content
|
-- Records of infra_file_content
|
||||||
|
@ -596,17 +594,17 @@ CREATE TABLE `infra_job` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of infra_job
|
-- Records of infra_job
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
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');
|
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');
|
||||||
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');
|
|
||||||
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');
|
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');
|
||||||
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');
|
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');
|
||||||
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');
|
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');
|
||||||
|
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');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
@ -630,7 +628,7 @@ CREATE TABLE `infra_job_log` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 161 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 163 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of infra_job_log
|
-- Records of infra_job_log
|
||||||
|
@ -803,7 +801,7 @@ CREATE TABLE `member_level_record` (
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员等级记录-用户编号'
|
INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员等级记录-用户编号'
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录';
|
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of member_level_record
|
-- Records of member_level_record
|
||||||
|
@ -828,7 +826,7 @@ CREATE TABLE `member_point_config` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '会员积分配置表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员积分配置表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of member_point_config
|
-- Records of member_point_config
|
||||||
|
@ -844,10 +842,10 @@ DROP TABLE IF EXISTS `member_point_record`;
|
||||||
CREATE TABLE `member_point_record` (
|
CREATE TABLE `member_point_record` (
|
||||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
|
||||||
`user_id` bigint NOT NULL COMMENT '用户编号',
|
`user_id` bigint NOT NULL COMMENT '用户编号',
|
||||||
`biz_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '业务编码',
|
`biz_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '业务编码',
|
||||||
`biz_type` tinyint NOT NULL COMMENT '业务类型',
|
`biz_type` tinyint NOT NULL COMMENT '业务类型',
|
||||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '积分标题',
|
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '积分标题',
|
||||||
`description` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '积分描述',
|
`description` varchar(5000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '积分描述',
|
||||||
`point` int NOT NULL COMMENT '积分',
|
`point` int NOT NULL COMMENT '积分',
|
||||||
`total_point` int NOT NULL COMMENT '变动后的积分',
|
`total_point` int NOT NULL COMMENT '变动后的积分',
|
||||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||||
|
@ -859,7 +857,7 @@ CREATE TABLE `member_point_record` (
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
INDEX `index_userId`(`user_id` ASC) USING BTREE,
|
INDEX `index_userId`(`user_id` ASC) USING BTREE,
|
||||||
INDEX `index_title`(`title` ASC) USING BTREE
|
INDEX `index_title`(`title` ASC) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户积分记录';
|
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户积分记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of member_point_record
|
-- Records of member_point_record
|
||||||
|
@ -872,6 +870,15 @@ INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
@ -890,7 +897,7 @@ CREATE TABLE `member_sign_in_config` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '签到规则';
|
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '签到规则';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of member_sign_in_config
|
-- Records of member_sign_in_config
|
||||||
|
@ -919,20 +926,23 @@ CREATE TABLE `member_sign_in_record` (
|
||||||
`user_id` int NULL DEFAULT NULL COMMENT '签到用户',
|
`user_id` int NULL DEFAULT NULL COMMENT '签到用户',
|
||||||
`day` int NULL DEFAULT NULL COMMENT '第几天签到',
|
`day` int NULL DEFAULT NULL COMMENT '第几天签到',
|
||||||
`point` int NULL DEFAULT NULL COMMENT '签到的分数',
|
`point` int NULL DEFAULT NULL COMMENT '签到的分数',
|
||||||
`create_time` datetime NULL DEFAULT NULL COMMENT '签到时间',
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||||
`update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '变更时间',
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
`tenant_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '租户id',
|
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||||
`deleted` int NULL DEFAULT 0 COMMENT '是否删除',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新人',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '签到记录';
|
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '签到记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of member_sign_in_record
|
-- Records of member_sign_in_record
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
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');
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
@ -972,7 +982,7 @@ CREATE TABLE `member_user` (
|
||||||
`login_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '最后登录IP',
|
`login_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '最后登录IP',
|
||||||
`login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间',
|
`login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间',
|
||||||
`nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
|
`nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
|
||||||
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像',
|
`avatar` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像',
|
||||||
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '真实名字',
|
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '真实名字',
|
||||||
`sex` tinyint NULL DEFAULT 0 COMMENT '用户性别',
|
`sex` tinyint NULL DEFAULT 0 COMMENT '用户性别',
|
||||||
`area_id` bigint NULL DEFAULT NULL COMMENT '所在地',
|
`area_id` bigint NULL DEFAULT NULL COMMENT '所在地',
|
||||||
|
@ -989,9 +999,8 @@ CREATE TABLE `member_user` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
UNIQUE INDEX `uk_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
) ENGINE = InnoDB AUTO_INCREMENT = 249 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员用户';
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员用户';
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of member_user
|
-- Records of member_user
|
||||||
|
@ -1305,7 +1314,7 @@ CREATE TABLE `system_dict_type` (
|
||||||
`deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
`deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
|
UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 176 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 175 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_dict_type
|
-- Records of system_dict_type
|
||||||
|
@ -1389,7 +1398,7 @@ CREATE TABLE `system_error_code` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 5933 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 5932 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_error_code
|
-- Records of system_error_code
|
||||||
|
@ -1418,7 +1427,7 @@ CREATE TABLE `system_login_log` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 2375 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
) ENGINE = InnoDB AUTO_INCREMENT = 2482 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_login_log
|
-- Records of system_login_log
|
||||||
|
@ -1483,7 +1492,7 @@ CREATE TABLE `system_mail_log` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 354 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 355 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_mail_log
|
-- Records of system_mail_log
|
||||||
|
@ -2116,7 +2125,7 @@ CREATE TABLE `system_oauth2_access_token` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 2597 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
) ENGINE = InnoDB AUTO_INCREMENT = 2721 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_oauth2_access_token
|
-- Records of system_oauth2_access_token
|
||||||
|
@ -2238,7 +2247,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 896 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
) ENGINE = InnoDB AUTO_INCREMENT = 991 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_oauth2_refresh_token
|
-- Records of system_oauth2_refresh_token
|
||||||
|
@ -2278,7 +2287,7 @@ CREATE TABLE `system_operate_log` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 8321 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
|
) ENGINE = InnoDB AUTO_INCREMENT = 8338 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_operate_log
|
-- Records of system_operate_log
|
||||||
|
@ -3286,7 +3295,7 @@ CREATE TABLE `system_sms_code` (
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 501 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
) ENGINE = InnoDB AUTO_INCREMENT = 513 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_sms_code
|
-- Records of system_sms_code
|
||||||
|
@ -3329,7 +3338,7 @@ CREATE TABLE `system_sms_log` (
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 365 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
) ENGINE = InnoDB AUTO_INCREMENT = 381 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_sms_log
|
-- Records of system_sms_log
|
||||||
|
@ -3401,7 +3410,7 @@ CREATE TABLE `system_social_user` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_social_user
|
-- Records of system_social_user
|
||||||
|
@ -3426,7 +3435,7 @@ CREATE TABLE `system_social_user_bind` (
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
) ENGINE = InnoDB AUTO_INCREMENT = 76 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of system_social_user_bind
|
-- Records of system_social_user_bind
|
||||||
|
@ -3462,8 +3471,8 @@ CREATE TABLE `system_tenant` (
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
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');
|
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');
|
||||||
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');
|
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');
|
||||||
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');
|
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');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
|
@ -3602,10 +3611,10 @@ CREATE TABLE `system_users` (
|
||||||
-- Records of system_users
|
-- Records of system_users
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
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);
|
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);
|
||||||
|
|
|
@ -5815,8 +5815,7 @@ GO
|
||||||
|
|
||||||
CREATE TABLE [dbo].[system_dict_type]
|
CREATE TABLE [dbo].[system_dict_type]
|
||||||
(
|
(
|
||||||
[
|
[id]
|
||||||
id]
|
|
||||||
bigint
|
bigint
|
||||||
IDENTITY
|
IDENTITY
|
||||||
(
|
(
|
||||||
|
|
|
@ -14,16 +14,16 @@
|
||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>1.8.1-snapshot</revision>
|
<revision>1.8.2-snapshot</revision>
|
||||||
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
|
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
|
||||||
<!-- 统一依赖管理 -->
|
<!-- 统一依赖管理 -->
|
||||||
<spring.boot.version>2.7.14</spring.boot.version>
|
<spring.boot.version>2.7.16</spring.boot.version>
|
||||||
<!-- Web 相关 -->
|
<!-- Web 相关 -->
|
||||||
<springdoc.version>1.6.15</springdoc.version>
|
<springdoc.version>1.7.0</springdoc.version>
|
||||||
<knife4j.version>4.1.0</knife4j.version>
|
<knife4j.version>4.3.0</knife4j.version>
|
||||||
<servlet.versoin>2.5</servlet.versoin>
|
<servlet.versoin>2.5</servlet.versoin>
|
||||||
<!-- DB 相关 -->
|
<!-- DB 相关 -->
|
||||||
<druid.version>1.2.18</druid.version>
|
<druid.version>1.2.19</druid.version>
|
||||||
<mybatis-plus.version>3.5.3.2</mybatis-plus.version>
|
<mybatis-plus.version>3.5.3.2</mybatis-plus.version>
|
||||||
<mybatis-plus-generator.version>3.5.3.2</mybatis-plus-generator.version>
|
<mybatis-plus-generator.version>3.5.3.2</mybatis-plus-generator.version>
|
||||||
<dynamic-datasource.version>3.6.1</dynamic-datasource.version>
|
<dynamic-datasource.version>3.6.1</dynamic-datasource.version>
|
||||||
|
@ -44,33 +44,32 @@
|
||||||
<!-- Bpm 工作流相关 -->
|
<!-- Bpm 工作流相关 -->
|
||||||
<flowable.version>6.8.0</flowable.version>
|
<flowable.version>6.8.0</flowable.version>
|
||||||
<!-- 工具类相关 -->
|
<!-- 工具类相关 -->
|
||||||
<captcha-plus.version>1.0.6</captcha-plus.version>
|
<captcha-plus.version>1.0.8</captcha-plus.version>
|
||||||
<jsoup.version>1.15.4</jsoup.version>
|
<jsoup.version>1.16.1</jsoup.version>
|
||||||
<lombok.version>1.18.28</lombok.version>
|
<lombok.version>1.18.30</lombok.version>
|
||||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||||
<hutool.version>5.8.20</hutool.version>
|
<hutool.version>5.8.22</hutool.version>
|
||||||
<easyexcel.verion>3.3.2</easyexcel.verion>
|
<easyexcel.verion>3.3.2</easyexcel.verion>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<screw.version>1.0.5</screw.version>
|
<screw.version>1.0.5</screw.version>
|
||||||
<fastjson.version>1.2.83</fastjson.version>
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
<guava.version>32.0.1-jre</guava.version>
|
<guava.version>32.1.2-jre</guava.version>
|
||||||
<guice.version>5.1.0</guice.version>
|
<guice.version>5.1.0</guice.version>
|
||||||
<transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
|
<transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
|
||||||
<commons-net.version>3.9.0</commons-net.version>
|
<commons-net.version>3.9.0</commons-net.version>
|
||||||
<jsch.version>0.1.55</jsch.version>
|
<jsch.version>0.1.55</jsch.version>
|
||||||
<tika-core.version>2.7.0</tika-core.version>
|
<tika-core.version>2.7.0</tika-core.version>
|
||||||
<netty-all.version>4.1.90.Final</netty-all.version>
|
|
||||||
<ip2region.version>2.7.0</ip2region.version>
|
<ip2region.version>2.7.0</ip2region.version>
|
||||||
<!-- 三方云服务相关 -->
|
<!-- 三方云服务相关 -->
|
||||||
<okio.version>3.0.0</okio.version>
|
<okio.version>3.5.0</okio.version>
|
||||||
<okhttp3.version>4.10.0</okhttp3.version>
|
<okhttp3.version>4.11.0</okhttp3.version>
|
||||||
<commons-io.version>2.11.0</commons-io.version>
|
<commons-io.version>2.11.0</commons-io.version>
|
||||||
<minio.version>8.5.4</minio.version>
|
<minio.version>8.5.6</minio.version>
|
||||||
<aliyun-java-sdk-core.version>4.6.3</aliyun-java-sdk-core.version>
|
<aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version>
|
||||||
<aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
|
<aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
|
||||||
<tencentcloud-sdk-java.version>3.1.758</tencentcloud-sdk-java.version>
|
<tencentcloud-sdk-java.version>3.1.853</tencentcloud-sdk-java.version>
|
||||||
<justauth.version>1.0.3</justauth.version>
|
<justauth.version>1.0.5</justauth.version>
|
||||||
<jimureport.version>1.5.8</jimureport.version>
|
<jimureport.version>1.6.1</jimureport.version>
|
||||||
<xercesImpl.version>2.12.2</xercesImpl.version>
|
<xercesImpl.version>2.12.2</xercesImpl.version>
|
||||||
<weixin-java.version>4.5.0</weixin-java.version>
|
<weixin-java.version>4.5.0</weixin-java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -233,6 +232,12 @@
|
||||||
<groupId>org.redisson</groupId>
|
<groupId>org.redisson</groupId>
|
||||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
<version>${redisson.version}</version>
|
<version>${redisson.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -337,6 +342,12 @@
|
||||||
<groupId>de.codecentric</groupId>
|
<groupId>de.codecentric</groupId>
|
||||||
<artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
|
<artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
|
||||||
<version>${spring-boot-admin.version}</version>
|
<version>${spring-boot-admin.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>de.codecentric</groupId>
|
||||||
|
<artifactId>spring-boot-admin-server-cloud</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.codecentric</groupId>
|
<groupId>de.codecentric</groupId>
|
||||||
|
@ -519,12 +530,6 @@
|
||||||
<version>${jsch.version}</version>
|
<version>${jsch.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-all</artifactId>
|
|
||||||
<version>${netty-all.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.xingyuv</groupId>
|
<groupId>com.xingyuv</groupId>
|
||||||
<artifactId>spring-boot-starter-captcha-plus</artifactId>
|
<artifactId>spring-boot-starter-captcha-plus</artifactId>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<maven.compiler.target>8</maven.compiler.target>
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<!-- 统一依赖管理 -->
|
<!-- 统一依赖管理 -->
|
||||||
<spring.boot.version>2.7.14</spring.boot.version>
|
<spring.boot.version>2.7.16</spring.boot.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.8.20</version>
|
<version>5.8.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<maven.compiler.target>8</maven.compiler.target>
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<!-- 统一依赖管理 -->
|
<!-- 统一依赖管理 -->
|
||||||
<spring.boot.version>2.7.14</spring.boot.version>
|
<spring.boot.version>2.7.16</spring.boot.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.8.20</version>
|
<version>5.8.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -137,6 +137,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -23,7 +22,6 @@ import java.util.List;
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@UtilityClass
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class JsonUtils {
|
public class JsonUtils {
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,12 @@ public class PayTransferRespDTO {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建【FAILURE】状态的转账返回
|
* 创建【CLOSED】状态的转账返回
|
||||||
*/
|
*/
|
||||||
public static PayTransferRespDTO failureOf(String channelErrorCode, String channelErrorMsg,
|
public static PayTransferRespDTO closedOf(String channelErrorCode, String channelErrorMsg,
|
||||||
String outTransferNo, Object rawData) {
|
String outTransferNo, Object rawData) {
|
||||||
PayTransferRespDTO respDTO = new PayTransferRespDTO();
|
PayTransferRespDTO respDTO = new PayTransferRespDTO();
|
||||||
respDTO.status = PayTransferStatusRespEnum.FAILURE.getStatus();
|
respDTO.status = PayTransferStatusRespEnum.CLOSED.getStatus();
|
||||||
respDTO.channelErrorCode = channelErrorCode;
|
respDTO.channelErrorCode = channelErrorCode;
|
||||||
respDTO.channelErrorMsg = channelErrorMsg;
|
respDTO.channelErrorMsg = channelErrorMsg;
|
||||||
// 相对通用的字段
|
// 相对通用的字段
|
||||||
|
|
|
@ -58,7 +58,6 @@ public class PayTransferUnifiedReqDTO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付渠道的额外参数
|
* 支付渠道的额外参数
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private Map<String, String> channelExtras;
|
private Map<String, String> channelExtras;
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||||
*/
|
*/
|
||||||
public final void init() {
|
public final void init() {
|
||||||
doInit();
|
doInit();
|
||||||
log.info("[init][客户端({}) 初始化完成]", getId());
|
log.debug("[init][客户端({}) 初始化完成]", getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class AlipayTransferClient extends AbstractAlipayPayClient {
|
||||||
model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
|
model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
|
||||||
model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER。
|
model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER。
|
||||||
model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
|
model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
|
||||||
PayTransferTypeEnum transferType = PayTransferTypeEnum.valueOf(reqDTO.getType());
|
PayTransferTypeEnum transferType = PayTransferTypeEnum.ofType(reqDTO.getType());
|
||||||
switch(transferType){
|
switch(transferType){
|
||||||
case WX_BALANCE :
|
case WX_BALANCE :
|
||||||
case WALLET_BALANCE : {
|
case WALLET_BALANCE : {
|
||||||
|
@ -84,7 +84,7 @@ public class AlipayTransferClient extends AbstractAlipayPayClient {
|
||||||
if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
|
if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
|
||||||
return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
|
return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
|
||||||
}
|
}
|
||||||
return PayTransferRespDTO.failureOf(response.getSubCode(), response.getSubMsg(),
|
return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
|
||||||
reqDTO.getOutTransferNo(), response);
|
reqDTO.getOutTransferNo(), response);
|
||||||
}
|
}
|
||||||
return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
|
return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
|
||||||
|
|
|
@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.pay.core.enums.transfer;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渠道的转账状态枚举
|
* 渠道的转账状态枚举
|
||||||
*
|
*
|
||||||
|
@ -12,10 +14,28 @@ import lombok.Getter;
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum PayTransferStatusRespEnum {
|
public enum PayTransferStatusRespEnum {
|
||||||
|
|
||||||
WAITING(0, "等待转账"),
|
WAITING(0, "转账中"),
|
||||||
SUCCESS(10, "转账成功"),
|
|
||||||
FAILURE(20, "转账失败");
|
/**
|
||||||
|
* TODO 转账到银行卡. 会有T+0 T+1 到账的请情况。 还未实现
|
||||||
|
*/
|
||||||
|
IN_PROGRESS(10, "转账进行中"),
|
||||||
|
|
||||||
|
|
||||||
|
SUCCESS(20, "转账成功"),
|
||||||
|
/**
|
||||||
|
* 转账关闭 (失败,或者其它情况)
|
||||||
|
*/
|
||||||
|
CLOSED(30, "转账关闭");
|
||||||
|
|
||||||
private final Integer status;
|
private final Integer status;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
public static boolean isSuccess(Integer status) {
|
||||||
|
return Objects.equals(status, SUCCESS.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isClosed(Integer status) {
|
||||||
|
return Objects.equals(status, CLOSED.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ public enum PayTransferTypeEnum implements IntArrayValuable {
|
||||||
BANK_CARD(3, "银行卡"),
|
BANK_CARD(3, "银行卡"),
|
||||||
WALLET_BALANCE(4, "钱包余额");
|
WALLET_BALANCE(4, "钱包余额");
|
||||||
|
|
||||||
|
public static final String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID";
|
||||||
|
public static final String ALIPAY_ACCOUNT_NAME = "ALIPAY_ACCOUNT_NAME";
|
||||||
|
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
@ -30,7 +33,7 @@ public enum PayTransferTypeEnum implements IntArrayValuable {
|
||||||
return ARRAYS;
|
return ARRAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PayTransferTypeEnum valueOf(Integer type) {
|
public static PayTransferTypeEnum ofType(Integer type) {
|
||||||
return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
|
return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public abstract class AbstractSmsClient implements SmsClient {
|
||||||
*/
|
*/
|
||||||
public final void init() {
|
public final void init() {
|
||||||
doInit();
|
doInit();
|
||||||
log.info("[init][配置({}) 初始化完成]", properties);
|
log.debug("[init][配置({}) 初始化完成]", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
package cn.iocoder.yudao.framework.social.config;
|
package cn.iocoder.yudao.framework.social.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
|
import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
|
||||||
import com.xingyuv.http.HttpUtil;
|
import com.xingyuv.http.HttpUtil;
|
||||||
import com.xingyuv.http.support.hutool.HutoolImpl;
|
import com.xingyuv.http.support.hutool.HutoolImpl;
|
||||||
import com.xingyuv.jushauth.cache.AuthStateCache;
|
import com.xingyuv.jushauth.cache.AuthStateCache;
|
||||||
import com.xingyuv.justauth.autoconfigure.JustAuthProperties;
|
import com.xingyuv.justauth.autoconfigure.JustAuthProperties;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 社交自动装配类
|
* 社交自动装配类
|
||||||
*
|
*
|
||||||
* @author timfruit
|
* @author timfruit
|
||||||
* @date 2021-10-30
|
* @date 2021-10-30
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@EnableConfigurationProperties(JustAuthProperties.class)
|
@EnableConfigurationProperties(JustAuthProperties.class)
|
||||||
public class YudaoSocialAutoConfiguration {
|
public class YudaoSocialAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Primary
|
@Primary
|
||||||
@ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)
|
||||||
public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
|
public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
|
||||||
// 需要修改 HttpUtil 使用的实现,避免类报错
|
// 需要修改 HttpUtil 使用的实现,避免类报错
|
||||||
HttpUtil.setHttp(new HutoolImpl());
|
HttpUtil.setHttp(new HutoolImpl());
|
||||||
// 创建 YudaoAuthRequestFactory
|
// 创建 YudaoAuthRequestFactory
|
||||||
return new YudaoAuthRequestFactory(properties, authStateCache);
|
return new YudaoAuthRequestFactory(properties, authStateCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package cn.iocoder.yudao.framework.tenant.config;
|
package cn.iocoder.yudao.framework.tenant.config;
|
||||||
|
|
||||||
import cn.hutool.core.annotation.AnnotationUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
|
||||||
import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
|
import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
|
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
|
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobHandlerDecorator;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor;
|
import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager;
|
import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
|
import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
|
||||||
|
@ -20,8 +17,6 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
|
import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
@ -100,25 +95,8 @@ public class YudaoTenantAutoConfiguration {
|
||||||
// ========== Job ==========
|
// ========== Job ==========
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
|
public TenantJobAspect tenantJobAspect(TenantFrameworkService tenantFrameworkService) {
|
||||||
public BeanPostProcessor jobHandlerBeanPostProcessor(TenantFrameworkService tenantFrameworkService) {
|
return new TenantJobAspect(tenantFrameworkService);
|
||||||
return new BeanPostProcessor() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
|
||||||
if (!(bean instanceof JobHandler)) {
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
// 有 TenantJob 注解的情况下,才会进行处理
|
|
||||||
if (!AnnotationUtil.hasAnnotation(bean.getClass(), TenantJob.class)) {
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 TenantJobHandlerDecorator 装饰
|
|
||||||
return new TenantJobHandlerDecorator(tenantFrameworkService, (JobHandler) bean);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== Redis ==========
|
// ========== Redis ==========
|
||||||
|
|
|
@ -8,7 +8,7 @@ import java.lang.annotation.Target;
|
||||||
/**
|
/**
|
||||||
* 多租户 Job 注解
|
* 多租户 Job 注解
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface TenantJob {
|
public @interface TenantJob {
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package cn.iocoder.yudao.framework.tenant.core.job;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
|
||||||
|
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多租户 JobHandler AOP
|
||||||
|
* 任务执行时,会按照租户逐个执行 Job 的逻辑
|
||||||
|
*
|
||||||
|
* 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class TenantJobAspect {
|
||||||
|
|
||||||
|
private final TenantFrameworkService tenantFrameworkService;
|
||||||
|
|
||||||
|
@Around("@annotation(tenantJob)")
|
||||||
|
public String around(ProceedingJoinPoint joinPoint, TenantJob tenantJob) {
|
||||||
|
// 获得租户列表
|
||||||
|
List<Long> tenantIds = tenantFrameworkService.getTenantIds();
|
||||||
|
if (CollUtil.isEmpty(tenantIds)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逐个租户,执行 Job
|
||||||
|
Map<Long, String> results = new ConcurrentHashMap<>();
|
||||||
|
tenantIds.parallelStream().forEach(tenantId -> {
|
||||||
|
// TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况
|
||||||
|
TenantUtils.execute(tenantId, () -> {
|
||||||
|
try {
|
||||||
|
joinPoint.proceed();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
results.put(tenantId, ExceptionUtil.getRootCauseMessage(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return JsonUtils.toJsonString(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,58 +0,0 @@
|
||||||
package cn.iocoder.yudao.framework.tenant.core.job;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
|
||||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 多租户 JobHandler 装饰器
|
|
||||||
* 任务执行时,会按照租户逐个执行 Job 的逻辑
|
|
||||||
*
|
|
||||||
* 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class TenantJobHandlerDecorator implements JobHandler {
|
|
||||||
|
|
||||||
private final TenantFrameworkService tenantFrameworkService;
|
|
||||||
/**
|
|
||||||
* 被装饰的 Job
|
|
||||||
*/
|
|
||||||
private final JobHandler jobHandler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String execute(String param) throws Exception {
|
|
||||||
// 获得租户列表
|
|
||||||
List<Long> tenantIds = tenantFrameworkService.getTenantIds();
|
|
||||||
if (CollUtil.isEmpty(tenantIds)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 逐个租户,执行 Job
|
|
||||||
Map<Long, String> results = new ConcurrentHashMap<>();
|
|
||||||
tenantIds.parallelStream().forEach(tenantId -> { // TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况
|
|
||||||
try {
|
|
||||||
// 设置租户
|
|
||||||
TenantContextHolder.setTenantId(tenantId);
|
|
||||||
// 执行 Job
|
|
||||||
String result = jobHandler.execute(param);
|
|
||||||
// 添加结果
|
|
||||||
results.put(tenantId, result);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
TenantContextHolder.clear();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return JsonUtils.toJsonString(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.iocoder.yudao.framework.tenant.core.redis;
|
package cn.iocoder.yudao.framework.tenant.core.redis;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.redis.core.TimeoutRedisCacheManager;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
|
@ -15,7 +16,7 @@ import org.springframework.data.redis.cache.RedisCacheWriter;
|
||||||
* @author airhead
|
* @author airhead
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TenantRedisCacheManager extends RedisCacheManager {
|
public class TenantRedisCacheManager extends TimeoutRedisCacheManager {
|
||||||
|
|
||||||
public TenantRedisCacheManager(RedisCacheWriter cacheWriter,
|
public TenantRedisCacheManager(RedisCacheWriter cacheWriter,
|
||||||
RedisCacheConfiguration defaultCacheConfiguration) {
|
RedisCacheConfiguration defaultCacheConfiguration) {
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package cn.iocoder.yudao.framework.tenant.core.job;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
|
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证 job 租户逻辑
|
|
||||||
* {@link TenantJobHandlerDecorator}
|
|
||||||
*
|
|
||||||
* @author gaibu
|
|
||||||
*/
|
|
||||||
public class TenantJobTest extends BaseMockitoUnitTest {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
TenantFrameworkService tenantFrameworkService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
// 准备测试租户 id
|
|
||||||
List<Long> tenantIds = Lists.newArrayList(1L, 2L, 3L);
|
|
||||||
// mock 数据
|
|
||||||
Mockito.doReturn(tenantIds).when(tenantFrameworkService).getTenantIds();
|
|
||||||
// 准备测试任务
|
|
||||||
TestJob testJob = new TestJob();
|
|
||||||
// 创建任务装饰器
|
|
||||||
TenantJobHandlerDecorator tenantJobHandlerDecorator = new TenantJobHandlerDecorator(tenantFrameworkService, testJob);
|
|
||||||
|
|
||||||
// 执行任务
|
|
||||||
tenantJobHandlerDecorator.execute(null);
|
|
||||||
|
|
||||||
// 断言返回值
|
|
||||||
assertEquals(testJob.getTenantIds(), tenantIds);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,12 +9,12 @@ import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@TenantJob // 标记多租户
|
|
||||||
public class TestJob implements JobHandler {
|
public class TestJob implements JobHandler {
|
||||||
|
|
||||||
private final List<Long> tenantIds = new CopyOnWriteArrayList<>();
|
private final List<Long> tenantIds = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@TenantJob // 标记多租户
|
||||||
public String execute(String param) throws Exception {
|
public String execute(String param) throws Exception {
|
||||||
tenantIds.add(TenantContextHolder.getTenantId());
|
tenantIds.add(TenantContextHolder.getTenantId());
|
||||||
return "success";
|
return "success";
|
||||||
|
@ -24,4 +24,5 @@ public class TestJob implements JobHandler {
|
||||||
CollUtil.sort(tenantIds, Long::compareTo);
|
CollUtil.sort(tenantIds, Long::compareTo);
|
||||||
return tenantIds;
|
return tenantIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public abstract class AbstractFileClient<Config extends FileClientConfig> implem
|
||||||
*/
|
*/
|
||||||
public final void init() {
|
public final void init() {
|
||||||
doInit();
|
doInit();
|
||||||
log.info("[init][配置({}) 初始化完成]", config);
|
log.debug("[init][配置({}) 初始化完成]", config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
package cn.iocoder.yudao.framework.flowable.core.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
import org.flowable.bpmn.model.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程模型转操作工具类
|
||||||
|
*/
|
||||||
|
public class BpmnModelUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据节点,获取入口连线
|
||||||
|
*
|
||||||
|
* @param source 起始节点
|
||||||
|
* @return 入口连线列表
|
||||||
|
*/
|
||||||
|
public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) {
|
||||||
|
if (source instanceof FlowNode) {
|
||||||
|
return ((FlowNode) source).getIncomingFlows();
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据节点,获取出口连线
|
||||||
|
*
|
||||||
|
* @param source 起始节点
|
||||||
|
* @return 出口连线列表
|
||||||
|
*/
|
||||||
|
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) {
|
||||||
|
if (source instanceof FlowNode) {
|
||||||
|
return ((FlowNode) source).getOutgoingFlows();
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流程元素信息
|
||||||
|
*
|
||||||
|
* @param model bpmnModel 对象
|
||||||
|
* @param flowElementId 元素 ID
|
||||||
|
* @return 元素信息
|
||||||
|
*/
|
||||||
|
public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) {
|
||||||
|
Process process = model.getMainProcess();
|
||||||
|
return process.getFlowElement(flowElementId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 BPMN 流程中,指定的元素们
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
* @param clazz 指定元素。例如说,{@link UserTask}、{@link Gateway} 等等
|
||||||
|
* @return 元素们
|
||||||
|
*/
|
||||||
|
public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
|
||||||
|
List<T> result = new ArrayList<>();
|
||||||
|
model.getProcesses().forEach(process -> {
|
||||||
|
process.getFlowElements().forEach(flowElement -> {
|
||||||
|
if (flowElement.getClass().isAssignableFrom(clazz)) {
|
||||||
|
result.add((T) flowElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较 两个bpmnModel 是否相同
|
||||||
|
* @param oldModel 老的bpmn model
|
||||||
|
* @param newModel 新的bpmn model
|
||||||
|
*/
|
||||||
|
public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
|
||||||
|
// 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
|
||||||
|
return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把 bpmnModel 转换成 byte[]
|
||||||
|
* @param model bpmnModel
|
||||||
|
*/
|
||||||
|
public static byte[] getBpmnBytes(BpmnModel model) {
|
||||||
|
if (model == null) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||||
|
return converter.convertToXML(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 遍历相关的方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 找到 source 节点之前的所有用户任务节点
|
||||||
|
*
|
||||||
|
* @param source 起始节点
|
||||||
|
* @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复
|
||||||
|
* @param userTaskList 已找到的用户任务节点
|
||||||
|
* @return 用户任务节点 数组
|
||||||
|
*/
|
||||||
|
public static List<UserTask> getPreviousUserTaskList(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
|
||||||
|
userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
|
||||||
|
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
|
||||||
|
// 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代
|
||||||
|
if (source instanceof StartEvent && source.getSubProcess() != null) {
|
||||||
|
userTaskList = getPreviousUserTaskList(source.getSubProcess(), hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型,获取入口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (sequenceFlows == null) {
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
// 循环找到目标元素
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
hasSequenceFlow.add(sequenceFlow.getId());
|
||||||
|
// 类型为用户节点,则新增父级节点
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||||
|
userTaskList.add((UserTask) sequenceFlow.getSourceFlowElement());
|
||||||
|
}
|
||||||
|
// 类型为子流程,则添加子流程开始节点出口处相连的节点
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) {
|
||||||
|
// 获取子流程用户任务节点
|
||||||
|
List<UserTask> childUserTaskList = findChildProcessUserTaskList((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, null);
|
||||||
|
// 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续
|
||||||
|
if (CollUtil.isNotEmpty(childUserTaskList)) {
|
||||||
|
userTaskList.addAll(childUserTaskList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 继续迭代
|
||||||
|
userTaskList = getPreviousUserTaskList(sequenceFlow.getSourceFlowElement(), hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 迭代获取子流程用户任务节点
|
||||||
|
*
|
||||||
|
* @param source 起始节点
|
||||||
|
* @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复
|
||||||
|
* @param userTaskList 需要撤回的用户任务列表
|
||||||
|
* @return 用户任务节点
|
||||||
|
*/
|
||||||
|
public static List<UserTask> findChildProcessUserTaskList(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
|
||||||
|
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
|
||||||
|
userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
|
||||||
|
|
||||||
|
// 根据类型,获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (sequenceFlows == null) {
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
// 循环找到目标元素
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
hasSequenceFlow.add(sequenceFlow.getId());
|
||||||
|
// 如果为用户任务类型,且任务节点的 Key 正在运行的任务中存在,添加
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof UserTask) {
|
||||||
|
userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 如果节点为子流程节点情况,则从节点中的第一个节点开始获取
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
|
||||||
|
List<UserTask> childUserTaskList = findChildProcessUserTaskList((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, null);
|
||||||
|
// 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续
|
||||||
|
if (CollUtil.isNotEmpty(childUserTaskList)) {
|
||||||
|
userTaskList.addAll(childUserTaskList);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 继续迭代
|
||||||
|
userTaskList = findChildProcessUserTaskList(sequenceFlow.getTargetFlowElement(), hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 迭代从后向前扫描,判断目标节点相对于当前节点是否是串行
|
||||||
|
* 不存在直接回退到子流程中的情况,但存在从子流程出去到父流程情况
|
||||||
|
*
|
||||||
|
* @param source 起始节点
|
||||||
|
* @param target 目标节点
|
||||||
|
* @param visitedElements 已经经过的连线的 ID,用于判断线路是否重复
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) {
|
||||||
|
visitedElements = visitedElements == null ? new HashSet<>() : visitedElements;
|
||||||
|
// 不能是开始事件和子流程
|
||||||
|
if (source instanceof StartEvent && isInEventSubprocess(source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型,获取入口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (CollUtil.isEmpty(sequenceFlows)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 循环找到目标元素
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (visitedElements.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
visitedElements.add(sequenceFlow.getId());
|
||||||
|
// 这条线路存在目标节点,这条线路完成,进入下个线路
|
||||||
|
FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
|
||||||
|
if (target.getId().equals(sourceFlowElement.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 如果目标节点为并行网关,则不继续
|
||||||
|
if (sourceFlowElement instanceof ParallelGateway) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 否则就继续迭代
|
||||||
|
if (!isSequentialReachable(sourceFlowElement, target, visitedElements)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前节点是否属于不同的子流程
|
||||||
|
*
|
||||||
|
* @param flowElement 被判断的节点
|
||||||
|
* @return true 表示属于子流程
|
||||||
|
*/
|
||||||
|
private static boolean isInEventSubprocess(FlowElement flowElement) {
|
||||||
|
FlowElementsContainer flowElementsContainer = flowElement.getParentContainer();
|
||||||
|
while (flowElementsContainer != null) {
|
||||||
|
if (flowElementsContainer instanceof EventSubProcess) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flowElementsContainer instanceof FlowElement) {
|
||||||
|
flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
|
||||||
|
} else {
|
||||||
|
flowElementsContainer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据正在运行的任务节点,迭代获取子级任务节点列表,向后找
|
||||||
|
*
|
||||||
|
* @param source 起始节点
|
||||||
|
* @param runTaskKeyList 正在运行的任务 Key,用于校验任务节点是否是正在运行的节点
|
||||||
|
* @param hasSequenceFlow 已经经过的连线的 ID,用于判断线路是否重复
|
||||||
|
* @param userTaskList 需要撤回的用户任务列表
|
||||||
|
* @return 子级任务节点列表
|
||||||
|
*/
|
||||||
|
public static List<UserTask> iteratorFindChildUserTasks(FlowElement source, List<String> runTaskKeyList,
|
||||||
|
Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
|
||||||
|
hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
|
||||||
|
userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
|
||||||
|
// 如果该节点为开始节点,且存在上级子节点,则顺着上级子节点继续迭代
|
||||||
|
if (source instanceof StartEvent && source.getSubProcess() != null) {
|
||||||
|
userTaskList = iteratorFindChildUserTasks(source.getSubProcess(), runTaskKeyList, hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型,获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (sequenceFlows == null) {
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
// 循环找到目标元素
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
hasSequenceFlow.add(sequenceFlow.getId());
|
||||||
|
// 如果为用户任务类型,且任务节点的 Key 正在运行的任务中存在,添加
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof UserTask && runTaskKeyList.contains((sequenceFlow.getTargetFlowElement()).getId())) {
|
||||||
|
userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 如果节点为子流程节点情况,则从节点中的第一个节点开始获取
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
|
||||||
|
List<UserTask> childUserTaskList = iteratorFindChildUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), runTaskKeyList, hasSequenceFlow, null);
|
||||||
|
// 如果找到节点,则说明该线路找到节点,不继续向下找,反之继续
|
||||||
|
if (CollUtil.isNotEmpty(childUserTaskList)) {
|
||||||
|
userTaskList.addAll(childUserTaskList);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 继续迭代
|
||||||
|
userTaskList = iteratorFindChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,14 +1,7 @@
|
||||||
package cn.iocoder.yudao.framework.flowable.core.util;
|
package cn.iocoder.yudao.framework.flowable.core.util;
|
||||||
|
|
||||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
|
||||||
import org.flowable.bpmn.model.BpmnModel;
|
|
||||||
import org.flowable.bpmn.model.FlowElement;
|
|
||||||
import org.flowable.common.engine.impl.identity.Authentication;
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flowable 相关的工具方法
|
* Flowable 相关的工具方法
|
||||||
*
|
*
|
||||||
|
@ -26,49 +19,6 @@ public class FlowableUtils {
|
||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== BPMN 相关的工具方法 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得 BPMN 流程中,指定的元素们
|
|
||||||
*
|
|
||||||
* @param model
|
|
||||||
* @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
|
|
||||||
* @return 元素们
|
|
||||||
*/
|
|
||||||
public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
|
|
||||||
List<T> result = new ArrayList<>();
|
|
||||||
model.getProcesses().forEach(process -> {
|
|
||||||
process.getFlowElements().forEach(flowElement -> {
|
|
||||||
if (flowElement.getClass().isAssignableFrom(clazz)) {
|
|
||||||
result.add((T) flowElement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 比较 两个bpmnModel 是否相同
|
|
||||||
* @param oldModel 老的bpmn model
|
|
||||||
* @param newModel 新的bpmn model
|
|
||||||
*/
|
|
||||||
public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
|
|
||||||
// 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
|
|
||||||
return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把 bpmnModel 转换成 byte[]
|
|
||||||
* @param model bpmnModel
|
|
||||||
*/
|
|
||||||
public static byte[] getBpmnBytes(BpmnModel model) {
|
|
||||||
if (model == null) {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
|
||||||
return converter.convertToXML(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== Execution 相关的工具方法 ==========
|
// ========== Execution 相关的工具方法 ==========
|
||||||
|
|
||||||
public static String formatCollectionVariable(String activityId) {
|
public static String formatCollectionVariable(String activityId) {
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
package cn.iocoder.yudao.framework.quartz.config;
|
package cn.iocoder.yudao.framework.quartz.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager;
|
import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务 Configuration
|
* 定时任务 Configuration
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@EnableScheduling // 开启 Spring 自带的定时任务
|
@EnableScheduling // 开启 Spring 自带的定时任务
|
||||||
|
@Slf4j
|
||||||
public class YudaoQuartzAutoConfiguration {
|
public class YudaoQuartzAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SchedulerManager schedulerManager(Scheduler scheduler) {
|
public SchedulerManager schedulerManager(Optional<Scheduler> scheduler) {
|
||||||
return new SchedulerManager(scheduler);
|
if (!scheduler.isPresent()) {
|
||||||
|
log.info("[定时任务 - 已禁用][参考 https://doc.iocoder.cn/job/ 开启]");
|
||||||
|
return new SchedulerManager(null);
|
||||||
|
}
|
||||||
|
return new SchedulerManager(scheduler.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.quartz.core.enums.JobDataKeyEnum;
|
||||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker;
|
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker;
|
||||||
import org.quartz.*;
|
import org.quartz.*;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.quartz.Scheduler} 的管理器,负责创建任务
|
* {@link org.quartz.Scheduler} 的管理器,负责创建任务
|
||||||
*
|
*
|
||||||
|
@ -37,6 +40,7 @@ public class SchedulerManager {
|
||||||
public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression,
|
public void addJob(Long jobId, String jobHandlerName, String jobHandlerParam, String cronExpression,
|
||||||
Integer retryCount, Integer retryInterval)
|
Integer retryCount, Integer retryInterval)
|
||||||
throws SchedulerException {
|
throws SchedulerException {
|
||||||
|
validateScheduler();
|
||||||
// 创建 JobDetail 对象
|
// 创建 JobDetail 对象
|
||||||
JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class)
|
JobDetail jobDetail = JobBuilder.newJob(JobHandlerInvoker.class)
|
||||||
.usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId)
|
.usingJobData(JobDataKeyEnum.JOB_ID.name(), jobId)
|
||||||
|
@ -61,6 +65,7 @@ public class SchedulerManager {
|
||||||
public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression,
|
public void updateJob(String jobHandlerName, String jobHandlerParam, String cronExpression,
|
||||||
Integer retryCount, Integer retryInterval)
|
Integer retryCount, Integer retryInterval)
|
||||||
throws SchedulerException {
|
throws SchedulerException {
|
||||||
|
validateScheduler();
|
||||||
// 创建新 Trigger 对象
|
// 创建新 Trigger 对象
|
||||||
Trigger newTrigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval);
|
Trigger newTrigger = this.buildTrigger(jobHandlerName, jobHandlerParam, cronExpression, retryCount, retryInterval);
|
||||||
// 修改调度
|
// 修改调度
|
||||||
|
@ -74,6 +79,7 @@ public class SchedulerManager {
|
||||||
* @throws SchedulerException 删除异常
|
* @throws SchedulerException 删除异常
|
||||||
*/
|
*/
|
||||||
public void deleteJob(String jobHandlerName) throws SchedulerException {
|
public void deleteJob(String jobHandlerName) throws SchedulerException {
|
||||||
|
validateScheduler();
|
||||||
scheduler.deleteJob(new JobKey(jobHandlerName));
|
scheduler.deleteJob(new JobKey(jobHandlerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +90,7 @@ public class SchedulerManager {
|
||||||
* @throws SchedulerException 暂停异常
|
* @throws SchedulerException 暂停异常
|
||||||
*/
|
*/
|
||||||
public void pauseJob(String jobHandlerName) throws SchedulerException {
|
public void pauseJob(String jobHandlerName) throws SchedulerException {
|
||||||
|
validateScheduler();
|
||||||
scheduler.pauseJob(new JobKey(jobHandlerName));
|
scheduler.pauseJob(new JobKey(jobHandlerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +101,7 @@ public class SchedulerManager {
|
||||||
* @throws SchedulerException 启动异常
|
* @throws SchedulerException 启动异常
|
||||||
*/
|
*/
|
||||||
public void resumeJob(String jobHandlerName) throws SchedulerException {
|
public void resumeJob(String jobHandlerName) throws SchedulerException {
|
||||||
|
validateScheduler();
|
||||||
scheduler.resumeJob(new JobKey(jobHandlerName));
|
scheduler.resumeJob(new JobKey(jobHandlerName));
|
||||||
scheduler.resumeTrigger(new TriggerKey(jobHandlerName));
|
scheduler.resumeTrigger(new TriggerKey(jobHandlerName));
|
||||||
}
|
}
|
||||||
|
@ -108,11 +116,12 @@ public class SchedulerManager {
|
||||||
*/
|
*/
|
||||||
public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam)
|
public void triggerJob(Long jobId, String jobHandlerName, String jobHandlerParam)
|
||||||
throws SchedulerException {
|
throws SchedulerException {
|
||||||
|
validateScheduler();
|
||||||
|
// 触发任务
|
||||||
JobDataMap data = new JobDataMap(); // 无需重试,所以不设置 retryCount 和 retryInterval
|
JobDataMap data = new JobDataMap(); // 无需重试,所以不设置 retryCount 和 retryInterval
|
||||||
data.put(JobDataKeyEnum.JOB_ID.name(), jobId);
|
data.put(JobDataKeyEnum.JOB_ID.name(), jobId);
|
||||||
data.put(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName);
|
data.put(JobDataKeyEnum.JOB_HANDLER_NAME.name(), jobHandlerName);
|
||||||
data.put(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam);
|
data.put(JobDataKeyEnum.JOB_HANDLER_PARAM.name(), jobHandlerParam);
|
||||||
// 触发任务
|
|
||||||
scheduler.triggerJob(new JobKey(jobHandlerName), data);
|
scheduler.triggerJob(new JobKey(jobHandlerName), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,4 +136,11 @@ public class SchedulerManager {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateScheduler() {
|
||||||
|
if (scheduler == null) {
|
||||||
|
throw exception0(NOT_IMPLEMENTED.getCode(),
|
||||||
|
"[定时任务 - 已禁用][参考 https://doc.iocoder.cn/job/ 开启]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||||
|
|
|
@ -26,11 +26,13 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.github.resilience4j</groupId>
|
<groupId>io.github.resilience4j</groupId>
|
||||||
<artifactId>resilience4j-spring-boot2</artifactId>
|
<artifactId>resilience4j-spring-boot2</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,11 @@ package cn.iocoder.yudao.framework.lock4j.config;
|
||||||
import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
|
import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
|
||||||
import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
|
import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
@AutoConfiguration(before = LockAutoConfiguration.class)
|
@AutoConfiguration(before = LockAutoConfiguration.class)
|
||||||
|
@ConditionalOnClass(name = "com.baomidou.lock.annotation.Lock4j")
|
||||||
public class YudaoLock4jConfiguration {
|
public class YudaoLock4jConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
@ -32,12 +32,6 @@
|
||||||
<artifactId>spring-boot-starter-cache</artifactId> <!-- 实现对 Caches 的自动化配置 -->
|
<artifactId>spring-boot-starter-cache</artifactId> <!-- 实现对 Caches 的自动化配置 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty-all</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class TimeoutRedisCacheManager extends RedisCacheManager {
|
||||||
Duration duration = parseDuration(names[1]);
|
Duration duration = parseDuration(names[1]);
|
||||||
cacheConfig = cacheConfig.entryTtl(duration);
|
cacheConfig = cacheConfig.entryTtl(duration);
|
||||||
}
|
}
|
||||||
return super.createRedisCache(names[0], cacheConfig);
|
return super.createRedisCache(name, cacheConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -55,13 +55,6 @@
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 服务保障相关 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.resilience4j</groupId>
|
|
||||||
<artifactId>resilience4j-ratelimiter</artifactId>
|
|
||||||
<scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 -->
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- xss -->
|
<!-- xss -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.iocoder.yudao.framework.jackson.config;
|
package cn.iocoder.yudao.framework.jackson.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
|
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
|
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
|
||||||
|
@ -11,51 +12,41 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class YudaoJacksonAutoConfiguration {
|
public class YudaoJacksonAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public BeanPostProcessor objectMapperBeanPostProcessor() {
|
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||||
return new BeanPostProcessor() {
|
public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
|
||||||
|
// 1.1 创建 SimpleModule 对象
|
||||||
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
|
simpleModule
|
||||||
|
// 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
|
||||||
|
.addSerializer(Long.class, NumberSerializer.INSTANCE)
|
||||||
|
.addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
|
||||||
|
.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
|
||||||
|
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||||
|
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||||
|
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||||
|
// 新增 LocalDateTime 序列化、反序列化规则
|
||||||
|
.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
|
||||||
|
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
|
||||||
|
// 1.2 注册到 objectMapper
|
||||||
|
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
||||||
|
|
||||||
@Override
|
// 2. 设置 objectMapper 到 JsonUtils {
|
||||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
JsonUtils.init(CollUtil.getFirst(objectMappers));
|
||||||
if (!(bean instanceof ObjectMapper)) {
|
log.info("[init][初始化 JsonUtils 成功]");
|
||||||
return bean;
|
return new JsonUtils();
|
||||||
}
|
|
||||||
ObjectMapper objectMapper = (ObjectMapper) bean;
|
|
||||||
SimpleModule simpleModule = new SimpleModule();
|
|
||||||
/*
|
|
||||||
* 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型
|
|
||||||
* 2. 新增LocalDateTime序列化、反序列化规则
|
|
||||||
*/
|
|
||||||
simpleModule
|
|
||||||
.addSerializer(Long.class, NumberSerializer.INSTANCE)
|
|
||||||
.addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
|
|
||||||
.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
|
|
||||||
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
|
||||||
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
|
||||||
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
|
||||||
.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
|
|
||||||
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
|
|
||||||
|
|
||||||
objectMapper.registerModules(simpleModule);
|
|
||||||
|
|
||||||
JsonUtils.init(objectMapper);
|
|
||||||
log.info("初始化 jackson 自动配置");
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import io.github.resilience4j.ratelimiter.RequestNotPermitted;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
@ -33,6 +32,7 @@ import javax.validation.ConstraintViolationException;
|
||||||
import javax.validation.ValidationException;
|
import javax.validation.ValidationException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*;
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*;
|
||||||
|
|
||||||
|
@ -83,9 +83,6 @@ public class GlobalExceptionHandler {
|
||||||
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
||||||
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
|
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof RequestNotPermitted) {
|
|
||||||
return requestNotPermittedExceptionHandler(request, (RequestNotPermitted) ex);
|
|
||||||
}
|
|
||||||
if (ex instanceof ServiceException) {
|
if (ex instanceof ServiceException) {
|
||||||
return serviceExceptionHandler((ServiceException) ex);
|
return serviceExceptionHandler((ServiceException) ex);
|
||||||
}
|
}
|
||||||
|
@ -186,8 +183,7 @@ public class GlobalExceptionHandler {
|
||||||
/**
|
/**
|
||||||
* 处理 Resilience4j 限流抛出的异常
|
* 处理 Resilience4j 限流抛出的异常
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(value = RequestNotPermitted.class)
|
public CommonResult<?> requestNotPermittedExceptionHandler(HttpServletRequest req, Throwable ex) {
|
||||||
public CommonResult<?> requestNotPermittedExceptionHandler(HttpServletRequest req, RequestNotPermitted ex) {
|
|
||||||
log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex);
|
log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex);
|
||||||
return CommonResult.error(TOO_MANY_REQUESTS);
|
return CommonResult.error(TOO_MANY_REQUESTS);
|
||||||
}
|
}
|
||||||
|
@ -226,7 +222,12 @@ public class GlobalExceptionHandler {
|
||||||
return tableNotExistsResult;
|
return tableNotExistsResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况二:处理异常
|
// 情况二:部分特殊的库的处理
|
||||||
|
if (Objects.equals("io.github.resilience4j.ratelimiter.RequestNotPermitted", ex.getClass().getName())) {
|
||||||
|
return requestNotPermittedExceptionHandler(req, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况三:处理异常
|
||||||
log.error("[defaultExceptionHandler]", ex);
|
log.error("[defaultExceptionHandler]", ex);
|
||||||
// 插入异常日志
|
// 插入异常日志
|
||||||
this.createExceptionLog(req, ex);
|
this.createExceptionLog(req, ex);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.cr
|
||||||
|
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@EnableConfigurationProperties(XssProperties.class)
|
@EnableConfigurationProperties(XssProperties.class)
|
||||||
|
@ConditionalOnProperty(prefix = "yudao.xss", name = "enable", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用
|
||||||
public class YudaoXssAutoConfiguration implements WebMvcConfigurer {
|
public class YudaoXssAutoConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration
|
cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration
|
||||||
cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration
|
cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration
|
||||||
com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration
|
|
||||||
cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
|
cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
|
||||||
cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
|
cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
|
||||||
cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration
|
cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration
|
||||||
|
|
|
@ -4,61 +4,66 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bpm 错误码枚举类
|
* Bpm 错误码枚举类
|
||||||
*
|
* <p>
|
||||||
* bpm 系统,使用 1-009-000-000 段
|
* bpm 系统,使用 1-009-000-000 段
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 通用流程处理 模块 1009000000 ==========
|
// ========== 通用流程处理 模块 1-009-000-000 ==========
|
||||||
ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1009000002, "获取高亮流程图异常");
|
ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1_009_000_002, "获取高亮流程图异常");
|
||||||
|
|
||||||
// ========== OA 流程模块 1009001000 ==========
|
// ========== OA 流程模块 1-009-001-000 ==========
|
||||||
ErrorCode OA_LEAVE_NOT_EXISTS = new ErrorCode(1009001001, "请假申请不存在");
|
ErrorCode OA_LEAVE_NOT_EXISTS = new ErrorCode(1_009_001_001, "请假申请不存在");
|
||||||
ErrorCode OA_PM_POST_NOT_EXISTS = new ErrorCode(1009001002, "项目经理岗位未设置");
|
ErrorCode OA_PM_POST_NOT_EXISTS = new ErrorCode(1_009_001_002, "项目经理岗位未设置");
|
||||||
ErrorCode OA_DEPART_PM_POST_NOT_EXISTS = new ErrorCode(1009001009, "部门的项目经理不存在");
|
ErrorCode OA_DEPART_PM_POST_NOT_EXISTS = new ErrorCode(1_009_001_009, "部门的项目经理不存在");
|
||||||
ErrorCode OA_BM_POST_NOT_EXISTS = new ErrorCode(1009001004, "部门经理岗位未设置");
|
ErrorCode OA_BM_POST_NOT_EXISTS = new ErrorCode(1_009_001_004, "部门经理岗位未设置");
|
||||||
ErrorCode OA_DEPART_BM_POST_NOT_EXISTS = new ErrorCode(1009001005, "部门的部门经理不存在");
|
ErrorCode OA_DEPART_BM_POST_NOT_EXISTS = new ErrorCode(1_009_001_005, "部门的部门经理不存在");
|
||||||
ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1009001006, "HR岗位未设置");
|
ErrorCode OA_HR_POST_NOT_EXISTS = new ErrorCode(1_009_001_006, "HR岗位未设置");
|
||||||
ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1009001007, "请假天数必须>=1");
|
ErrorCode OA_DAY_LEAVE_ERROR = new ErrorCode(1_009_001_007, "请假天数必须>=1");
|
||||||
|
|
||||||
// ========== 流程模型 1009002000 ==========
|
// ========== 流程模型 1-009-002-000 ==========
|
||||||
ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1009002000, "已经存在流程标识为【{}】的流程");
|
ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1_009_002_000, "已经存在流程标识为【{}】的流程");
|
||||||
ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1009002001, "流程模型不存在");
|
ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_009_002_001, "流程模型不存在");
|
||||||
ErrorCode MODEL_KEY_VALID = new ErrorCode(1009002002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
|
ErrorCode MODEL_KEY_VALID = new ErrorCode(1_009_002_002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
|
||||||
ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1009002003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
|
ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1_009_002_003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
|
||||||
ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1009002004, "部署流程失败," +
|
ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," +
|
||||||
"原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置");
|
"原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置");
|
||||||
ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1009003005, "流程定义部署失败,原因:信息未发生变化");
|
ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1_009_003_005, "流程定义部署失败,原因:信息未发生变化");
|
||||||
|
|
||||||
// ========== 流程定义 1009003000 ==========
|
// ========== 流程定义 1-009-003-000 ==========
|
||||||
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
|
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1_009_003_000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
|
||||||
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
|
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1_009_003_001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
|
||||||
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");
|
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_009_003_002, "流程定义不存在");
|
||||||
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003003, "流程定义处于挂起状态");
|
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1_009_003_003, "流程定义处于挂起状态");
|
||||||
ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009003004, "流程定义的模型不存在");
|
ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1_009_003_004, "流程定义的模型不存在");
|
||||||
|
|
||||||
// ========== 流程实例 1009004000 ==========
|
// ========== 流程实例 1-009-004-000 ==========
|
||||||
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在");
|
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1_009_004_000, "流程实例不存在");
|
||||||
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1009004001, "流程取消失败,流程不处于运行中");
|
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1_009_004_001, "流程取消失败,流程不处于运行中");
|
||||||
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1009004002, "流程取消失败,该流程不是你发起的");
|
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1_009_004_002, "流程取消失败,该流程不是你发起的");
|
||||||
|
|
||||||
// ========== 流程任务 1009005000 ==========
|
// ========== 流程任务 1-009-005-000 ==========
|
||||||
ErrorCode TASK_COMPLETE_FAIL_NOT_EXISTS = new ErrorCode(1009005000, "审批任务失败,原因:该任务不处于未审批");
|
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
|
||||||
ErrorCode TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1009005001, "审批任务失败,原因:该任务的审批人不是你");
|
ErrorCode TASK_NOT_EXISTS = new ErrorCode(1_009_005_002, "流程任务不存在");
|
||||||
|
ErrorCode TASK_IS_PENDING = new ErrorCode(1_009_005_003, "当前任务处于挂起状态,不能操作");
|
||||||
|
ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_004, " 目标节点不存在");
|
||||||
|
ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
|
||||||
|
ErrorCode TASK_DELEGATE_FAIL_USER_REPEAT = new ErrorCode(1_009_005_007, "任务委派失败,委派人和当前审批人为同一人");
|
||||||
|
ErrorCode TASK_DELEGATE_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_008, "任务委派失败,被委派人不存在");
|
||||||
|
|
||||||
// ========== 流程任务分配规则 1009006000 ==========
|
// ========== 流程任务分配规则 1-009-006-000 ==========
|
||||||
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1009006000, "流程({}) 的任务({}) 已经存在分配规则");
|
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1_009_006_000, "流程({}) 的任务({}) 已经存在分配规则");
|
||||||
ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1009006001, "流程任务分配规则不存在");
|
ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1_009_006_001, "流程任务分配规则不存在");
|
||||||
ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1009006002, "只有流程模型的任务分配规则,才允许被修改");
|
ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1_009_006_002, "只有流程模型的任务分配规则,才允许被修改");
|
||||||
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1009006003, "操作失败,原因:找不到任务的审批人!");
|
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
|
||||||
ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1009006004, "操作失败,原因:任务分配脚本({}) 不存在");
|
ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1_009_006_004, "操作失败,原因:任务分配脚本({}) 不存在");
|
||||||
|
|
||||||
// ========== 动态表单模块 1009010000 ==========
|
// ========== 动态表单模块 1-009-010-000 ==========
|
||||||
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在");
|
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
|
||||||
ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009010001, "表单项({}) 和 ({}) 使用了相同的字段名({})");
|
ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1_009_010_001, "表单项({}) 和 ({}) 使用了相同的字段名({})");
|
||||||
|
|
||||||
// ========== 用户组模块 1009011000 ==========
|
// ========== 用户组模块 1-009-011-000 ==========
|
||||||
ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1009011000, "用户组不存在");
|
ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1_009_011_000, "用户组不存在");
|
||||||
ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1009011001, "名字为【{}】的用户组已被禁用");
|
ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1_009_011_001, "名字为【{}】的用户组已被禁用");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ public enum BpmProcessInstanceResultEnum {
|
||||||
|
|
||||||
// ========== 流程任务独有的状态 ==========
|
// ========== 流程任务独有的状态 ==========
|
||||||
|
|
||||||
BACK(5, "退回/驳回");
|
BACK(5, "驳回"), // 退回
|
||||||
|
DELEGATE(6, "委派");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 结果
|
* 结果
|
||||||
|
|
|
@ -75,4 +75,29 @@ public class BpmTaskController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get-return-list")
|
||||||
|
@Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮")
|
||||||
|
@Parameter(name = "taskId", description = "当前任务ID", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('bpm:task:update')")
|
||||||
|
public CommonResult<List<BpmTaskSimpleRespVO>> getReturnList(@RequestParam("taskId") String taskId) {
|
||||||
|
return success(taskService.getReturnTaskList(taskId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/return")
|
||||||
|
@Operation(summary = "回退任务", description = "用于【流程详情】的【回退】按钮")
|
||||||
|
@PreAuthorize("@ss.hasPermission('bpm:task:update')")
|
||||||
|
public CommonResult<Boolean> returnTask(@Valid @RequestBody BpmTaskReturnReqVO reqVO) {
|
||||||
|
taskService.returnTask(getLoginUserId(), reqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/delegate")
|
||||||
|
@Operation(summary = "委派任务", description = "用于【流程详情】的【委派】按钮。和向前【加签】有点像,唯一区别是【委托】没有单独创立任务")
|
||||||
|
@PreAuthorize("@ss.hasPermission('bpm:task:update')")
|
||||||
|
public CommonResult<Boolean> delegateTask(@Valid @RequestBody BpmTaskDelegateReqVO reqVO) {
|
||||||
|
// TODO @海:, 后面要有空格
|
||||||
|
taskService.delegateTask(reqVO,getLoginUserId());
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 委派流程任务的 Request VO")
|
||||||
|
@Data
|
||||||
|
public class BpmTaskDelegateReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
@NotEmpty(message = "任务编号不能为空")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "被委派人 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@NotNull(message = "被委派人 ID 不能为空")
|
||||||
|
private Long delegateUserId;
|
||||||
|
|
||||||
|
@Schema(description = "委派原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "做不了决定,需要你先帮忙瞅瞅")
|
||||||
|
@NotEmpty(message = "委派原因不能为空")
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 回退流程任务的 Request VO")
|
||||||
|
@Data
|
||||||
|
public class BpmTaskReturnReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
@NotEmpty(message = "任务编号不能为空")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "回退到的任务 Key", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
@NotEmpty(message = "回退到的任务 Key 不能为空")
|
||||||
|
private String targetDefinitionKey;
|
||||||
|
|
||||||
|
@Schema(description = "回退意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "我就是想驳回")
|
||||||
|
@NotEmpty(message = "回退意见不能为空")
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 流程任务的精简 Response VO")
|
||||||
|
@Data
|
||||||
|
public class BpmTaskSimpleRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "任务定义的标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "Activity_one")
|
||||||
|
private String definitionKey;
|
||||||
|
|
||||||
|
@Schema(description = "任务名词", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
|
@ -6,11 +6,13 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
|
||||||
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskSimpleRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
||||||
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
|
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||||
import org.flowable.engine.history.HistoricProcessInstance;
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
@ -55,8 +57,8 @@ public interface BpmTaskConvert {
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
|
default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
|
||||||
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,
|
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,
|
||||||
Map<Long, AdminUserRespDTO> userMap) {
|
Map<Long, AdminUserRespDTO> userMap) {
|
||||||
return CollectionUtils.convertList(tasks, task -> {
|
return CollectionUtils.convertList(tasks, task -> {
|
||||||
BpmTaskDonePageItemRespVO respVO = convert2(task);
|
BpmTaskDonePageItemRespVO respVO = convert2(task);
|
||||||
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
|
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
|
||||||
|
@ -82,8 +84,8 @@ public interface BpmTaskConvert {
|
||||||
BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
|
BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
|
||||||
|
|
||||||
default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks,
|
default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks,
|
||||||
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,
|
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,
|
||||||
Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
|
Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
|
||||||
return CollectionUtils.convertList(tasks, task -> {
|
return CollectionUtils.convertList(tasks, task -> {
|
||||||
BpmTaskRespVO respVO = convert3(task);
|
BpmTaskRespVO respVO = convert3(task);
|
||||||
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
|
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
|
||||||
|
@ -113,29 +115,34 @@ public interface BpmTaskConvert {
|
||||||
void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
|
void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
|
||||||
|
|
||||||
@Mappings({@Mapping(source = "processInstance.id", target = "id"),
|
@Mappings({@Mapping(source = "processInstance.id", target = "id"),
|
||||||
@Mapping(source = "processInstance.name", target = "name"),
|
@Mapping(source = "processInstance.name", target = "name"),
|
||||||
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
|
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
|
||||||
@Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
|
@Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
|
||||||
@Mapping(source = "startUser.nickname", target = "startUserNickname")})
|
@Mapping(source = "startUser.nickname", target = "startUserNickname")})
|
||||||
BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance,
|
BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance,
|
||||||
AdminUserRespDTO startUser);
|
AdminUserRespDTO startUser);
|
||||||
|
|
||||||
default BpmTaskExtDO convert2TaskExt(Task task) {
|
default BpmTaskExtDO convert2TaskExt(Task task) {
|
||||||
BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId())
|
BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId())
|
||||||
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())
|
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())
|
||||||
.setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId());
|
.setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId());
|
||||||
taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime()));
|
taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime()));
|
||||||
return taskExtDO;
|
return taskExtDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
|
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
|
||||||
Task task) {
|
Task task) {
|
||||||
BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
|
BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
|
||||||
reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
|
reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
|
||||||
.setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId())
|
.setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId())
|
||||||
.setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName())
|
.setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName())
|
||||||
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
|
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
|
||||||
return reqDTO;
|
return reqDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<BpmTaskSimpleRespVO> convertList(List<? extends FlowElement> elementList) {
|
||||||
|
return CollectionUtils.convertList(elementList, element -> new BpmTaskSimpleRespVO()
|
||||||
|
.setName(element.getName())
|
||||||
|
.setDefinitionKey(element.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,4 +74,12 @@ public interface BpmModelService {
|
||||||
*/
|
*/
|
||||||
BpmnModel getBpmnModel(String id);
|
BpmnModel getBpmnModel(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得流程定义编号对应的 BPMN Model
|
||||||
|
*
|
||||||
|
* @param processDefinitionId 流程定义编号
|
||||||
|
* @return BPMN Model
|
||||||
|
*/
|
||||||
|
BpmnModel getBpmnModelByDefinitionId(String processDefinitionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,6 +233,11 @@ public class BpmModelServiceImpl implements BpmModelService {
|
||||||
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
|
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmnModel getBpmnModelByDefinitionId(String processDefinitionId) {
|
||||||
|
return repositoryService.getBpmnModel(processDefinitionId);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkKeyNCName(String key) {
|
private void checkKeyNCName(String key) {
|
||||||
if (!ValidationUtils.isXmlNCName(key)) {
|
if (!ValidationUtils.isXmlNCName(key)) {
|
||||||
throw exception(MODEL_KEY_VALID);
|
throw exception(MODEL_KEY_VALID);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||||
import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
|
import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
||||||
|
@ -200,7 +200,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
||||||
BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
|
BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
|
||||||
BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
|
BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
|
||||||
// 对比字节变化
|
// 对比字节变化
|
||||||
if (!FlowableUtils.equals(oldModel, newModel)) {
|
if (!BpmnModelUtils.equals(oldModel, newModel)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 最终发现都一致,则返回 true
|
// 最终发现都一致,则返回 true
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
|
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
|
||||||
import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
|
import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
||||||
|
@ -114,7 +114,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
// 获得用户任务,只有用户任务才可以设置分配规则
|
// 获得用户任务,只有用户任务才可以设置分配规则
|
||||||
List<UserTask> userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class);
|
List<UserTask> userTasks = BpmnModelUtils.getBpmnModelElements(model, UserTask.class);
|
||||||
if (CollUtil.isEmpty(userTasks)) {
|
if (CollUtil.isEmpty(userTasks)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package cn.iocoder.yudao.module.bpm.service.task;
|
package cn.iocoder.yudao.module.bpm.service.task;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
||||||
|
@ -23,7 +22,6 @@ public interface BpmTaskService {
|
||||||
*
|
*
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @param pageReqVO 分页请求
|
* @param pageReqVO 分页请求
|
||||||
*
|
|
||||||
* @return 流程任务分页
|
* @return 流程任务分页
|
||||||
*/
|
*/
|
||||||
PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
|
PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
|
||||||
|
@ -33,7 +31,6 @@ public interface BpmTaskService {
|
||||||
*
|
*
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @param pageReqVO 分页请求
|
* @param pageReqVO 分页请求
|
||||||
*
|
|
||||||
* @return 流程任务分页
|
* @return 流程任务分页
|
||||||
*/
|
*/
|
||||||
PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
|
PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
|
||||||
|
@ -42,19 +39,17 @@ public interface BpmTaskService {
|
||||||
* 获得流程任务 Map
|
* 获得流程任务 Map
|
||||||
*
|
*
|
||||||
* @param processInstanceIds 流程实例的编号数组
|
* @param processInstanceIds 流程实例的编号数组
|
||||||
*
|
|
||||||
* @return 流程任务 Map
|
* @return 流程任务 Map
|
||||||
*/
|
*/
|
||||||
default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
|
default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
|
||||||
return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
|
return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
|
||||||
Task::getProcessInstanceId);
|
Task::getProcessInstanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得流程任务列表
|
* 获得流程任务列表
|
||||||
*
|
*
|
||||||
* @param processInstanceIds 流程实例的编号数组
|
* @param processInstanceIds 流程实例的编号数组
|
||||||
*
|
|
||||||
* @return 流程任务列表
|
* @return 流程任务列表
|
||||||
*/
|
*/
|
||||||
List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
|
List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
|
||||||
|
@ -63,7 +58,6 @@ public interface BpmTaskService {
|
||||||
* 获得指令流程实例的流程任务列表,包括所有状态的
|
* 获得指令流程实例的流程任务列表,包括所有状态的
|
||||||
*
|
*
|
||||||
* @param processInstanceId 流程实例的编号
|
* @param processInstanceId 流程实例的编号
|
||||||
*
|
|
||||||
* @return 流程任务列表
|
* @return 流程任务列表
|
||||||
*/
|
*/
|
||||||
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
|
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
|
||||||
|
@ -128,4 +122,29 @@ public interface BpmTaskService {
|
||||||
*/
|
*/
|
||||||
void updateTaskExtAssign(Task task);
|
void updateTaskExtAssign(Task task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前任务的可回退的流程集合
|
||||||
|
*
|
||||||
|
* @param taskId 当前的任务 ID
|
||||||
|
* @return 可以回退的节点列表
|
||||||
|
*/
|
||||||
|
List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将任务回退到指定的 targetDefinitionKey 位置
|
||||||
|
*
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param reqVO 回退的任务key和当前所在的任务ID
|
||||||
|
*/
|
||||||
|
void returnTask(Long userId, BpmTaskReturnReqVO reqVO);
|
||||||
|
|
||||||
|
// TODO @海:userId 放前面
|
||||||
|
/**
|
||||||
|
* 将指定任务委派给其他人处理,等接收人处理后再回到原审批人手中审批
|
||||||
|
*
|
||||||
|
* @param reqVO 被委派人和被委派的任务编号理由参数
|
||||||
|
* @param userId 用户编号
|
||||||
|
*/
|
||||||
|
void delegateTask(BpmTaskDelegateReqVO reqVO, Long userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,36 @@
|
||||||
package cn.iocoder.yudao.module.bpm.service.task;
|
package cn.iocoder.yudao.module.bpm.service.task;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.collection.ListUtil;
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||||
|
import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
|
||||||
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
||||||
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
|
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
|
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||||
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
|
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.UserTask;
|
||||||
import org.flowable.engine.HistoryService;
|
import org.flowable.engine.HistoryService;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
import org.flowable.engine.TaskService;
|
import org.flowable.engine.TaskService;
|
||||||
import org.flowable.engine.history.HistoricProcessInstance;
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.flowable.task.api.DelegationState;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
import org.flowable.task.api.TaskQuery;
|
import org.flowable.task.api.TaskQuery;
|
||||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
|
@ -32,6 +39,7 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
@ -39,8 +47,7 @@ import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,23 +64,29 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
private TaskService taskService;
|
private TaskService taskService;
|
||||||
@Resource
|
@Resource
|
||||||
private HistoryService historyService;
|
private HistoryService historyService;
|
||||||
|
@Resource
|
||||||
|
private RuntimeService runtimeService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private BpmProcessInstanceService processInstanceService;
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
@Resource
|
||||||
|
private BpmModelService bpmModelService;
|
||||||
|
@Resource
|
||||||
|
private BpmMessageService messageService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AdminUserApi adminUserApi;
|
private AdminUserApi adminUserApi;
|
||||||
@Resource
|
@Resource
|
||||||
private DeptApi deptApi;
|
private DeptApi deptApi;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private BpmTaskExtMapper taskExtMapper;
|
private BpmTaskExtMapper taskExtMapper;
|
||||||
@Resource
|
|
||||||
private BpmMessageService messageService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
|
public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
|
||||||
// 查询待办任务
|
// 查询待办任务
|
||||||
TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己
|
TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己
|
||||||
.orderByTaskCreateTime().desc(); // 创建时间倒序
|
.orderByTaskCreateTime().desc(); // 创建时间倒序
|
||||||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||||
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
||||||
}
|
}
|
||||||
|
@ -91,21 +104,21 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
|
|
||||||
// 获得 ProcessInstance Map
|
// 获得 ProcessInstance Map
|
||||||
Map<String, ProcessInstance> processInstanceMap =
|
Map<String, ProcessInstance> processInstanceMap =
|
||||||
processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId));
|
processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId));
|
||||||
// 获得 User Map
|
// 获得 User Map
|
||||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
||||||
convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
|
convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
|
||||||
// 拼接结果
|
// 拼接结果
|
||||||
return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
|
return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
|
||||||
taskQuery.count());
|
taskQuery.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
|
public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
|
||||||
// 查询已办任务
|
// 查询已办任务
|
||||||
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
|
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
|
||||||
.taskAssignee(String.valueOf(userId)) // 分配给自己
|
.taskAssignee(String.valueOf(userId)) // 分配给自己
|
||||||
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
|
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
|
||||||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||||
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
||||||
}
|
}
|
||||||
|
@ -123,19 +136,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
|
|
||||||
// 获得 TaskExtDO Map
|
// 获得 TaskExtDO Map
|
||||||
List<BpmTaskExtDO> bpmTaskExtDOs =
|
List<BpmTaskExtDO> bpmTaskExtDOs =
|
||||||
taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
|
taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
|
||||||
Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
|
Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
|
||||||
// 获得 ProcessInstance Map
|
// 获得 ProcessInstance Map
|
||||||
Map<String, HistoricProcessInstance> historicProcessInstanceMap =
|
Map<String, HistoricProcessInstance> historicProcessInstanceMap =
|
||||||
processInstanceService.getHistoricProcessInstanceMap(
|
processInstanceService.getHistoricProcessInstanceMap(
|
||||||
convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
|
convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
|
||||||
// 获得 User Map
|
// 获得 User Map
|
||||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
||||||
convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
|
convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
|
||||||
// 拼接结果
|
// 拼接结果
|
||||||
return new PageResult<>(
|
return new PageResult<>(
|
||||||
BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
|
BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
|
||||||
taskQuery.count());
|
taskQuery.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -176,27 +189,58 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
|
public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
|
||||||
// 校验任务存在
|
// 1.1 校验任务存在
|
||||||
Task task = checkTask(userId, reqVO.getId());
|
Task task = validateTask(userId, reqVO.getId());
|
||||||
// 校验流程实例存在
|
// 1.2 校验流程实例存在
|
||||||
ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 情况一:被委派的任务,不调用 complete 去完成任务
|
||||||
|
if (DelegationState.PENDING.equals(task.getDelegationState())) {
|
||||||
|
approveDelegateTask(reqVO, task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况二:自己审批的任务,调用 complete 去完成任务
|
||||||
// 完成任务,审批通过
|
// 完成任务,审批通过
|
||||||
taskService.complete(task.getId(), instance.getProcessVariables());
|
taskService.complete(task.getId(), instance.getProcessVariables());
|
||||||
|
|
||||||
// 更新任务拓展表为通过
|
// 更新任务拓展表为通过
|
||||||
taskExtMapper.updateByTaskId(
|
taskExtMapper.updateByTaskId(
|
||||||
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
|
||||||
.setReason(reqVO.getReason()));
|
.setReason(reqVO.getReason()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批被委派的任务
|
||||||
|
*
|
||||||
|
* @param reqVO 前端请求参数,包含当前任务ID,审批意见等
|
||||||
|
* @param task 当前被审批的任务
|
||||||
|
*/
|
||||||
|
private void approveDelegateTask(BpmTaskApproveReqVO reqVO, Task task) {
|
||||||
|
// 1. 添加审批意见
|
||||||
|
AdminUserRespDTO currentUser = adminUserApi.getUser(WebFrameworkUtils.getLoginUserId());
|
||||||
|
AdminUserRespDTO sourceApproveUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner()));
|
||||||
|
Assert.notNull(sourceApproveUser, "委派任务找不到原审批人,需要检查数据");
|
||||||
|
String comment = StrUtil.format("[{}]完成委派任务,任务重新回到[{}]手中,审批意见为:{}", currentUser.getNickname(),
|
||||||
|
sourceApproveUser.getNickname(), reqVO.getReason());
|
||||||
|
taskService.addComment(reqVO.getId(), task.getProcessInstanceId(),
|
||||||
|
BpmProcessInstanceResultEnum.DELEGATE.getResult().toString(), comment);
|
||||||
|
|
||||||
|
// 2.1 调用 resolveTask 完成任务。
|
||||||
|
// 底层调用 TaskHelper.changeTaskAssignee(task, task.getOwner()):将 owner 设置为 assignee
|
||||||
|
taskService.resolveTask(task.getId());
|
||||||
|
// 2.2 更新任务拓展表为【处理中】
|
||||||
|
taskExtMapper.updateByTaskId(
|
||||||
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult())
|
||||||
|
.setReason(reqVO.getReason()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
|
public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
|
||||||
Task task = checkTask(userId, reqVO.getId());
|
Task task = validateTask(userId, reqVO.getId());
|
||||||
// 校验流程实例存在
|
// 校验流程实例存在
|
||||||
ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
|
@ -208,14 +252,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
|
|
||||||
// 更新任务拓展表为不通过
|
// 更新任务拓展表为不通过
|
||||||
taskExtMapper.updateByTaskId(
|
taskExtMapper.updateByTaskId(
|
||||||
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
|
||||||
.setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
|
.setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) {
|
public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) {
|
||||||
// 校验任务存在
|
// 校验任务存在
|
||||||
Task task = checkTask(userId, reqVO.getId());
|
Task task = validateTask(userId, reqVO.getId());
|
||||||
// 更新负责人
|
// 更新负责人
|
||||||
updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId());
|
updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId());
|
||||||
}
|
}
|
||||||
|
@ -231,13 +275,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
* @param userId 用户 id
|
* @param userId 用户 id
|
||||||
* @param taskId task id
|
* @param taskId task id
|
||||||
*/
|
*/
|
||||||
private Task checkTask(Long userId, String taskId) {
|
private Task validateTask(Long userId, String taskId) {
|
||||||
Task task = getTask(taskId);
|
Task task = getTask(taskId);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);
|
throw exception(TASK_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {
|
if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {
|
||||||
throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
|
throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
|
||||||
}
|
}
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +289,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
@Override
|
@Override
|
||||||
public void createTaskExt(Task task) {
|
public void createTaskExt(Task task) {
|
||||||
BpmTaskExtDO taskExtDO =
|
BpmTaskExtDO taskExtDO =
|
||||||
BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
||||||
taskExtMapper.insert(taskExtDO);
|
taskExtMapper.insert(taskExtDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,27 +337,183 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
@Override
|
@Override
|
||||||
public void updateTaskExtAssign(Task task) {
|
public void updateTaskExtAssign(Task task) {
|
||||||
BpmTaskExtDO taskExtDO =
|
BpmTaskExtDO taskExtDO =
|
||||||
new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
|
new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
|
||||||
taskExtMapper.updateByTaskId(taskExtDO);
|
taskExtMapper.updateByTaskId(taskExtDO);
|
||||||
// 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
|
// 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
|
||||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||||
@Override
|
@Override
|
||||||
public void afterCommit() {
|
public void afterCommit() {
|
||||||
ProcessInstance processInstance =
|
ProcessInstance processInstance =
|
||||||
processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
||||||
AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
|
AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
|
||||||
messageService.sendMessageWhenTaskAssigned(
|
messageService.sendMessageWhenTaskAssigned(
|
||||||
BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
|
BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task getTask(String id) {
|
private Task getTask(String id) {
|
||||||
return taskService.createTaskQuery().taskId(id).singleResult();
|
Task task = taskService.createTaskQuery().taskId(id).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw exception(TASK_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoricTaskInstance getHistoricTask(String id) {
|
private HistoricTaskInstance getHistoricTask(String id) {
|
||||||
return historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
|
return historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId) {
|
||||||
|
// 1. 校验当前任务 task 存在
|
||||||
|
Task task = getTask(taskId);
|
||||||
|
if (task == null) {
|
||||||
|
throw exception(TASK_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 根据流程定义获取流程模型信息
|
||||||
|
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
||||||
|
FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||||
|
if (source == null) {
|
||||||
|
throw exception(TASK_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.1 查询该任务的前置任务节点的 key 集合
|
||||||
|
List<UserTask> previousUserList = BpmnModelUtils.getPreviousUserTaskList(source, null, null);
|
||||||
|
if (CollUtil.isEmpty(previousUserList)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
// 2.2 过滤:只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回
|
||||||
|
previousUserList.removeIf(userTask -> !BpmnModelUtils.isSequentialReachable(source, userTask, null));
|
||||||
|
return BpmTaskConvert.INSTANCE.convertList(previousUserList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void returnTask(Long userId, BpmTaskReturnReqVO reqVO) {
|
||||||
|
// 1.1 当前任务 task
|
||||||
|
Task task = validateTask(userId, reqVO.getId());
|
||||||
|
if (task.isSuspended()) {
|
||||||
|
throw exception(TASK_IS_PENDING);
|
||||||
|
}
|
||||||
|
// 1.2 校验源头和目标节点的关系,并返回目标元素
|
||||||
|
FlowElement targetElement = validateTargetTaskCanReturn(task.getTaskDefinitionKey(), reqVO.getTargetDefinitionKey(), task.getProcessDefinitionId());
|
||||||
|
|
||||||
|
// 2. 调用 flowable 框架的回退逻辑
|
||||||
|
returnTask0(task, targetElement, reqVO);
|
||||||
|
|
||||||
|
// 3. 更新任务扩展表
|
||||||
|
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
|
||||||
|
.setResult(BpmProcessInstanceResultEnum.BACK.getResult())
|
||||||
|
.setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退流程节点时,校验目标任务节点是否可回退
|
||||||
|
*
|
||||||
|
* @param sourceKey 当前任务节点 Key
|
||||||
|
* @param targetKey 目标任务节点 key
|
||||||
|
* @param processDefinitionId 当前流程定义 ID
|
||||||
|
* @return 目标任务节点元素
|
||||||
|
*/
|
||||||
|
private FlowElement validateTargetTaskCanReturn(String sourceKey, String targetKey, String processDefinitionId) {
|
||||||
|
// 1.1 获取流程模型信息
|
||||||
|
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(processDefinitionId);
|
||||||
|
// 1.3 获取当前任务节点元素
|
||||||
|
FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, sourceKey);
|
||||||
|
// 1.3 获取跳转的节点元素
|
||||||
|
FlowElement target = BpmnModelUtils.getFlowElementById(bpmnModel, targetKey);
|
||||||
|
if (target == null) {
|
||||||
|
throw exception(TASK_TARGET_NODE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2 只有串行可到达的节点,才可以回退。类似非串行、子流程无法退回
|
||||||
|
if (!BpmnModelUtils.isSequentialReachable(source, target, null)) {
|
||||||
|
throw exception(TASK_RETURN_FAIL_SOURCE_TARGET_ERROR);
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行回退逻辑
|
||||||
|
*
|
||||||
|
* @param currentTask 当前回退的任务
|
||||||
|
* @param targetElement 需要回退到的目标任务
|
||||||
|
* @param reqVO 前端参数封装
|
||||||
|
*/
|
||||||
|
public void returnTask0(Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
|
||||||
|
// 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveActivityIdsToSingleActivityId 回撤
|
||||||
|
// 1.1 获取所有正常进行的任务节点 Key
|
||||||
|
List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
|
||||||
|
List<String> runTaskKeyList = convertList(taskList, Task::getTaskDefinitionKey);
|
||||||
|
// 1.2 通过 targetElement 的出口连线,计算在 runTaskKeyList 有哪些 key 需要被撤回
|
||||||
|
// 为什么不直接使用 runTaskKeyList 呢?因为可能存在多个审批分支,例如说:A -> B -> C 和 D -> F,而只要 C 撤回到 A,需要排除掉 F
|
||||||
|
List<UserTask> returnUserTaskList = BpmnModelUtils.iteratorFindChildUserTasks(targetElement, runTaskKeyList, null, null);
|
||||||
|
List<String> returnTaskKeyList = convertList(returnUserTaskList, UserTask::getId);
|
||||||
|
|
||||||
|
// 2. 给当前要被回退的 task 数组,设置回退意见
|
||||||
|
taskList.forEach(task -> {
|
||||||
|
// 需要排除掉,不需要设置回退意见的任务
|
||||||
|
if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
taskService.addComment(task.getId(), currentTask.getProcessInstanceId(),
|
||||||
|
BpmProcessInstanceResultEnum.BACK.getResult().toString(), reqVO.getReason());
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. 执行驳回
|
||||||
|
runtimeService.createChangeActivityStateBuilder()
|
||||||
|
.processInstanceId(currentTask.getProcessInstanceId())
|
||||||
|
.moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多)
|
||||||
|
reqVO.getTargetDefinitionKey()) // targetKey 跳转到的节点(1)
|
||||||
|
.changeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void delegateTask(BpmTaskDelegateReqVO reqVO, Long userId) {
|
||||||
|
// 1.1 校验任务
|
||||||
|
Task task = validateTaskCanDelegate(userId, reqVO);
|
||||||
|
// 1.2 校验目标用户存在
|
||||||
|
AdminUserRespDTO delegateUser = adminUserApi.getUser(reqVO.getDelegateUserId());
|
||||||
|
if (delegateUser == null) {
|
||||||
|
throw exception(TASK_DELEGATE_FAIL_USER_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 添加审批意见
|
||||||
|
AdminUserRespDTO currentUser = adminUserApi.getUser(userId);
|
||||||
|
String comment = StrUtil.format("[{}]将任务委派给[{}],委派理由为:{}", currentUser.getNickname(),
|
||||||
|
delegateUser.getNickname(), reqVO.getReason());
|
||||||
|
String taskId = reqVO.getId();
|
||||||
|
// TODO 海:后面改;感觉 comment 应该 type 做个枚举;不和 result 耦合在一起;
|
||||||
|
taskService.addComment(taskId, task.getProcessInstanceId(),
|
||||||
|
BpmProcessInstanceResultEnum.DELEGATE.getResult().toString(), comment);
|
||||||
|
|
||||||
|
// 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
|
||||||
|
taskService.setOwner(taskId, task.getAssignee());
|
||||||
|
// 3.2 执行委派,将任务委派给 receiveId
|
||||||
|
taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
|
||||||
|
// 3.3 更新任务拓展表为【委派】
|
||||||
|
taskExtMapper.updateByTaskId(
|
||||||
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.DELEGATE.getResult())
|
||||||
|
.setReason(reqVO.getReason()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验任务委派参数
|
||||||
|
*
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param reqVO 任务编号,接收人ID
|
||||||
|
* @return 当前任务信息
|
||||||
|
*/
|
||||||
|
private Task validateTaskCanDelegate(Long userId, BpmTaskDelegateReqVO reqVO) {
|
||||||
|
// 校验任务
|
||||||
|
Task task = validateTask(userId, reqVO.getId());
|
||||||
|
// 校验当前审批人和被委派人不是同一人
|
||||||
|
if (task.getAssignee().equals(reqVO.getDelegateUserId().toString())) {
|
||||||
|
throw exception(TASK_DELEGATE_FAIL_USER_REPEAT);
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,49 +9,49 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 参数配置 1001000000 ==========
|
// ========== 参数配置 1-001-000-000 ==========
|
||||||
ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1001000001, "参数配置不存在");
|
ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1_001_000_001, "参数配置不存在");
|
||||||
ErrorCode CONFIG_KEY_DUPLICATE = new ErrorCode(1001000002, "参数配置 key 重复");
|
ErrorCode CONFIG_KEY_DUPLICATE = new ErrorCode(1_001_000_002, "参数配置 key 重复");
|
||||||
ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1001000003, "不能删除类型为系统内置的参数配置");
|
ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1_001_000_003, "不能删除类型为系统内置的参数配置");
|
||||||
ErrorCode CONFIG_GET_VALUE_ERROR_IF_VISIBLE = new ErrorCode(1001000004, "获取参数配置失败,原因:不允许获取不可见配置");
|
ErrorCode CONFIG_GET_VALUE_ERROR_IF_VISIBLE = new ErrorCode(1_001_000_004, "获取参数配置失败,原因:不允许获取不可见配置");
|
||||||
|
|
||||||
// ========== 定时任务 1001001000 ==========
|
// ========== 定时任务 1-001-001-000 ==========
|
||||||
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1001001000, "定时任务不存在");
|
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1_001_001_000, "定时任务不存在");
|
||||||
ErrorCode JOB_HANDLER_EXISTS = new ErrorCode(1001001001, "定时任务的处理器已经存在");
|
ErrorCode JOB_HANDLER_EXISTS = new ErrorCode(1_001_001_001, "定时任务的处理器已经存在");
|
||||||
ErrorCode JOB_CHANGE_STATUS_INVALID = new ErrorCode(1001001002, "只允许修改为开启或者关闭状态");
|
ErrorCode JOB_CHANGE_STATUS_INVALID = new ErrorCode(1_001_001_002, "只允许修改为开启或者关闭状态");
|
||||||
ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1001001003, "定时任务已经处于该状态,无需修改");
|
ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1_001_001_003, "定时任务已经处于该状态,无需修改");
|
||||||
ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1001001004, "只有开启状态的任务,才可以修改");
|
ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1_001_001_004, "只有开启状态的任务,才可以修改");
|
||||||
ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1001001005, "CRON 表达式不正确");
|
ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1_001_001_005, "CRON 表达式不正确");
|
||||||
|
|
||||||
// ========== API 错误日志 1001002000 ==========
|
// ========== API 错误日志 1-001-002-000 ==========
|
||||||
ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在");
|
ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1_001_002_000, "API 错误日志不存在");
|
||||||
ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理");
|
ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1_001_002_001, "API 错误日志已处理");
|
||||||
|
|
||||||
// ========= 文件相关 1001003000=================
|
// ========= 文件相关 1-001-003-000 =================
|
||||||
ErrorCode FILE_PATH_EXISTS = new ErrorCode(1001003000, "文件路径已存在");
|
ErrorCode FILE_PATH_EXISTS = new ErrorCode(1_001_003_000, "文件路径已存在");
|
||||||
ErrorCode FILE_NOT_EXISTS = new ErrorCode(1001003001, "文件不存在");
|
ErrorCode FILE_NOT_EXISTS = new ErrorCode(1_001_003_001, "文件不存在");
|
||||||
ErrorCode FILE_IS_EMPTY = new ErrorCode(1001003002, "文件为空");
|
ErrorCode FILE_IS_EMPTY = new ErrorCode(1_001_003_002, "文件为空");
|
||||||
|
|
||||||
// ========== 代码生成器 1001004000 ==========
|
// ========== 代码生成器 1-001-004-000 ==========
|
||||||
ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1003001000, "表定义已经存在");
|
ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1_003_001_000, "表定义已经存在");
|
||||||
ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1003001001, "导入的表不存在");
|
ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1_003_001_001, "导入的表不存在");
|
||||||
ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1003001002, "导入的字段不存在");
|
ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1_003_001_002, "导入的字段不存在");
|
||||||
ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1003001004, "表定义不存在");
|
ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_004, "表定义不存在");
|
||||||
ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1003001005, "字段义不存在");
|
ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_005, "字段义不存在");
|
||||||
ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1003001006, "同步的字段不存在");
|
ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1_003_001_006, "同步的字段不存在");
|
||||||
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1003001007, "同步失败,不存在改变");
|
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变");
|
||||||
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1003001008, "数据库的表注释未填写");
|
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写");
|
||||||
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1003001009, "数据库的表字段({})注释未填写");
|
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写");
|
||||||
|
|
||||||
// ========== 字典类型(测试)1001005000 ==========
|
// ========== 字典类型(测试)1-001-005-000 ==========
|
||||||
ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1001005000, "测试示例不存在");
|
ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1_001_005_000, "测试示例不存在");
|
||||||
|
|
||||||
// ========== 文件配置 1001006000 ==========
|
// ========== 文件配置 1-001-006-000 ==========
|
||||||
ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1001006000, "文件配置不存在");
|
ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在");
|
||||||
ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1001006001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件");
|
ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1_001_006_001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件");
|
||||||
|
|
||||||
// ========== 数据源配置 1001007000 ==========
|
// ========== 数据源配置 1-001-007-000 ==========
|
||||||
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1001007000, "数据源配置不存在");
|
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在");
|
||||||
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1001007001, "数据源配置不正确,无法进行连接");
|
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
|
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
|
||||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
||||||
|
@ -21,7 +18,8 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
||||||
.orderByDesc(FileConfigDO::getId));
|
.orderByDesc(FileConfigDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}")
|
default FileConfigDO selectByMaster() {
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
return selectOne(FileConfigDO::getMaster, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package cn.iocoder.yudao.module.infra.service.file;
|
package cn.iocoder.yudao.module.infra.service.file;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||||
import cn.iocoder.yudao.framework.file.core.client.FileClient;
|
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
|
||||||
import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert;
|
import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert;
|
||||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
||||||
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
|
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Validator;
|
import javax.validation.Validator;
|
||||||
import java.time.LocalDateTime;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
|
||||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER;
|
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER;
|
||||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS;
|
||||||
|
|
||||||
|
@ -46,19 +44,29 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FileConfigServiceImpl implements FileConfigService {
|
public class FileConfigServiceImpl implements FileConfigService {
|
||||||
|
|
||||||
@Resource
|
private static final Long CACHE_MASTER_ID = 0L;
|
||||||
private FileClientFactory fileClientFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件配置的缓存
|
* {@link FileClient} 缓存,通过它异步刷新 fileClientFactory
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private List<FileConfigDO> fileConfigCache;
|
private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
|
||||||
/**
|
new CacheLoader<Long, FileClient>() {
|
||||||
* Master FileClient 对象,有且仅有一个,即 {@link FileConfigDO#getMaster()} 对应的
|
|
||||||
*/
|
@Override
|
||||||
@Getter
|
public FileClient load(Long id) {
|
||||||
private FileClient masterFileClient;
|
FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
|
||||||
|
fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
|
||||||
|
if (config != null) {
|
||||||
|
fileClientFactory.createOrUpdateFileClient(id, config.getStorage(), config.getConfig());
|
||||||
|
}
|
||||||
|
return fileClientFactory.getFileClient(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FileClientFactory fileClientFactory;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private FileConfigMapper fileConfigMapper;
|
private FileConfigMapper fileConfigMapper;
|
||||||
|
@ -66,53 +74,12 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
@Resource
|
@Resource
|
||||||
private Validator validator;
|
private Validator validator;
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void initLocalCache() {
|
|
||||||
// 第一步:查询数据
|
|
||||||
List<FileConfigDO> configs = fileConfigMapper.selectList();
|
|
||||||
log.info("[initLocalCache][缓存文件配置,数量为:{}]", configs.size());
|
|
||||||
|
|
||||||
// 第二步:构建缓存:创建或更新文件 Client
|
|
||||||
configs.forEach(config -> {
|
|
||||||
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
|
|
||||||
// 如果是 master,进行设置
|
|
||||||
if (Boolean.TRUE.equals(config.getMaster())) {
|
|
||||||
masterFileClient = fileClientFactory.getFileClient(config.getId());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.fileConfigCache = configs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过定时任务轮询,刷新缓存
|
|
||||||
*
|
|
||||||
* 目的:多节点部署时,通过轮询”通知“所有节点,进行刷新
|
|
||||||
*/
|
|
||||||
@Scheduled(initialDelay = 60, fixedRate = 60, timeUnit = TimeUnit.SECONDS)
|
|
||||||
public void refreshLocalCache() {
|
|
||||||
// 情况一:如果缓存里没有数据,则直接刷新缓存
|
|
||||||
if (CollUtil.isEmpty(fileConfigCache)) {
|
|
||||||
initLocalCache();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 情况二,如果缓存里数据,则通过 updateTime 判断是否有数据变更,有变更则刷新缓存
|
|
||||||
LocalDateTime maxTime = CollectionUtils.getMaxValue(fileConfigCache, FileConfigDO::getUpdateTime);
|
|
||||||
if (fileConfigMapper.selectCountByUpdateTimeGt(maxTime) > 0) {
|
|
||||||
initLocalCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createFileConfig(FileConfigCreateReqVO createReqVO) {
|
public Long createFileConfig(FileConfigCreateReqVO createReqVO) {
|
||||||
// 插入
|
|
||||||
FileConfigDO fileConfig = FileConfigConvert.INSTANCE.convert(createReqVO)
|
FileConfigDO fileConfig = FileConfigConvert.INSTANCE.convert(createReqVO)
|
||||||
.setConfig(parseClientConfig(createReqVO.getStorage(), createReqVO.getConfig()))
|
.setConfig(parseClientConfig(createReqVO.getStorage(), createReqVO.getConfig()))
|
||||||
.setMaster(false); // 默认非 master
|
.setMaster(false); // 默认非 master
|
||||||
fileConfigMapper.insert(fileConfig);
|
fileConfigMapper.insert(fileConfig);
|
||||||
|
|
||||||
// 刷新缓存
|
|
||||||
initLocalCache();
|
|
||||||
return fileConfig.getId();
|
return fileConfig.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +92,8 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
.setConfig(parseClientConfig(config.getStorage(), updateReqVO.getConfig()));
|
.setConfig(parseClientConfig(config.getStorage(), updateReqVO.getConfig()));
|
||||||
fileConfigMapper.updateById(updateObj);
|
fileConfigMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 刷新缓存
|
// 清空缓存
|
||||||
initLocalCache();
|
clearCache(config.getId(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,8 +106,8 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
// 更新
|
// 更新
|
||||||
fileConfigMapper.updateById(new FileConfigDO().setId(id).setMaster(true));
|
fileConfigMapper.updateById(new FileConfigDO().setId(id).setMaster(true));
|
||||||
|
|
||||||
// 刷新缓存
|
// 清空缓存
|
||||||
initLocalCache();
|
clearCache(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileClientConfig parseClientConfig(Integer storage, Map<String, Object> config) {
|
private FileClientConfig parseClientConfig(Integer storage, Map<String, Object> config) {
|
||||||
|
@ -164,8 +131,23 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
// 删除
|
// 删除
|
||||||
fileConfigMapper.deleteById(id);
|
fileConfigMapper.deleteById(id);
|
||||||
|
|
||||||
// 刷新缓存
|
// 清空缓存
|
||||||
initLocalCache();
|
clearCache(id, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空指定文件配置
|
||||||
|
*
|
||||||
|
* @param id 配置编号
|
||||||
|
* @param master 是否主配置
|
||||||
|
*/
|
||||||
|
private void clearCache(Long id, Boolean master) {
|
||||||
|
if (id != null) {
|
||||||
|
clientCache.invalidate(id);
|
||||||
|
}
|
||||||
|
if (Boolean.TRUE.equals(master)) {
|
||||||
|
clientCache.invalidate(CACHE_MASTER_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileConfigDO validateFileConfigExists(Long id) {
|
private FileConfigDO validateFileConfigExists(Long id) {
|
||||||
|
@ -192,12 +174,17 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
validateFileConfigExists(id);
|
validateFileConfigExists(id);
|
||||||
// 上传文件
|
// 上传文件
|
||||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
||||||
return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg");
|
return getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileClient getFileClient(Long id) {
|
public FileClient getFileClient(Long id) {
|
||||||
return fileClientFactory.getFileClient(id);
|
return clientCache.getUnchecked(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileClient getMasterFileClient() {
|
||||||
|
return clientCache.getUnchecked(CACHE_MASTER_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,27 +3,27 @@ import { defHttp } from '@/utils/http/axios'
|
||||||
|
|
||||||
// 查询${table.classComment}列表
|
// 查询${table.classComment}列表
|
||||||
export function get${simpleClassName}Page(params) {
|
export function get${simpleClassName}Page(params) {
|
||||||
return defHttp.get({ url: '${baseURL}/page', params })
|
return defHttp.get({ url: '${baseURL}/page', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询${table.classComment}详情
|
// 查询${table.classComment}详情
|
||||||
export function get${simpleClassName}(id: number) {
|
export function get${simpleClassName}(id: number) {
|
||||||
return defHttp.get({ url: '${baseURL}/get?id=' + id })
|
return defHttp.get({ url: `${baseURL}/get?id=${id}` })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增${table.classComment}
|
// 新增${table.classComment}
|
||||||
export function create${simpleClassName}(data) {
|
export function create${simpleClassName}(data) {
|
||||||
return defHttp.post({ url: '${baseURL}/create', data })
|
return defHttp.post({ url: '${baseURL}/create', data })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改${table.classComment}
|
// 修改${table.classComment}
|
||||||
export function update${simpleClassName}(data) {
|
export function update${simpleClassName}(data) {
|
||||||
return defHttp.put({ url: '${baseURL}/update', data })
|
return defHttp.put({ url: '${baseURL}/update', data })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除${table.classComment}
|
// 删除${table.classComment}
|
||||||
export function delete${simpleClassName}(id: number) {
|
export function delete${simpleClassName}(id: number) {
|
||||||
return defHttp.delete({ url: '${baseURL}/delete?id=' + id })
|
return defHttp.delete({ url: `${baseURL}/delete?id=${id}` })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出${table.classComment} Excel
|
// 导出${table.classComment} Excel
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { BasicColumn, FormSchema, useRender } from '@/components/Table'
|
import type { BasicColumn, FormSchema } from '@/components/Table'
|
||||||
|
import { useRender } from '@/components/Table'
|
||||||
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
|
||||||
|
|
||||||
export const columns: BasicColumn[] = [
|
export const columns: BasicColumn[] = [
|
||||||
|
@ -92,13 +93,13 @@ export const createFormSchema: FormSchema[] = [
|
||||||
#elseif($column.htmlType == "imageUpload")## 图片上传
|
#elseif($column.htmlType == "imageUpload")## 图片上传
|
||||||
component: 'FileUpload',
|
component: 'FileUpload',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
fileType: 'file',
|
fileType: 'image',
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
},
|
},
|
||||||
#elseif($column.htmlType == "fileUpload")## 文件上传
|
#elseif($column.htmlType == "fileUpload")## 文件上传
|
||||||
component: 'FileUpload',
|
component: 'FileUpload',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
fileType: 'image',
|
fileType: 'file',
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
},
|
},
|
||||||
#elseif($column.htmlType == "editor")## 文本编辑器
|
#elseif($column.htmlType == "editor")## 文本编辑器
|
||||||
|
@ -132,6 +133,11 @@ export const createFormSchema: FormSchema[] = [
|
||||||
},
|
},
|
||||||
#elseif($column.htmlType == "datetime")## 时间框
|
#elseif($column.htmlType == "datetime")## 时间框
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
|
componentProps: {
|
||||||
|
showTime: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'x',
|
||||||
|
},
|
||||||
#elseif($column.htmlType == "textarea")## 文本域
|
#elseif($column.htmlType == "textarea")## 文本域
|
||||||
component: 'InputTextArea',
|
component: 'InputTextArea',
|
||||||
#end
|
#end
|
||||||
|
@ -154,7 +160,7 @@ export const updateFormSchema: FormSchema[] = [
|
||||||
#set ($javaField = $column.javaField)
|
#set ($javaField = $column.javaField)
|
||||||
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
#set ($comment = $column.columnComment)
|
#set ($comment = $column.columnComment)
|
||||||
#if (!$column.primaryKey)## 忽略主键,不用在表单里
|
#if (!$column.primaryKey)## 忽略主键,不用在表单里
|
||||||
{
|
{
|
||||||
label: '${comment}',
|
label: '${comment}',
|
||||||
field: '${javaField}',
|
field: '${javaField}',
|
||||||
|
@ -164,45 +170,57 @@ export const updateFormSchema: FormSchema[] = [
|
||||||
#if ($column.htmlType == "input")
|
#if ($column.htmlType == "input")
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
#elseif($column.htmlType == "imageUpload")## 图片上传
|
#elseif($column.htmlType == "imageUpload")## 图片上传
|
||||||
component: 'Upload',
|
component: 'FileUpload',
|
||||||
|
componentProps: {
|
||||||
|
fileType: 'image',
|
||||||
|
maxCount: 1,
|
||||||
|
},
|
||||||
#elseif($column.htmlType == "fileUpload")## 文件上传
|
#elseif($column.htmlType == "fileUpload")## 文件上传
|
||||||
component: 'Upload',
|
component: 'FileUpload',
|
||||||
#elseif($column.htmlType == "editor")## 文本编辑器
|
componentProps: {
|
||||||
component: 'Editor',
|
fileType: 'file',
|
||||||
|
maxCount: 1,
|
||||||
|
},
|
||||||
|
#elseif($column.htmlType == "editor")## 文本编辑器component: 'Editor',
|
||||||
#elseif($column.htmlType == "select")## 下拉框
|
#elseif($column.htmlType == "select")## 下拉框
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
#if ("" != $dictType)## 有数据字典
|
#if ("" != $dictType)## 有数据字典
|
||||||
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
|
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
|
||||||
#else##没数据字典
|
#else##没数据字典
|
||||||
options:[],
|
options:[],
|
||||||
#end
|
#end
|
||||||
},
|
},
|
||||||
#elseif($column.htmlType == "checkbox")## 多选框
|
#elseif($column.htmlType == "checkbox")## 多选框
|
||||||
component: 'Checkbox',
|
component: 'Checkbox',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
#if ("" != $dictType)## 有数据字典
|
#if ("" != $dictType)## 有数据字典
|
||||||
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
|
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
|
||||||
#else##没数据字典
|
#else##没数据字典
|
||||||
options:[],
|
options:[],
|
||||||
#end
|
#end
|
||||||
},
|
},
|
||||||
#elseif($column.htmlType == "radio")## 单选框
|
#elseif($column.htmlType == "radio")## 单选框
|
||||||
component: 'RadioButtonGroup',
|
component: 'RadioButtonGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
#if ("" != $dictType)## 有数据字典
|
#if ("" != $dictType)## 有数据字典
|
||||||
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
|
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'),
|
||||||
#else##没数据字典
|
#else##没数据字典
|
||||||
options:[],
|
options:[],
|
||||||
#end
|
#end
|
||||||
},
|
},
|
||||||
#elseif($column.htmlType == "datetime")## 时间框
|
#elseif($column.htmlType == "datetime")## 时间框
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
|
componentProps: {
|
||||||
|
showTime: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'x',
|
||||||
|
},
|
||||||
#elseif($column.htmlType == "textarea")## 文本域
|
#elseif($column.htmlType == "textarea")## 文本域
|
||||||
component: 'InputTextArea',
|
component: 'InputTextArea',
|
||||||
#end
|
#end
|
||||||
},
|
},
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
]
|
]
|
|
@ -9,9 +9,10 @@ import { create${simpleClassName}, get${simpleClassName}, update${simpleClassNam
|
||||||
|
|
||||||
defineOptions({ name: '${table.className}Modal' })
|
defineOptions({ name: '${table.className}Modal' })
|
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'register'])
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { createMessage } = useMessage()
|
const { createMessage } = useMessage()
|
||||||
const emit = defineEmits(['success', 'register'])
|
|
||||||
const isUpdate = ref(true)
|
const isUpdate = ref(true)
|
||||||
|
|
||||||
const [registerForm, { setFieldsValue, resetFields, resetSchema, validate }] = useForm({
|
const [registerForm, { setFieldsValue, resetFields, resetSchema, validate }] = useForm({
|
||||||
|
@ -37,11 +38,11 @@ async function handleSubmit() {
|
||||||
try {
|
try {
|
||||||
const values = await validate()
|
const values = await validate()
|
||||||
setModalProps({ confirmLoading: true })
|
setModalProps({ confirmLoading: true })
|
||||||
if (unref(isUpdate)) {
|
if (unref(isUpdate))
|
||||||
await update${simpleClassName}(values)
|
await update${simpleClassName}(values)
|
||||||
} else {
|
else
|
||||||
await create${simpleClassName}(values)
|
await create${simpleClassName}(values)
|
||||||
}
|
|
||||||
closeModal()
|
closeModal()
|
||||||
emit('success')
|
emit('success')
|
||||||
createMessage.success(t('common.saveSuccessText'))
|
createMessage.success(t('common.saveSuccessText'))
|
||||||
|
@ -51,7 +52,7 @@ async function handleSubmit() {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<BasicModal v-bind="$attrs" @register="registerModal" :title="isUpdate ? t('action.edit') : t('action.create')" @ok="handleSubmit">
|
<BasicModal v-bind="$attrs" :title="isUpdate ? t('action.edit') : t('action.create')" @register="registerModal" @ok="handleSubmit">
|
||||||
<BasicForm @register="registerForm" />
|
<BasicForm @register="registerForm" />
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
</template>
|
</template>
|
|
@ -1,12 +1,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ${simpleClassName}Modal from './${simpleClassName}Modal.vue'
|
import ${ simpleClassName }Modal from './${simpleClassName}Modal.vue'
|
||||||
import { columns, searchFormSchema } from './${classNameVar}.data'
|
import { columns, searchFormSchema } from './${classNameVar}.data'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { useMessage } from '@/hooks/web/useMessage'
|
import { useMessage } from '@/hooks/web/useMessage'
|
||||||
import { useModal } from '@/components/Modal'
|
import { useModal } from '@/components/Modal'
|
||||||
import { IconEnum } from '@/enums/appEnum'
|
import { IconEnum } from '@/enums/appEnum'
|
||||||
import { BasicTable, useTable, TableAction } from '@/components/Table'
|
import { BasicTable, useTable, TableAction } from '@/components/Table'
|
||||||
import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${classNameVar}'
|
import { delete${ simpleClassName }, export${ simpleClassName }, get${ simpleClassName } Page } from '@/api/${table.moduleName}/${classNameVar}'
|
||||||
|
|
||||||
defineOptions({ name: '${table.className}' })
|
defineOptions({ name: '${table.className}' })
|
||||||
|
|
||||||
|
@ -16,17 +16,17 @@ const [registerModal, { openModal }] = useModal()
|
||||||
|
|
||||||
const [registerTable, { getForm, reload }] = useTable({
|
const [registerTable, { getForm, reload }] = useTable({
|
||||||
title: '${table.classComment}列表',
|
title: '${table.classComment}列表',
|
||||||
api: get${simpleClassName}Page,
|
api: get${ simpleClassName }Page,
|
||||||
columns,
|
columns,
|
||||||
formConfig: { labelWidth: 120, schemas: searchFormSchema },
|
formConfig: { labelWidth: 120, schemas: searchFormSchema },
|
||||||
useSearchForm: true,
|
useSearchForm: true,
|
||||||
showTableSetting: true,
|
showTableSetting: true,
|
||||||
actionColumn: {
|
actionColumn: {
|
||||||
width: 140,
|
width: 140,
|
||||||
title: t('common.action'),
|
title: t('common.action'),
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleCreate() {
|
function handleCreate() {
|
||||||
|
@ -43,14 +43,14 @@ async function handleExport() {
|
||||||
iconType: 'warning',
|
iconType: 'warning',
|
||||||
content: t('common.exportMessage'),
|
content: t('common.exportMessage'),
|
||||||
async onOk() {
|
async onOk() {
|
||||||
await export${simpleClassName}(getForm().getFieldsValue())
|
await export${ simpleClassName } (getForm().getFieldsValue())
|
||||||
createMessage.success(t('common.exportSuccessText'))
|
createMessage.success(t('common.exportSuccessText'))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDelete(record: Recordable) {
|
async function handleDelete(record: Recordable) {
|
||||||
await delete${simpleClassName}(record.id)
|
await delete${ simpleClassName } (record.id)
|
||||||
createMessage.success(t('common.delSuccessText'))
|
createMessage.success(t('common.delSuccessText'))
|
||||||
reload()
|
reload()
|
||||||
}
|
}
|
||||||
|
@ -89,4 +89,4 @@ async function handleDelete(record: Recordable) {
|
||||||
</BasicTable>
|
</BasicTable>
|
||||||
<${simpleClassName}Modal @register="registerModal" @success="reload()" />
|
<${simpleClassName}Modal @register="registerModal" @success="reload()" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -59,31 +59,6 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
@MockBean
|
@MockBean
|
||||||
private FileClientFactory fileClientFactory;
|
private FileClientFactory fileClientFactory;
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInitLocalCache() {
|
|
||||||
// mock 数据
|
|
||||||
FileConfigDO configDO1 = randomFileConfigDO().setId(1L).setMaster(true);
|
|
||||||
fileConfigMapper.insert(configDO1);
|
|
||||||
FileConfigDO configDO2 = randomFileConfigDO().setId(2L).setMaster(false);
|
|
||||||
fileConfigMapper.insert(configDO2);
|
|
||||||
// mock fileClientFactory 获得 master
|
|
||||||
FileClient masterFileClient = mock(FileClient.class);
|
|
||||||
when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient);
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
fileConfigService.initLocalCache();
|
|
||||||
// 断言 fileClientFactory 调用
|
|
||||||
verify(fileClientFactory).createOrUpdateFileClient(eq(1L),
|
|
||||||
eq(configDO1.getStorage()), eq(configDO1.getConfig()));
|
|
||||||
verify(fileClientFactory).createOrUpdateFileClient(eq(2L),
|
|
||||||
eq(configDO2.getStorage()), eq(configDO2.getConfig()));
|
|
||||||
assertSame(masterFileClient, fileConfigService.getMasterFileClient());
|
|
||||||
// 断言 fileConfigCache 缓存
|
|
||||||
assertEquals(2, fileConfigService.getFileConfigCache().size());
|
|
||||||
assertEquals(configDO1, fileConfigService.getFileConfigCache().get(0));
|
|
||||||
assertEquals(configDO2, fileConfigService.getFileConfigCache().get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateFileConfig_success() {
|
public void testCreateFileConfig_success() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
|
@ -102,6 +77,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
assertFalse(fileConfig.getMaster());
|
assertFalse(fileConfig.getMaster());
|
||||||
assertEquals("/yunai", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
|
assertEquals("/yunai", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
|
||||||
assertEquals("https://www.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
|
assertEquals("https://www.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
|
||||||
|
// 验证 cache
|
||||||
|
assertNull(fileConfigService.getClientCache().getIfPresent(fileConfigId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -125,6 +102,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
assertPojoEquals(reqVO, fileConfig, "config");
|
assertPojoEquals(reqVO, fileConfig, "config");
|
||||||
assertEquals("/yunai2", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
|
assertEquals("/yunai2", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
|
||||||
assertEquals("https://doc.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
|
assertEquals("https://doc.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
|
||||||
|
// 验证 cache
|
||||||
|
assertNull(fileConfigService.getClientCache().getIfPresent(fileConfig.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -149,6 +128,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
// 断言数据
|
// 断言数据
|
||||||
assertTrue(fileConfigMapper.selectById(dbFileConfig.getId()).getMaster());
|
assertTrue(fileConfigMapper.selectById(dbFileConfig.getId()).getMaster());
|
||||||
assertFalse(fileConfigMapper.selectById(masterFileConfig.getId()).getMaster());
|
assertFalse(fileConfigMapper.selectById(masterFileConfig.getId()).getMaster());
|
||||||
|
// 验证 cache
|
||||||
|
assertNull(fileConfigService.getClientCache().getIfPresent(0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -169,6 +150,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
fileConfigService.deleteFileConfig(id);
|
fileConfigService.deleteFileConfig(id);
|
||||||
// 校验数据不存在了
|
// 校验数据不存在了
|
||||||
assertNull(fileConfigMapper.selectById(id));
|
assertNull(fileConfigMapper.selectById(id));
|
||||||
|
// 验证 cache
|
||||||
|
assertNull(fileConfigService.getClientCache().getIfPresent(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -250,14 +233,38 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetFileClient() {
|
public void testGetFileClient() {
|
||||||
|
// mock 数据
|
||||||
|
FileConfigDO fileConfig = randomFileConfigDO().setMaster(false);
|
||||||
|
fileConfigMapper.insert(fileConfig);
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long id = randomLongId();
|
Long id = fileConfig.getId();
|
||||||
// mock 获得 Client
|
// mock 获得 Client
|
||||||
FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
|
FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
|
||||||
when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient);
|
when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient);
|
||||||
|
|
||||||
// 调用,并断言
|
// 调用,并断言
|
||||||
assertSame(fileClient, fileConfigService.getFileClient(id));
|
assertSame(fileClient, fileConfigService.getFileClient(id));
|
||||||
|
// 断言缓存
|
||||||
|
verify(fileClientFactory).createOrUpdateFileClient(eq(id), eq(fileConfig.getStorage()),
|
||||||
|
eq(fileConfig.getConfig()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMasterFileClient() {
|
||||||
|
// mock 数据
|
||||||
|
FileConfigDO fileConfig = randomFileConfigDO().setMaster(true);
|
||||||
|
fileConfigMapper.insert(fileConfig);
|
||||||
|
// 准备参数
|
||||||
|
Long id = fileConfig.getId();
|
||||||
|
// mock 获得 Client
|
||||||
|
FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
|
||||||
|
when(fileClientFactory.getFileClient(eq(0L))).thenReturn(fileClient);
|
||||||
|
|
||||||
|
// 调用,并断言
|
||||||
|
assertSame(fileClient, fileConfigService.getMasterFileClient());
|
||||||
|
// 断言缓存
|
||||||
|
verify(fileClientFactory).createOrUpdateFileClient(eq(0L), eq(fileConfig.getStorage()),
|
||||||
|
eq(fileConfig.getConfig()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileConfigDO randomFileConfigDO() {
|
private FileConfigDO randomFileConfigDO() {
|
||||||
|
|
|
@ -139,4 +139,5 @@ public class FileServiceImplTest extends BaseDbUnitTest {
|
||||||
// 断言
|
// 断言
|
||||||
assertSame(result, content);
|
assertSame(result, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 商品分类相关 1008001000 ============
|
// ========== 商品分类相关 1-008-001-000 ============
|
||||||
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
|
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_008_001_000, "商品分类不存在");
|
||||||
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
|
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_008_001_001, "父分类不存在");
|
||||||
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
|
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_008_001_002, "父分类不能是二级分类");
|
||||||
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
|
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_008_001_003, "存在子分类,无法删除");
|
||||||
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
|
ErrorCode CATEGORY_DISABLED = new ErrorCode(1_008_001_004, "商品分类({})已禁用,无法使用");
|
||||||
ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1008001005, "类别下存在商品,无法删除");
|
ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1_008_001_005, "类别下存在商品,无法删除");
|
||||||
|
|
||||||
// ========== 商品品牌相关编号 1008002000 ==========
|
// ========== 商品品牌相关编号 1-008-002-000 ==========
|
||||||
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
|
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1_008_002_000, "品牌不存在");
|
||||||
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌已禁用");
|
ErrorCode BRAND_DISABLED = new ErrorCode(1_008_002_001, "品牌已禁用");
|
||||||
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
|
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1_008_002_002, "品牌名称已存在");
|
||||||
|
|
||||||
// ========== 商品属性项 1008003000 ==========
|
// ========== 商品属性项 1-008-003-000 ==========
|
||||||
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
|
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1_008_003_000, "属性项不存在");
|
||||||
ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
|
ErrorCode PROPERTY_EXISTS = new ErrorCode(1_008_003_001, "属性项的名称已存在");
|
||||||
ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
|
ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1_008_003_002, "属性项下存在属性值,无法删除");
|
||||||
|
|
||||||
// ========== 商品属性值 1008004000 ==========
|
// ========== 商品属性值 1-008-004-000 ==========
|
||||||
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");
|
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1_008_004_000, "属性值不存在");
|
||||||
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");
|
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1_008_004_001, "属性值的名称已存在");
|
||||||
|
|
||||||
// ========== 商品 SPU 1008005000 ==========
|
// ========== 商品 SPU 1-008-005-000 ==========
|
||||||
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
|
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在");
|
||||||
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
|
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
|
||||||
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
|
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU 不处于上架状态");
|
||||||
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1008005003, "商品 SPU 不处于回收站状态");
|
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_003, "商品 SPU 不处于回收站状态");
|
||||||
|
|
||||||
// ========== 商品 SKU 1008006000 ==========
|
// ========== 商品 SKU 1-008-006-000 ==========
|
||||||
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
|
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1_008_006_000, "商品 SKU 不存在");
|
||||||
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
|
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1_008_006_001, "商品 SKU 的属性组合存在重复");
|
||||||
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");
|
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1_008_006_002, "一个 SPU 下的每个 SKU,其属性项必须一致");
|
||||||
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
|
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1_008_006_003, "一个 SPU 下的每个 SKU,必须不重复");
|
||||||
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
|
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1_008_006_004, "商品 SKU 库存不足");
|
||||||
|
|
||||||
// ========== 商品 评价 1008007000 ==========
|
// ========== 商品 评价 1-008-007-000 ==========
|
||||||
ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品评价不存在");
|
ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1_008_007_000, "商品评价不存在");
|
||||||
ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1008007001, "订单的商品评价已存在");
|
ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1_008_007_001, "订单的商品评价已存在");
|
||||||
|
|
||||||
// ========== 商品 收藏 1008008000 ==========
|
// ========== 商品 收藏 1-008-008-000 ==========
|
||||||
ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏");
|
ErrorCode FAVORITE_EXISTS = new ErrorCode(1_008_008_000, "该商品已经被收藏");
|
||||||
ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1008008001, "商品收藏不存在");
|
ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1_008_008_001, "商品收藏不存在");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,4 +140,5 @@ public class AppProductSpuController {
|
||||||
return price - newPrice;
|
return price - newPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 芋艿:商品的浏览记录;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
|
||||||
import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum;
|
import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum;
|
||||||
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||||
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
||||||
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
@ -48,8 +47,6 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
|
||||||
@Lazy
|
@Lazy
|
||||||
private ProductCommentServiceImpl productCommentService;
|
private ProductCommentServiceImpl productCommentService;
|
||||||
|
|
||||||
@MockBean
|
|
||||||
private TradeOrderApi tradeOrderApi;
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private ProductSpuService productSpuService;
|
private ProductSpuService productSpuService;
|
||||||
@MockBean
|
@MockBean
|
||||||
|
|
|
@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 促销活动相关 1013001000 ============
|
// ========== 促销活动相关 1-013-001-000 ============
|
||||||
ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1013001000, "限时折扣活动不存在");
|
ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_001_000, "限时折扣活动不存在");
|
||||||
ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013001001, "存在商品参加了其它限时折扣活动");
|
ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_001_001, "存在商品参加了其它限时折扣活动");
|
||||||
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013001002, "限时折扣活动已关闭,不能修改");
|
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改");
|
||||||
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1013001003, "限时折扣活动未关闭,不能删除");
|
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
|
||||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013001004, "限时折扣活动已关闭,不能重复关闭");
|
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");
|
||||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013001005, "限时折扣活动已结束,不能关闭");
|
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_001_005, "限时折扣活动已结束,不能关闭");
|
||||||
|
|
||||||
// ========== Banner 相关 1013002000 ============
|
// ========== Banner 相关 1-013-002-000 ============
|
||||||
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1013002000, "Banner 不存在");
|
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在");
|
||||||
|
|
||||||
// ========== Coupon 相关 1013003000 ============
|
// ========== Coupon 相关 1-013-003-000 ============
|
||||||
ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1013003000, "优惠劵没有可使用的商品!");
|
ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1_013_003_000, "优惠劵没有可使用的商品!");
|
||||||
ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1013003001, "所结算的商品中未满足使用的金额");
|
ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1_013_003_001, "所结算的商品中未满足使用的金额");
|
||||||
|
|
||||||
// ========== 优惠劵模板 1013004000 ==========
|
// ========== 优惠劵模板 1-013-004-000 ==========
|
||||||
ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1013004000, "优惠劵模板不存在");
|
ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在");
|
||||||
ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1013004001, "发放数量不能小于已领取数量({})");
|
ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1_013_004_001, "发放数量不能小于已领取数量({})");
|
||||||
ErrorCode COUPON_TEMPLATE_NOT_ENOUGH = new ErrorCode(1013004002, "当前剩余数量不够领取");
|
ErrorCode COUPON_TEMPLATE_NOT_ENOUGH = new ErrorCode(1_013_004_002, "当前剩余数量不够领取");
|
||||||
ErrorCode COUPON_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1013004003, "用户已领取过此优惠券");
|
ErrorCode COUPON_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1_013_004_003, "用户已领取过此优惠券");
|
||||||
ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1013004004, "优惠券已过期");
|
ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1_013_004_004, "优惠券已过期");
|
||||||
ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1013004005, "领取方式不正确");
|
ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1_013_004_005, "领取方式不正确");
|
||||||
|
|
||||||
// ========== 优惠劵 1013005000 ==========
|
// ========== 优惠劵 1-013-005-000 ==========
|
||||||
ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1013005000, "优惠券不存在");
|
ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1_013_005_000, "优惠券不存在");
|
||||||
ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");
|
ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1_013_005_001, "回收优惠劵失败,优惠劵已被使用");
|
||||||
ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");
|
ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1_013_005_002, "优惠劵不处于待使用状态");
|
||||||
ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内");
|
ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1_013_005_003, "优惠券不在使用时间范围内");
|
||||||
ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态");
|
ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1_013_005_004, "优惠劵不是已使用状态");
|
||||||
|
|
||||||
// ========== 满减送活动 1013006000 ==========
|
// ========== 满减送活动 1-013-006-000 ==========
|
||||||
ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1013006000, "满减送活动不存在");
|
ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_006_000, "满减送活动不存在");
|
||||||
ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013006001, "存在商品参加了其它满减送活动");
|
ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_006_001, "存在商品参加了其它满减送活动");
|
||||||
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013006002, "满减送活动已关闭,不能修改");
|
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
|
||||||
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1013006003, "满减送活动未关闭,不能删除");
|
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
|
||||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013006004, "满减送活动已关闭,不能重复关闭");
|
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
|
||||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013006005, "满减送活动已结束,不能关闭");
|
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_006_005, "满减送活动已结束,不能关闭");
|
||||||
|
|
||||||
// ========== TODO 空着 1013007000 ============
|
// ========== TODO 空着 1-013-007-000 ============
|
||||||
|
|
||||||
// ========== 秒杀活动 1013008000 ==========
|
// ========== 秒杀活动 1-013-008-000 ==========
|
||||||
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
|
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
|
||||||
ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
|
ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
|
||||||
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
|
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
|
||||||
|
@ -57,19 +57,19 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
|
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
|
||||||
ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
|
ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
|
||||||
|
|
||||||
// ========== 秒杀时段 1013009000 ==========
|
// ========== 秒杀时段 1-013-009-000 ==========
|
||||||
ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
|
ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1_013_009_000, "秒杀时段不存在");
|
||||||
ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
|
ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1_013_009_001, "秒杀时段冲突");
|
||||||
ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
|
ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1_013_009_004, "秒杀时段已关闭");
|
||||||
|
|
||||||
// ========== 拼团活动 1013010000 ==========
|
// ========== 拼团活动 1-013-010-000 ==========
|
||||||
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
|
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
|
||||||
ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
|
ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
|
||||||
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
|
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
|
||||||
ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
|
ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
|
||||||
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
|
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
|
||||||
|
|
||||||
// ========== 拼团记录 1013011000 ==========
|
// ========== 拼团记录 1-013-011-000 ==========
|
||||||
ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
|
ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
|
||||||
ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
|
ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
|
||||||
ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在");
|
ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在");
|
||||||
|
@ -79,17 +79,17 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出");
|
ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出");
|
||||||
ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数");
|
ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数");
|
||||||
|
|
||||||
// ========== 砍价活动 1013012000 ==========
|
// ========== 砍价活动 1-013-012-000 ==========
|
||||||
ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
|
ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
|
||||||
ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
|
ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
|
||||||
ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
|
ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
|
||||||
ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
|
ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
|
||||||
ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
|
ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
|
||||||
|
|
||||||
// ========== 砍价记录 1013013000 ==========
|
// ========== 砍价记录 1-013-013-000 ==========
|
||||||
ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在");
|
ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1_013_013_000, "砍价记录不存在");
|
||||||
ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1013013001, "砍价失败,已参与过该砍价");
|
ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1_013_013_001, "砍价失败,已参与过该砍价");
|
||||||
ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013013002, "砍价失败,父砍价不存在");
|
ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_013_002, "砍价失败,父砍价不存在");
|
||||||
ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1013013003, "砍价失败,砍价人数已满");
|
ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1_013_013_003, "砍价失败,砍价人数已满");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,15 +37,6 @@ public class CouponController {
|
||||||
@Resource
|
@Resource
|
||||||
private MemberUserApi memberUserApi;
|
private MemberUserApi memberUserApi;
|
||||||
|
|
||||||
// @GetMapping("/get")
|
|
||||||
// @Operation(summary = "获得优惠劵")
|
|
||||||
// @Parameter(name = "id", description = "编号", required = true, example = "1024")
|
|
||||||
// @PreAuthorize("@ss.hasPermission('promotion:coupon:query')")
|
|
||||||
// public CommonResult<CouponRespVO> getCoupon(@RequestParam("id") Long id) {
|
|
||||||
// CouponDO coupon = couponService.getCoupon(id);
|
|
||||||
// return success(CouponConvert.INSTANCE.convert(coupon));
|
|
||||||
// }
|
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@Operation(summary = "回收优惠劵")
|
@Operation(summary = "回收优惠劵")
|
||||||
@Parameter(name = "id", description = "编号", required = true)
|
@Parameter(name = "id", description = "编号", required = true)
|
||||||
|
|
|
@ -44,4 +44,5 @@ public class CouponTemplatePageReqVO extends PageParam {
|
||||||
|
|
||||||
@Schema(description = "商品范围编号", example = "1")
|
@Schema(description = "商品范围编号", example = "1")
|
||||||
private Long productScopeValue;
|
private Long productScopeValue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,41 +9,41 @@ import java.time.LocalDateTime;
|
||||||
@Data
|
@Data
|
||||||
public class AppArticleRespVO {
|
public class AppArticleRespVO {
|
||||||
|
|
||||||
@Schema(description = "文章编号", required = true, example = "1")
|
@Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "文章标题", required = true, example = "芋道源码 - 促销模块")
|
@Schema(description = "文章标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码 - 促销模块")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@Schema(description = "文章作者", required = true, example = "芋道源码")
|
@Schema(description = "文章作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
|
||||||
private String author;
|
private String author;
|
||||||
|
|
||||||
@Schema(description = "分类编号", required = true, example = "2048")
|
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||||
private Long categoryId;
|
private Long categoryId;
|
||||||
|
|
||||||
@Schema(description = "图文封面", required = true, example = "https://www.iocoder.cn/1.png")
|
@Schema(description = "图文封面", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||||
private String picUrl;
|
private String picUrl;
|
||||||
|
|
||||||
@Schema(description = "文章简介", required = true, example = "我是简介")
|
@Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是简介")
|
||||||
private String introduction;
|
private String introduction;
|
||||||
|
|
||||||
@Schema(description = "文章内容", required = true, example = "我是详细")
|
@Schema(description = "文章内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是详细")
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Schema(description = "发布时间", required = true)
|
@Schema(description = "发布时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
@Schema(description = "浏览量", required = true, example = "1024")
|
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Integer browseCount;
|
private Integer browseCount;
|
||||||
|
|
||||||
@Schema(description = "关联的商品 SPU 编号", example = "1024")
|
@Schema(description = "关联的商品 SPU 编号", example = "1024")
|
||||||
private Long spuId;
|
private Long spuId;
|
||||||
|
|
||||||
// TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
|
// TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
|
||||||
// @Schema(description = "是否热卖推荐", required = true, example = "true")
|
// @Schema(description = "是否热卖推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||||
// private Boolean recommendHot;
|
// private Boolean recommendHot;
|
||||||
//
|
//
|
||||||
// @Schema(description = "是否 Banner 推荐", required = true, example = "true")
|
// @Schema(description = "是否 Banner 推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||||
// private Boolean recommendBanner;
|
// private Boolean recommendBanner;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,20 +7,20 @@ import lombok.Data;
|
||||||
@Data
|
@Data
|
||||||
public class AppArticleCategoryRespVO {
|
public class AppArticleCategoryRespVO {
|
||||||
|
|
||||||
@Schema(description = "分类编号", required = true, example = "1")
|
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "分类名称", required = true, example = "技术")
|
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "分类图标", required = true, example = "https://www.iocoder.cn/1.png")
|
@Schema(description = "分类图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||||
private String picUrl;
|
private String picUrl;
|
||||||
|
|
||||||
// TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
|
// TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
|
||||||
// @Schema(description = "状态", required = true, example = "1")
|
// @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
// private Integer status;
|
// private Integer status;
|
||||||
//
|
//
|
||||||
// @Schema(description = "排序", required = true, example = "1024")
|
// @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
// private Integer sort;
|
// private Integer sort;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,46 +9,46 @@ import java.time.LocalDateTime;
|
||||||
@Data
|
@Data
|
||||||
public class AppBargainActivityDetailRespVO {
|
public class AppBargainActivityDetailRespVO {
|
||||||
|
|
||||||
@Schema(description = "砍价活动编号", required = true, example = "1024")
|
@Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "砍价活动名称", required = true, example = "618 大砍价")
|
@Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大砍价")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "活动开始时间", required = true)
|
@Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime startTime;
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
@Schema(description = "活动结束时间", required = true)
|
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime endTime;
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
|
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||||
private Long spuId;
|
private Long spuId;
|
||||||
|
|
||||||
@Schema(description = "商品 SKU 编号", required = true, example = "1024")
|
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Long skuId;
|
private Long skuId;
|
||||||
|
|
||||||
@Schema(description = "商品价格,单位:分", required = true, example = "100")
|
@Schema(description = "商品价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||||
private Integer price;
|
private Integer price;
|
||||||
|
|
||||||
@Schema(description = "商品描述", required = true, example = "我要吃西红柿")
|
@Schema(description = "商品描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "我要吃西红柿")
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Schema(description = "砍价库存", required = true, example = "512")
|
@Schema(description = "砍价库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
|
||||||
private Integer stock;
|
private Integer stock;
|
||||||
|
|
||||||
@Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
|
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") // 从 SPU 的 picUrl 读取
|
||||||
private String picUrl;
|
private String picUrl;
|
||||||
|
|
||||||
@Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
|
@Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") // 从 SPU 的 marketPrice 读取
|
||||||
private Integer marketPrice;
|
private Integer marketPrice;
|
||||||
|
|
||||||
@Schema(description = "商品单位", required = true, example = "个") // 从 SPU 的 unit 读取,然后转换
|
@Schema(description = "商品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") // 从 SPU 的 unit 读取,然后转换
|
||||||
private String unitName;
|
private String unitName;
|
||||||
|
|
||||||
@Schema(description = "砍价最低金额,单位:分", required = true, example = "100")
|
@Schema(description = "砍价最低金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||||
private Integer bargainPrice;
|
private Integer bargainPrice;
|
||||||
|
|
||||||
@Schema(description = "砍价成功数量", required = true, example = "100")
|
@Schema(description = "砍价成功数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||||
private Integer successCount;
|
private Integer successCount;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,34 +9,34 @@ import java.time.LocalDateTime;
|
||||||
@Data
|
@Data
|
||||||
public class AppBargainActivityRespVO {
|
public class AppBargainActivityRespVO {
|
||||||
|
|
||||||
@Schema(description = "砍价活动编号", required = true, example = "1024")
|
@Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "砍价活动名称", required = true, example = "618 大砍价")
|
@Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大砍价")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "活动开始时间", required = true)
|
@Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime startTime;
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
@Schema(description = "活动结束时间", required = true)
|
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime endTime;
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
|
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||||
private Long spuId;
|
private Long spuId;
|
||||||
|
|
||||||
@Schema(description = "商品 SKU 编号", required = true, example = "1024")
|
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Long skuId;
|
private Long skuId;
|
||||||
|
|
||||||
@Schema(description = "砍价库存", required = true, example = "512")
|
@Schema(description = "砍价库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
|
||||||
private Integer stock;
|
private Integer stock;
|
||||||
|
|
||||||
@Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
|
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") // 从 SPU 的 picUrl 读取
|
||||||
private String picUrl;
|
private String picUrl;
|
||||||
|
|
||||||
@Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
|
@Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") // 从 SPU 的 marketPrice 读取
|
||||||
private Integer marketPrice;
|
private Integer marketPrice;
|
||||||
|
|
||||||
@Schema(description = "砍价最低金额,单位:分", required = true, example = "100")
|
@Schema(description = "砍价最低金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||||
private Integer bargainPrice;
|
private Integer bargainPrice;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
|
||||||
@Data
|
@Data
|
||||||
public class AppBargainHelpCreateReqVO {
|
public class AppBargainHelpCreateReqVO {
|
||||||
|
|
||||||
@Schema(description = "砍价记录编号", required = true, example = "1024")
|
@Schema(description = "砍价记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
@NotNull(message = "砍价记录编号不能为空")
|
@NotNull(message = "砍价记录编号不能为空")
|
||||||
private Long recordId;
|
private Long recordId;
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@ import java.time.LocalDateTime;
|
||||||
@Data
|
@Data
|
||||||
public class AppBargainHelpRespVO {
|
public class AppBargainHelpRespVO {
|
||||||
|
|
||||||
@Schema(description = "助力用户的昵称", required = true, example = "1024")
|
@Schema(description = "助力用户的昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
|
||||||
@Schema(description = "助力用户的头像", required = true, example = "1024")
|
@Schema(description = "助力用户的头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
|
|
||||||
@Schema(description = "助力用户的砍价金额", required = true, example = "1024")
|
@Schema(description = "助力用户的砍价金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Integer reducePrice;
|
private Integer reducePrice;
|
||||||
|
|
||||||
@Schema(description = "创建时间", required = true, example = "1024")
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
|
||||||
@Data
|
@Data
|
||||||
public class AppBargainRecordCreateReqVO {
|
public class AppBargainRecordCreateReqVO {
|
||||||
|
|
||||||
@Schema(description = "砍价活动编号", required = true, example = "1024")
|
@Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
@NotNull(message = "砍价活动编号不能为空")
|
@NotNull(message = "砍价活动编号不能为空")
|
||||||
private Long activityId;
|
private Long activityId;
|
||||||
|
|
||||||
|
|
|
@ -9,23 +9,23 @@ import java.util.List;
|
||||||
@Data
|
@Data
|
||||||
public class AppBargainRecordSummaryRespVO {
|
public class AppBargainRecordSummaryRespVO {
|
||||||
|
|
||||||
@Schema(description = "砍价用户数量", required = true, example = "1024")
|
@Schema(description = "砍价用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Integer userCount;
|
private Integer userCount;
|
||||||
|
|
||||||
@Schema(description = "成功砍价的记录", required = true) // 只返回最近的 7 个
|
@Schema(description = "成功砍价的记录", requiredMode = Schema.RequiredMode.REQUIRED) // 只返回最近的 7 个
|
||||||
private List<Record> successRecords;
|
private List<Record> successRecords;
|
||||||
|
|
||||||
@Schema(description = "成功砍价记录")
|
@Schema(description = "成功砍价记录")
|
||||||
@Data
|
@Data
|
||||||
public static class Record {
|
public static class Record {
|
||||||
|
|
||||||
@Schema(description = "用户昵称", required = true, example = "王**")
|
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王**")
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
|
||||||
@Schema(description = "用户头像", required = true, example = "https://www.iocoder.cn/xxx.jpg")
|
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
|
|
||||||
@Schema(description = "活动名称", required = true, example = "天蚕土豆")
|
@Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "天蚕土豆")
|
||||||
private String activityName;
|
private String activityName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,14 +40,17 @@ public class AppCouponController {
|
||||||
@PostMapping("/take")
|
@PostMapping("/take")
|
||||||
@Operation(summary = "领取优惠劵")
|
@Operation(summary = "领取优惠劵")
|
||||||
@Parameter(name = "templateId", description = "优惠券模板编号", required = true, example = "1024")
|
@Parameter(name = "templateId", description = "优惠券模板编号", required = true, example = "1024")
|
||||||
|
@PreAuthenticated
|
||||||
public CommonResult<Boolean> takeCoupon(@Valid @RequestBody AppCouponTakeReqVO reqVO) {
|
public CommonResult<Boolean> takeCoupon(@Valid @RequestBody AppCouponTakeReqVO reqVO) {
|
||||||
|
// 1. 领取优惠劵
|
||||||
Long userId = getLoginUserId();
|
Long userId = getLoginUserId();
|
||||||
// 领取
|
|
||||||
couponService.takeCoupon(reqVO.getTemplateId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.USER);
|
couponService.takeCoupon(reqVO.getTemplateId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.USER);
|
||||||
// 检查是否可以继续领取
|
|
||||||
|
// 2. 检查是否可以继续领取
|
||||||
CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(reqVO.getTemplateId());
|
CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(reqVO.getTemplateId());
|
||||||
boolean canTakeAgain = true;
|
boolean canTakeAgain = true;
|
||||||
if (couponTemplate.getTakeLimitCount() != null && couponTemplate.getTakeLimitCount() > 0) {
|
if (couponTemplate.getTakeLimitCount() != null && couponTemplate.getTakeLimitCount() > 0) {
|
||||||
|
// TODO @疯狂:要不要搞个 getTakeCount 方法?
|
||||||
Integer takeCount = MapUtil.getInt(couponService.getTakeCountMapByTemplateIds(
|
Integer takeCount = MapUtil.getInt(couponService.getTakeCountMapByTemplateIds(
|
||||||
Collections.singleton(reqVO.getTemplateId()), userId), reqVO.getTemplateId(), 0);
|
Collections.singleton(reqVO.getTemplateId()), userId), reqVO.getTemplateId(), 0);
|
||||||
canTakeAgain = takeCount < couponTemplate.getTakeLimitCount();
|
canTakeAgain = takeCount < couponTemplate.getTakeLimitCount();
|
||||||
|
@ -56,15 +59,16 @@ public class AppCouponController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/match-list")
|
@GetMapping("/match-list")
|
||||||
@Operation(summary = "获得匹配指定商品的优惠劵列表")
|
@Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表")
|
||||||
public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) {
|
public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) {
|
||||||
// todo: 优惠金额倒序
|
// todo: 优化:优惠金额倒序
|
||||||
return success(CouponConvert.INSTANCE.convertList(couponService.getMatchCouponList(getLoginUserId(), matchReqVO)));
|
return success(CouponConvert.INSTANCE.convertList(couponService.getMatchCouponList(getLoginUserId(), matchReqVO)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@Operation(summary = "优惠劵列表", description = "我的优惠劵")
|
@Operation(summary = "我的优惠劵列表")
|
||||||
public CommonResult<PageResult<AppCouponRespVO>> takeCoupon(AppCouponPageReqVO pageReqVO) {
|
@PreAuthenticated
|
||||||
|
public CommonResult<PageResult<AppCouponRespVO>> getCouponPage(AppCouponPageReqVO pageReqVO) {
|
||||||
PageResult<CouponDO> pageResult = couponService.getCouponPage(
|
PageResult<CouponDO> pageResult = couponService.getCouponPage(
|
||||||
CouponConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId())));
|
CouponConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId())));
|
||||||
return success(CouponConvert.INSTANCE.convertAppPage(pageResult));
|
return success(CouponConvert.INSTANCE.convertAppPage(pageResult));
|
||||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
|
||||||
|
@ -14,13 +15,17 @@ import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
|
import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
@ -41,16 +46,63 @@ public class AppCouponTemplateController {
|
||||||
@Resource
|
@Resource
|
||||||
private ProductSpuApi productSpuApi;
|
private ProductSpuApi productSpuApi;
|
||||||
|
|
||||||
|
// TODO 疯狂:这里应该还有个 list 接口哈;获得优惠劵模版列表,用于首页、商品页的优惠劵
|
||||||
|
@GetMapping("/list")
|
||||||
|
@Operation(summary = "获得优惠劵模版列表")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = "spuId", description = "商品 SPU 编号"), // 目前主要给商品详情使用
|
||||||
|
@Parameter(name = "useType", description = "使用类型"),
|
||||||
|
@Parameter(name = "count", description = "数量", required = true)
|
||||||
|
})
|
||||||
|
public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList(
|
||||||
|
@RequestParam(value = "spuId", required = false) Long spuId,
|
||||||
|
@RequestParam(value = "useType", required = false) Integer useType,
|
||||||
|
@RequestParam(value = "count", required = false, defaultValue = "10") Integer count) {
|
||||||
|
List<AppCouponTemplateRespVO> list = new ArrayList<>();
|
||||||
|
Random random = new Random();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO();
|
||||||
|
vo.setId(i + 1L);
|
||||||
|
vo.setName("优惠劵" + (i + 1));
|
||||||
|
vo.setTakeLimitCount(random.nextInt(10) + 1);
|
||||||
|
vo.setUsePrice(random.nextInt(100) * 100);
|
||||||
|
vo.setValidityType(random.nextInt(2) + 1);
|
||||||
|
if (vo.getValidityType() == 1) {
|
||||||
|
vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10)));
|
||||||
|
vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10));
|
||||||
|
} else {
|
||||||
|
vo.setFixedStartTerm(random.nextInt(10));
|
||||||
|
vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1);
|
||||||
|
}
|
||||||
|
vo.setDiscountType(random.nextInt(2) + 1);
|
||||||
|
if (vo.getDiscountType() == 1) {
|
||||||
|
vo.setDiscountPercent(null);
|
||||||
|
vo.setDiscountPrice(random.nextInt(50) * 100);
|
||||||
|
vo.setDiscountLimitPrice(null);
|
||||||
|
} else {
|
||||||
|
vo.setDiscountPercent(random.nextInt(90) + 10);
|
||||||
|
vo.setDiscountPrice(null);
|
||||||
|
vo.setDiscountLimitPrice(random.nextInt(200) * 100);
|
||||||
|
}
|
||||||
|
// TODO @疯狂:是否已领取,要不在 TemplateService 搞个 static 方法,让它基于 countMap 这种去计算,这样好点?
|
||||||
|
vo.setTakeStatus(random.nextBoolean());
|
||||||
|
list.add(vo);
|
||||||
|
}
|
||||||
|
return success(list);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@Operation(summary = "获得优惠劵模版分页")
|
@Operation(summary = "获得优惠劵模版分页")
|
||||||
public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) {
|
public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) {
|
||||||
// 1.1 处理查询条件:商品范围编号
|
// 1.1 处理查询条件:商品范围编号
|
||||||
Long productScopeValue = getaProductScopeValue(pageReqVO);
|
Long productScopeValue = getProductScopeValue(pageReqVO);
|
||||||
// 1.2 处理查询条件:领取方式=直接领取
|
// 1.2 处理查询条件:领取方式 = 直接领取
|
||||||
List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue());
|
List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue());
|
||||||
|
|
||||||
// 2. 分页查询
|
// 2. 分页查询
|
||||||
PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(
|
PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(
|
||||||
CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue));
|
CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue));
|
||||||
|
|
||||||
// 3.1 领取数量
|
// 3.1 领取数量
|
||||||
Map<Long, Integer> couponTakeCountMap = new HashMap<>(0);
|
Map<Long, Integer> couponTakeCountMap = new HashMap<>(0);
|
||||||
Long userId = getLoginUserId();
|
Long userId = getLoginUserId();
|
||||||
|
@ -63,17 +115,24 @@ public class AppCouponTemplateController {
|
||||||
return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap));
|
return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long getaProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) {
|
/**
|
||||||
Long productScopeValue = pageReqVO.getSpuId();
|
* 获得分页查询的商品范围
|
||||||
if (pageReqVO.getProductScope() == null || Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope())) {
|
*
|
||||||
// 通用券:清除商品范围
|
* @param pageReqVO 分页查询
|
||||||
productScopeValue = null;
|
* @return 商品范围
|
||||||
} else if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) {
|
*/
|
||||||
// 品类券:查询商品的品类
|
private Long getProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) {
|
||||||
productScopeValue = Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId()))
|
// 通用券:清除商品范围
|
||||||
|
if (pageReqVO.getProductScope() == null || ObjectUtils.equalsAny(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope(), null)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 品类券:查询商品的品类
|
||||||
|
if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) {
|
||||||
|
return Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId()))
|
||||||
.map(ProductSpuRespDTO::getCategoryId).orElse(null);
|
.map(ProductSpuRespDTO::getCategoryId).orElse(null);
|
||||||
}
|
}
|
||||||
return productScopeValue;
|
// 商品卷:直接返回
|
||||||
|
return pageReqVO.getSpuId();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,5 @@ public class AppCouponTemplatePageReqVO extends PageParam {
|
||||||
|
|
||||||
@Schema(description = "商品标号", example = "1")
|
@Schema(description = "商品标号", example = "1")
|
||||||
private Long spuId;
|
private Long spuId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,6 @@ public class AppCouponTemplateRespVO {
|
||||||
// 单位:分;0 - 不限制
|
// 单位:分;0 - 不限制
|
||||||
private Integer usePrice;
|
private Integer usePrice;
|
||||||
|
|
||||||
// TODO 芋艿:这两要改的
|
|
||||||
// @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
|
||||||
// @InEnum(PromotionProductScopeEnum.class)
|
|
||||||
// private Integer productScope;
|
|
||||||
//
|
|
||||||
// @Schema(description = "商品范围编号的数组", example = "1,3")
|
|
||||||
// private List<Long> productScopeValues;
|
|
||||||
|
|
||||||
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
private Integer validityType;
|
private Integer validityType;
|
||||||
|
|
||||||
|
|
|
@ -61,4 +61,5 @@ public interface CouponConvert {
|
||||||
PageResult<AppCouponRespVO> convertAppPage(PageResult<CouponDO> pageResult);
|
PageResult<AppCouponRespVO> convertAppPage(PageResult<CouponDO> pageResult);
|
||||||
|
|
||||||
List<AppCouponMatchRespVO> convertList(List<CouponDO> list);
|
List<AppCouponMatchRespVO> convertList(List<CouponDO> list);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,16 +42,16 @@ public interface CouponTemplateConvert {
|
||||||
if (MapUtil.isEmpty(couponTakeCountMap)) {
|
if (MapUtil.isEmpty(couponTakeCountMap)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
for (AppCouponTemplateRespVO template : result.getList()) {
|
||||||
for (AppCouponTemplateRespVO vo : result.getList()) {
|
|
||||||
// 每人领取数量无限制
|
// 每人领取数量无限制
|
||||||
if (vo.getTakeLimitCount() == -1) {
|
if (template.getTakeLimitCount() == -1) {
|
||||||
vo.setTakeStatus(false);
|
template.setTakeStatus(false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 检查已领取数量是否超过限领数量
|
// 检查已领取数量是否超过限领数量
|
||||||
vo.setTakeStatus(MapUtil.getInt(couponTakeCountMap, vo.getId(), 0) >= vo.getTakeLimitCount());
|
template.setTakeStatus(MapUtil.getInt(couponTakeCountMap, template.getId(), 0) >= template.getTakeLimitCount());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ public interface CouponMapper extends BaseMapperX<CouponDO> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO @疯狂:这个是不是搞个 Map 就可以呀?
|
||||||
default List<CouponTakeCountBO> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) {
|
default List<CouponTakeCountBO> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) {
|
||||||
return BeanUtil.copyToList(selectMaps(MPJWrappers.lambdaJoin(CouponDO.class)
|
return BeanUtil.copyToList(selectMaps(MPJWrappers.lambdaJoin(CouponDO.class)
|
||||||
.select(CouponDO::getTemplateId)
|
.select(CouponDO::getTemplateId)
|
||||||
|
@ -81,18 +82,17 @@ public interface CouponMapper extends BaseMapperX<CouponDO> {
|
||||||
|
|
||||||
default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope(
|
default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope(
|
||||||
Long userId, Integer status, Integer usePrice, List<Long> spuIds, List<Long> categoryIds) {
|
Long userId, Integer status, Integer usePrice, List<Long> spuIds, List<Long> categoryIds) {
|
||||||
|
|
||||||
Function<List<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
|
Function<List<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
|
||||||
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
|
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
|
||||||
.collect(Collectors.joining(" OR "));
|
.collect(Collectors.joining(" OR "));
|
||||||
return selectList(new LambdaQueryWrapperX<CouponDO>()
|
return selectList(new LambdaQueryWrapperX<CouponDO>()
|
||||||
.eq(CouponDO::getUserId, userId)
|
.eq(CouponDO::getUserId, userId)
|
||||||
.eq(CouponDO::getStatus, status)
|
.eq(CouponDO::getStatus, status)
|
||||||
.le(CouponDO::getUsePrice, usePrice)
|
.le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件
|
||||||
.and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope())
|
.and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部
|
||||||
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope())
|
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品
|
||||||
.apply(productScopeValuesFindInSetFunc.apply(spuIds)))
|
.apply(productScopeValuesFindInSetFunc.apply(spuIds)))
|
||||||
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope())
|
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类
|
||||||
.apply(productScopeValuesFindInSetFunc.apply(categoryIds)))));
|
.apply(productScopeValuesFindInSetFunc.apply(categoryIds)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,4 +102,5 @@ public interface CouponMapper extends BaseMapperX<CouponDO> {
|
||||||
.le(CouponDO::getValidEndTime, validEndTime)
|
.le(CouponDO::getValidEndTime, validEndTime)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.iocoder.yudao.module.promotion.job;
|
package cn.iocoder.yudao.module.promotion.job.coupon;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||||
|
@ -8,19 +8,20 @@ import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
// TODO 芋艿:配置一个 Job
|
||||||
/**
|
/**
|
||||||
* 优惠券过期 Job
|
* 优惠券过期 Job
|
||||||
*
|
*
|
||||||
* @author owen
|
* @author owen
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@TenantJob
|
|
||||||
public class CouponExpireJob implements JobHandler {
|
public class CouponExpireJob implements JobHandler {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CouponService couponService;
|
private CouponService couponService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@TenantJob
|
||||||
public String execute(String param) {
|
public String execute(String param) {
|
||||||
int count = couponService.expireCoupon();
|
int count = couponService.expireCoupon();
|
||||||
return StrUtil.format("过期优惠券 {} 个", count);
|
return StrUtil.format("过期优惠券 {} 个", count);
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* TODO 占位,无具体含义
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.promotion.job;
|
|
@ -137,7 +137,8 @@ public interface CouponService {
|
||||||
* @return 领取优惠券的数量
|
* @return 领取优惠券的数量
|
||||||
*/
|
*/
|
||||||
default Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) {
|
default Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) {
|
||||||
return convertMap(getTakeCountListByTemplateIds(templateIds, userId), CouponTakeCountBO::getTemplateId, CouponTakeCountBO::getCount);
|
return convertMap(getTakeCountListByTemplateIds(templateIds, userId),
|
||||||
|
CouponTakeCountBO::getTemplateId, CouponTakeCountBO::getCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,4 +165,5 @@ public interface CouponService {
|
||||||
* @return 过期数量
|
* @return 过期数量
|
||||||
*/
|
*/
|
||||||
int expireCoupon();
|
int expireCoupon();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
||||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
// TODO @疯狂:注册时,赠送用户优惠劵;为了解耦,可以考虑注册时发个 MQ 消息;然后营销这里监听后消费;
|
||||||
/**
|
/**
|
||||||
* 优惠劵 Service 实现类
|
* 优惠劵 Service 实现类
|
||||||
*
|
*
|
||||||
|
@ -192,7 +193,8 @@ public class CouponServiceImpl implements CouponService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) {
|
public List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) {
|
||||||
return couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId, CouponStatusEnum.UNUSED.getStatus(),
|
return couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId,
|
||||||
|
CouponStatusEnum.UNUSED.getStatus(),
|
||||||
matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds());
|
matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,15 +222,20 @@ public class CouponServiceImpl implements CouponService {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期单个优惠劵
|
||||||
|
*
|
||||||
|
* @param coupon 优惠劵
|
||||||
|
* @return 是否过期成功
|
||||||
|
*/
|
||||||
private boolean expireCoupon(CouponDO coupon) {
|
private boolean expireCoupon(CouponDO coupon) {
|
||||||
// 更新记录状态
|
// 更新记录状态
|
||||||
CouponDO updateObj = new CouponDO().setStatus(CouponStatusEnum.EXPIRE.getStatus());
|
int updateRows = couponMapper.updateByIdAndStatus(coupon.getId(), CouponStatusEnum.UNUSED.getStatus(),
|
||||||
int updateRows = couponMapper.updateByIdAndStatus(coupon.getId(), CouponStatusEnum.UNUSED.getStatus(), updateObj);
|
new CouponDO().setStatus(CouponStatusEnum.EXPIRE.getStatus()));
|
||||||
if (updateRows == 0) {
|
if (updateRows == 0) {
|
||||||
log.error("[expireCoupon][coupon({}) 更新为已过期失败]", coupon.getId());
|
log.error("[expireCoupon][coupon({}) 更新为已过期失败]", coupon.getId());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("[expireCoupon][coupon({}) 更新为已过期成功]", coupon.getId());
|
log.info("[expireCoupon][coupon({}) 更新为已过期成功]", coupon.getId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
|
||||||
@Resource
|
@Resource
|
||||||
private CouponTemplateMapper couponTemplateMapper;
|
private CouponTemplateMapper couponTemplateMapper;
|
||||||
|
|
||||||
|
// TODO @疯狂:新增/修改时,需要校验对应的商品、分类是否存在
|
||||||
@Override
|
@Override
|
||||||
public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) {
|
public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) {
|
||||||
// 插入
|
// 插入
|
||||||
|
|
|
@ -9,6 +9,7 @@ import lombok.Data;
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class CouponTakeCountBO {
|
public class CouponTakeCountBO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠劵模板编号
|
* 优惠劵模板编号
|
||||||
*/
|
*/
|
||||||
|
@ -17,4 +18,5 @@ public class CouponTakeCountBO {
|
||||||
* 领取数量
|
* 领取数量
|
||||||
*/
|
*/
|
||||||
private Integer count;
|
private Integer count;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== Order 模块 1011000000 ==========
|
// ========== Order 模块 1-011-000-000 ==========
|
||||||
ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
|
ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
|
||||||
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
|
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
|
||||||
ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
|
ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
|
||||||
|
@ -33,45 +33,44 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1011000028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元");
|
ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1011000028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元");
|
||||||
ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态");
|
ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态");
|
||||||
|
|
||||||
// ========== After Sale 模块 1011000100 ==========
|
// ========== After Sale 模块 1-011-000-100 ==========
|
||||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
|
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
||||||
ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1011000101, "申请退款金额错误");
|
ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1_011_000_101, "申请退款金额错误");
|
||||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1011000102, "订单已关闭,无法申请售后");
|
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1_011_000_102, "订单已关闭,无法申请售后");
|
||||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1011000103, "订单未支付,无法申请售后");
|
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1_011_000_103, "订单未支付,无法申请售后");
|
||||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1011000104, "订单未发货,无法申请【退货退款】售后");
|
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1_011_000_104, "订单未发货,无法申请【退货退款】售后");
|
||||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1011000105, "订单项已申请售后,无法重复申请");
|
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1_011_000_105, "订单项已申请售后,无法重复申请");
|
||||||
ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1011000106, "审批失败,售后状态不处于审批中");
|
ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1_011_000_106, "审批失败,售后状态不处于审批中");
|
||||||
ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试");
|
ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1_011_000_107, "操作售后单失败,请刷新后重试");
|
||||||
ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");
|
ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1_011_000_108, "退货失败,售后单状态不处于【待买家退货】");
|
||||||
ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】");
|
ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1_011_000_109, "确认收货失败,售后单状态不处于【待确认收货】");
|
||||||
ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000110, "退款失败,售后单状态不是【待退款】");
|
ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1_011_000_110, "退款失败,售后单状态不是【待退款】");
|
||||||
ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY =
|
ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY =
|
||||||
new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
|
new ErrorCode(1_011_000_111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
|
||||||
|
|
||||||
// ========== Cart 模块 1011002000 ==========
|
// ========== Cart 模块 1-011-002-000 ==========
|
||||||
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");
|
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在");
|
||||||
|
|
||||||
// ========== Price 相关 1011003000 ============
|
// ========== Price 相关 1-011-003-000 ============
|
||||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
|
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
|
||||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
|
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
|
||||||
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
||||||
|
|
||||||
// ========== 物流 Express 模块 1011004000 ==========
|
// ========== 物流 Express 模块 1-011-004-000 ==========
|
||||||
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在");
|
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
|
||||||
ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011004001, "已经存在该编码的快递公司");
|
ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1_011_004_001, "已经存在该编码的快递公司");
|
||||||
ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1011004002, "需要接入快递服务商,比如【快递100】");
|
ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1_011_004_002, "需要接入快递服务商,比如【快递100】");
|
||||||
ErrorCode EXPRESS_STATUS_NOT_ENABLE = new ErrorCode(1011004003, "快递公司未启用");
|
ErrorCode EXPRESS_STATUS_NOT_ENABLE = new ErrorCode(1_011_004_003, "快递公司未启用");
|
||||||
|
|
||||||
ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011004101, "快递查询接口异常");
|
ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1_011_004_101, "快递查询接口异常");
|
||||||
ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011004102, "快递查询返回失败,原因:{}");
|
ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1_011_004_102, "快递查询返回失败,原因:{}");
|
||||||
|
|
||||||
// ========== 物流 Template 模块 1011005000 ==========
|
// ========== 物流 Template 模块 1-011-005-000 ==========
|
||||||
ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011005000, "已经存在该运费模板名");
|
ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1_011_005_000, "已经存在该运费模板名");
|
||||||
ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");
|
ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_011_005_001, "运费模板不存在");
|
||||||
|
|
||||||
// ========== 物流 PICK_UP 模块 1011006000 ==========
|
|
||||||
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
|
|
||||||
|
|
||||||
|
// ========== 物流 PICK_UP 模块 1-011-006-000 ==========
|
||||||
|
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店不存在");
|
||||||
|
|
||||||
// ========== 分销用户 模块 1011007000 ==========
|
// ========== 分销用户 模块 1011007000 ==========
|
||||||
ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
|
ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
|
||||||
|
|
|
@ -1,28 +1,35 @@
|
||||||
package cn.iocoder.yudao.module.trade.enums.aftersale;
|
package cn.iocoder.yudao.module.trade.enums.aftersale;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 售后操作类型的枚举
|
* 售后操作类型的枚举
|
||||||
*
|
*
|
||||||
* @author 陈賝
|
* @author 陈賝
|
||||||
* @since 2023/6/13 13:53
|
* @since 2023/6/13 13:53
|
||||||
*/
|
*/
|
||||||
// TODO @chenchen:可以 lombok 简化构造方法,和 get 方法
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
public enum AfterSaleOperateTypeEnum {
|
public enum AfterSaleOperateTypeEnum {
|
||||||
|
|
||||||
/**
|
MEMBER_CREATE(10, "会员申请退款"),
|
||||||
* 用户申请
|
ADMIN_AGREE_APPLY(11, "商家同意退款"),
|
||||||
*/
|
ADMIN_DISAGREE_APPLY(12, "商家拒绝退款"),
|
||||||
APPLY("用户申请"),
|
MEMBER_DELIVERY(20, "会员填写退货物流信息,快递公司:{deliveryName},快递单号:{logisticsNo}"),
|
||||||
|
ADMIN_AGREE_RECEIVE(21, "商家收货"),
|
||||||
|
ADMIN_DISAGREE_RECEIVE(22, "商家拒绝收货,原因:{reason}"),
|
||||||
|
ADMIN_REFUND(30, "商家退款"),
|
||||||
|
MEMBER_CANCEL(40, "会员取消退款"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String description;
|
/**
|
||||||
|
* 操作类型
|
||||||
AfterSaleOperateTypeEnum(String description) {
|
*/
|
||||||
this.description = description;
|
private final Integer type;
|
||||||
}
|
/**
|
||||||
|
* 操作描述
|
||||||
public String description() {
|
*/
|
||||||
return description;
|
private final String content;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,15 @@ public enum BrokerageBindModeEnum implements IntArrayValuable {
|
||||||
/**
|
/**
|
||||||
* 只要用户没有推广人,随时都可以绑定分销关系
|
* 只要用户没有推广人,随时都可以绑定分销关系
|
||||||
*/
|
*/
|
||||||
ANYTIME(1, "没有推广人"),
|
ANYTIME(1, "首次绑定"),
|
||||||
/**
|
/**
|
||||||
* 仅新用户注册时才能绑定推广关系
|
* 仅新用户注册时才能绑定推广关系
|
||||||
*/
|
*/
|
||||||
REGISTER(2, "新用户"),
|
REGISTER(2, "注册绑定"),
|
||||||
/**
|
/**
|
||||||
* 每次扫码都覆盖
|
* 每次扫码都覆盖
|
||||||
*/
|
*/
|
||||||
OVERRIDE(3, "扫码覆盖"),
|
OVERRIDE(3, "覆盖绑定"),
|
||||||
;
|
;
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray();
|
||||||
|
|
|
@ -17,7 +17,7 @@ public enum BrokerageRecordBizTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
ORDER(1, "获得推广佣金", "获得推广佣金 {}", true),
|
ORDER(1, "获得推广佣金", "获得推广佣金 {}", true),
|
||||||
WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false),
|
WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false),
|
||||||
WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回返还佣金 {}", true),
|
WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回,返还佣金 {}", true),
|
||||||
;
|
;
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import lombok.Getter;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
// TODO 芋艿:提现的打通,在纠结下;
|
||||||
/**
|
/**
|
||||||
* 佣金提现状态枚举
|
* 佣金提现状态枚举
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,15 +24,16 @@ public enum TradeOrderOperateTypeEnum {
|
||||||
MEMBER_CANCEL(40, "取消订单"),
|
MEMBER_CANCEL(40, "取消订单"),
|
||||||
SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"),
|
SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"),
|
||||||
// 42 预留:管理员取消订单
|
// 42 预留:管理员取消订单
|
||||||
MEMBER_DELETE(43, "删除订单"),
|
ADMIN_CANCEL_AFTER_SALE(43, "订单全部售后,管理员自动取消订单"),
|
||||||
|
MEMBER_DELETE(49, "删除订单"),
|
||||||
;
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型
|
* 操作类型
|
||||||
*/
|
*/
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
/**
|
/**
|
||||||
* 类型
|
* 操作描述
|
||||||
*/
|
*/
|
||||||
private final String content;
|
private final String content;
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum
|
||||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
|
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
|
||||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
|
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
|
||||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
|
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
|
||||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
|
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
@ -88,24 +88,24 @@ public class BrokerageUserController {
|
||||||
// 分页查询
|
// 分页查询
|
||||||
PageResult<BrokerageUserDO> pageResult = brokerageUserService.getBrokerageUserPage(pageVO);
|
PageResult<BrokerageUserDO> pageResult = brokerageUserService.getBrokerageUserPage(pageVO);
|
||||||
|
|
||||||
// 涉及到的用户
|
|
||||||
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
|
|
||||||
// 查询用户信息
|
// 查询用户信息
|
||||||
|
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
|
||||||
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
|
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
|
||||||
// 合计分佣订单
|
// 合计分佣的推广订单
|
||||||
Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap = brokerageRecordService.getUserBrokerageSummaryMapByUserId(
|
Map<Long, UserBrokerageSummaryRespBO> brokerageOrderSummaryMap = brokerageRecordService.getUserBrokerageSummaryMapByUserId(
|
||||||
userIds, BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
|
userIds, BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
|
||||||
// TODO @芋艿:看看下面 getBrokerageUserCountByBindUserId 有没可能一次性出结果,不然 n 次有点太花性能了;
|
// 合计分佣的推广用户
|
||||||
// 合计推广用户数量
|
// TODO @疯狂:转成 map 批量读取
|
||||||
Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
|
Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
|
||||||
userId -> userId,
|
userId -> userId,
|
||||||
userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
|
userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
|
||||||
// 合计提现
|
// 合计分佣的提现
|
||||||
Map<Long, UserWithdrawSummaryBO> withdrawMap = brokerageWithdrawService.getWithdrawSummaryMapByUserId(userIds,
|
// TODO @疯狂:如果未来支持了打款这个动作,可能 status 会不对;
|
||||||
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS);
|
Map<Long, BrokerageWithdrawSummaryRespBO> withdrawMap = brokerageWithdrawService.getWithdrawSummaryMapByUserId(
|
||||||
|
userIds, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS);
|
||||||
// 拼接返回
|
// 拼接返回
|
||||||
return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
|
return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
|
||||||
userOrderSummaryMap, withdrawMap));
|
brokerageOrderSummaryMap, withdrawMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,25 +21,25 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO {
|
||||||
|
|
||||||
// ========== 用户信息 ==========
|
// ========== 用户信息 ==========
|
||||||
|
|
||||||
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
|
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.png")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
@Schema(description = "用户昵称", example = "李四")
|
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
|
||||||
// ========== 推广信息 ==========
|
// ========== 推广信息 ==========
|
||||||
|
|
||||||
@Schema(description = "推广用户数量", example = "20019")
|
@Schema(description = "推广用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||||
private Integer brokerageUserCount;
|
private Integer brokerageUserCount;
|
||||||
@Schema(description = "推广订单数量", example = "20019")
|
@Schema(description = "推广订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||||
private Integer brokerageOrderCount;
|
private Integer brokerageOrderCount;
|
||||||
@Schema(description = "推广订单金额", example = "20019")
|
@Schema(description = "推广订单金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||||
private Integer brokerageOrderPrice;
|
private Integer brokerageOrderPrice;
|
||||||
|
|
||||||
// ========== 提现信息 ==========
|
// ========== 提现信息 ==========
|
||||||
|
|
||||||
@Schema(description = "已提现金额", example = "20019")
|
@Schema(description = "已提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||||
private Integer withdrawPrice;
|
private Integer withdrawPrice;
|
||||||
@Schema(description = "已提现次数", example = "20019")
|
@Schema(description = "已提现次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||||
private Integer withdrawCount;
|
private Integer withdrawCount;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue