Commit cbaadc3a77b99126978e39c768bbf08fdceaf352

Authored by niou233
2 parents 5facac73 4ae3d348

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

…-pro into feature/mall_product_org
Showing 266 changed files with 3598 additions and 2181 deletions

Too many changes.

To preserve performance only 100 of 266 files are displayed.

README.md
@@ -256,7 +256,7 @@ _鍓嶇鍩轰簬 crmeb uniapp 缁忚繃鎺堟潈閲嶆瀯锛屼紭鍖栦唬鐮佸疄鐜帮紝鎺ュ叆鑺嬮 @@ -256,7 +256,7 @@ _鍓嶇鍩轰簬 crmeb uniapp 缁忚繃鎺堟潈閲嶆瀯锛屼紭鍖栦唬鐮佸疄鐜帮紝鎺ュ叆鑺嬮
256 256
257 | 妗嗘灦 | 璇存槑 | 鐗堟湰 | 瀛︿範鎸囧崡 | 257 | 妗嗘灦 | 璇存槑 | 鐗堟湰 | 瀛︿範鎸囧崡 |
258 |---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------| 258 |---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------|
259 -| [Spring Boot](https://spring.io/projects/spring-boot) | 搴旂敤寮鍙戞鏋 | 2.7.16 | [鏂囨。](https://github.com/YunaiV/SpringBoot-Labs) | 259 +| [Spring Boot](https://spring.io/projects/spring-boot) | 搴旂敤寮鍙戞鏋 | 2.7.17 | [鏂囨。](https://github.com/YunaiV/SpringBoot-Labs) |
260 | [MySQL](https://www.mysql.com/cn/) | 鏁版嵁搴撴湇鍔″櫒 | 5.7 / 8.0+ | | 260 | [MySQL](https://www.mysql.com/cn/) | 鏁版嵁搴撴湇鍔″櫒 | 5.7 / 8.0+ | |
261 | [Druid](https://github.com/alibaba/druid) | JDBC 杩炴帴姹犮佺洃鎺х粍浠 | 1.2.19 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | 261 | [Druid](https://github.com/alibaba/druid) | JDBC 杩炴帴姹犮佺洃鎺х粍浠 | 1.2.19 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
262 | [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 澧炲己宸ュ叿鍖 | 3.5.3.2 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | 262 | [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 澧炲己宸ュ叿鍖 | 3.5.3.2 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
@@ -13,16 +13,16 @@ @@ -13,16 +13,16 @@
13 <!-- Server 主项目 --> 13 <!-- Server 主项目 -->
14 <module>yudao-server</module> 14 <module>yudao-server</module>
15 <!-- 各种 module 拓展 --> 15 <!-- 各种 module 拓展 -->
16 - <module>yudao-module-member</module>  
17 <module>yudao-module-system</module> 16 <module>yudao-module-system</module>
18 <module>yudao-module-infra</module> 17 <module>yudao-module-infra</module>
19 - <!-- <module>yudao-module-bpm</module>--> 18 + <module>yudao-module-member</module>
  19 +<!-- <module>yudao-module-bpm</module>-->
20 <!-- <module>yudao-module-report</module>--> 20 <!-- <module>yudao-module-report</module>-->
21 <!-- <module>yudao-module-mp</module>--> 21 <!-- <module>yudao-module-mp</module>-->
22 <module>yudao-module-pay</module> 22 <module>yudao-module-pay</module>
23 <module>yudao-module-mall</module> 23 <module>yudao-module-mall</module>
24 <!-- 示例项目 --> 24 <!-- 示例项目 -->
25 - <module>yudao-example</module> 25 +<!-- <module>yudao-example</module>-->
26 </modules> 26 </modules>
27 27
28 <name>${project.artifactId}</name> 28 <name>${project.artifactId}</name>
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 30 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
31 31
32 <properties> 32 <properties>
33 - <revision>1.8.2-snapshot</revision> 33 + <revision>1.8.3-snapshot</revision>
34 <!-- Maven 相关 --> 34 <!-- Maven 相关 -->
35 <java.version>1.8</java.version> 35 <java.version>1.8</java.version>
36 <maven.compiler.source>${java.version}</maven.compiler.source> 36 <maven.compiler.source>${java.version}</maven.compiler.source>
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> 40 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
41 <!-- 看看咋放到 bom 里 --> 41 <!-- 看看咋放到 bom 里 -->
42 <lombok.version>1.18.30</lombok.version> 42 <lombok.version>1.18.30</lombok.version>
43 - <spring.boot.version>2.7.16</spring.boot.version> 43 + <spring.boot.version>2.7.17</spring.boot.version>
44 <mapstruct.version>1.5.5.Final</mapstruct.version> 44 <mapstruct.version>1.5.5.Final</mapstruct.version>
45 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 45 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
46 </properties> 46 </properties>
sql/mysql/pay_wallet.sql
@@ -224,14 +224,33 @@ VALUES ( @@ -224,14 +224,33 @@ VALUES (
224 ); 224 );
225 225
226 -- 转账状态和转账类型数据字典 226 -- 转账状态和转账类型数据字典
227 -INSERT INTO `system_dict_type`(`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (171, '支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', b'0', '1970-01-01 00:00:00');  
228 -INSERT INTO `system_dict_type`(`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (170, '转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', b'0', '1970-01-01 00:00:00');  
229 -  
230 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1245, 4, '钱包余额', '4', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:37', '1', '2023-10-28 16:28:37', b'0');  
231 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1244, 3, '银行卡', '3', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:28:21', '1', '2023-10-28 16:28:21', b'0');  
232 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1243, 2, '微信余额', '2', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:07', '1', '2023-10-28 16:28:07', b'0');  
233 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1242, 1, '支付宝余额', '1', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:27:44', '1', '2023-10-28 16:27:44', b'0');  
234 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1241, 4, '转账失败', '30', 'pay_transfer_status', 0, 'warning', '', '', '1', '2023-10-28 16:24:16', '1', '2023-10-28 16:24:16', b'0');  
235 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1240, 3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', b'0');  
236 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1239, 2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23:12', b'0');  
237 -INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1238, 1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23:22', b'0'); 227 +INSERT INTO `system_dict_type`(`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES ('支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', b'0', '1970-01-01 00:00:00');
  228 +INSERT INTO `system_dict_type`(`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES ('转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', b'0', '1970-01-01 00:00:00');
  229 +
  230 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '钱包余额', '4', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:37', '1', '2023-10-28 16:28:37', b'0');
  231 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, '银行卡', '3', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:28:21', '1', '2023-10-28 16:28:21', b'0');
  232 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '微信余额', '2', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:07', '1', '2023-10-28 16:28:07', b'0');
  233 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '支付宝余额', '1', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:27:44', '1', '2023-10-28 16:27:44', b'0');
  234 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '转账失败', '30', 'pay_transfer_status', 0, 'warning', '', '', '1', '2023-10-28 16:24:16', '1', '2023-10-28 16:24:16', b'0');
  235 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', b'0');
  236 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23:12', b'0');
  237 +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23:22', b'0');
  238 +
  239 +-- 转账订单菜单脚本
  240 +
  241 +INSERT INTO system_menu(
  242 + name, permission, type, sort, parent_id,
  243 + path, icon, component, status, component_name
  244 +)
  245 +VALUES (
  246 + '转账订单', '', 2, 3, 1117,
  247 + 'transfer', 'ep:credit-card', 'pay/transfer/index', 0, 'PayTransfer'
  248 + );
  249 +
  250 +-- 转账通知脚本
  251 +
  252 +ALTER TABLE `pay_app`
  253 + ADD COLUMN `transfer_notify_url` varchar(1024) NOT NULL COMMENT '转账结果的回调地址' AFTER `refund_notify_url`;
  254 +ALTER TABLE `pay_notify_task`
  255 + MODIFY COLUMN `merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '商户订单编号' AFTER `status`,
  256 + ADD COLUMN `merchant_transfer_id` varchar(64) COMMENT '商户转账单编号' AFTER `merchant_order_id`;
238 \ No newline at end of file 257 \ No newline at end of file
sql/mysql/ruoyi-vue-pro.sql
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 Target Server Version : 80034 11 Target Server Version : 80034
12 File Encoding : 65001 12 File Encoding : 65001
13 13
14 - Date: 18/10/2023 23:33:15 14 + Date: 04/11/2023 20:42:49
15 */ 15 */
16 16
17 SET NAMES utf8mb4; 17 SET NAMES utf8mb4;
@@ -341,7 +341,8 @@ CREATE TABLE `infra_api_access_log` ( @@ -341,7 +341,8 @@ CREATE TABLE `infra_api_access_log` (
341 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 341 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
342 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 342 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
343 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 343 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
344 - PRIMARY KEY (`id`) USING BTREE 344 + PRIMARY KEY (`id`) USING BTREE,
  345 + INDEX `idx_create_time`(`create_time` ASC) USING BTREE
345 ) ENGINE = InnoDB AUTO_INCREMENT = 35832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; 346 ) ENGINE = InnoDB AUTO_INCREMENT = 35832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
346 347
347 -- ---------------------------- 348 -- ----------------------------
@@ -384,7 +385,7 @@ CREATE TABLE `infra_api_error_log` ( @@ -384,7 +385,7 @@ CREATE TABLE `infra_api_error_log` (
384 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 385 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
385 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 386 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
386 PRIMARY KEY (`id`) USING BTREE 387 PRIMARY KEY (`id`) USING BTREE
387 -) ENGINE = InnoDB AUTO_INCREMENT = 1739 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; 388 +) ENGINE = InnoDB AUTO_INCREMENT = 1781 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
388 389
389 -- ---------------------------- 390 -- ----------------------------
390 -- Records of infra_api_error_log 391 -- Records of infra_api_error_log
@@ -422,7 +423,7 @@ CREATE TABLE `infra_codegen_column` ( @@ -422,7 +423,7 @@ CREATE TABLE `infra_codegen_column` (
422 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 423 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
423 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 424 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
424 PRIMARY KEY (`id`) USING BTREE 425 PRIMARY KEY (`id`) USING BTREE
425 -) ENGINE = InnoDB AUTO_INCREMENT = 1805 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; 426 +) ENGINE = InnoDB AUTO_INCREMENT = 1804 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
426 427
427 -- ---------------------------- 428 -- ----------------------------
428 -- Records of infra_codegen_column 429 -- Records of infra_codegen_column
@@ -455,7 +456,7 @@ CREATE TABLE `infra_codegen_table` ( @@ -455,7 +456,7 @@ CREATE TABLE `infra_codegen_table` (
455 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 456 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
456 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 457 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
457 PRIMARY KEY (`id`) USING BTREE 458 PRIMARY KEY (`id`) USING BTREE
458 -) ENGINE = InnoDB AUTO_INCREMENT = 137 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; 459 +) ENGINE = InnoDB AUTO_INCREMENT = 136 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
459 460
460 -- ---------------------------- 461 -- ----------------------------
461 -- Records of infra_codegen_table 462 -- Records of infra_codegen_table
@@ -538,7 +539,7 @@ CREATE TABLE `infra_file` ( @@ -538,7 +539,7 @@ CREATE TABLE `infra_file` (
538 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 539 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
539 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 540 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
540 PRIMARY KEY (`id`) USING BTREE 541 PRIMARY KEY (`id`) USING BTREE
541 -) ENGINE = InnoDB AUTO_INCREMENT = 1098 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; 542 +) ENGINE = InnoDB AUTO_INCREMENT = 1108 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
542 543
543 -- ---------------------------- 544 -- ----------------------------
544 -- Records of infra_file 545 -- Records of infra_file
@@ -587,7 +588,7 @@ CREATE TABLE `infra_file_content` ( @@ -587,7 +588,7 @@ CREATE TABLE `infra_file_content` (
587 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 588 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
588 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 589 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
589 PRIMARY KEY (`id`) USING BTREE 590 PRIMARY KEY (`id`) USING BTREE
590 -) ENGINE = InnoDB AUTO_INCREMENT = 191 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; 591 +) ENGINE = InnoDB AUTO_INCREMENT = 202 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
591 592
592 -- ---------------------------- 593 -- ----------------------------
593 -- Records of infra_file_content 594 -- Records of infra_file_content
@@ -615,7 +616,7 @@ CREATE TABLE `infra_job` ( @@ -615,7 +616,7 @@ CREATE TABLE `infra_job` (
615 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 616 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
616 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 617 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
617 PRIMARY KEY (`id`) USING BTREE 618 PRIMARY KEY (`id`) USING BTREE
618 -) ENGINE = InnoDB AUTO_INCREMENT = 28 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表'; 619 +) ENGINE = InnoDB AUTO_INCREMENT = 27 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
619 620
620 -- ---------------------------- 621 -- ----------------------------
621 -- Records of infra_job 622 -- Records of infra_job
@@ -656,7 +657,7 @@ CREATE TABLE `infra_job_log` ( @@ -656,7 +657,7 @@ CREATE TABLE `infra_job_log` (
656 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 657 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
657 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 658 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
658 PRIMARY KEY (`id`) USING BTREE 659 PRIMARY KEY (`id`) USING BTREE
659 -) ENGINE = InnoDB AUTO_INCREMENT = 233 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; 660 +) ENGINE = InnoDB AUTO_INCREMENT = 232 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
660 661
661 -- ---------------------------- 662 -- ----------------------------
662 -- Records of infra_job_log 663 -- Records of infra_job_log
@@ -709,7 +710,7 @@ CREATE TABLE `member_address` ( @@ -709,7 +710,7 @@ CREATE TABLE `member_address` (
709 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 710 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
710 PRIMARY KEY (`id`) USING BTREE, 711 PRIMARY KEY (`id`) USING BTREE,
711 INDEX `idx_userId`(`user_id` ASC) USING BTREE 712 INDEX `idx_userId`(`user_id` ASC) USING BTREE
712 -) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址'; 713 +) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址';
713 714
714 -- ---------------------------- 715 -- ----------------------------
715 -- Records of member_address 716 -- Records of member_address
@@ -807,6 +808,7 @@ INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, ` @@ -807,6 +808,7 @@ INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `
807 INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (34, 248, '125', 11, '下单奖励', '下单获得 700100 经验', 700100, 700100, NULL, '2023-10-11 07:33:29', NULL, '2023-10-11 07:33:29', b'0', 1); 808 INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (34, 248, '125', 11, '下单奖励', '下单获得 700100 经验', 700100, 700100, NULL, '2023-10-11 07:33:29', NULL, '2023-10-11 07:33:29', b'0', 1);
808 INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (37, 248, '127', 11, '下单奖励', '下单获得 385145 经验', 385145, 385145, NULL, '2023-10-11 07:36:44', NULL, '2023-10-11 07:36:44', b'0', 1); 809 INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (37, 248, '127', 11, '下单奖励', '下单获得 385145 经验', 385145, 385145, NULL, '2023-10-11 07:36:44', NULL, '2023-10-11 07:36:44', b'0', 1);
809 INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (40, 248, '120', 13, '下单奖励(单个取消)', '退款订单获得 -385145 经验', -385145, 0, '1', '2023-10-11 07:39:26', '1', '2023-10-11 07:39:26', b'0', 1); 810 INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (40, 248, '120', 13, '下单奖励(单个取消)', '退款订单获得 -385145 经验', -385145, 0, '1', '2023-10-11 07:39:26', '1', '2023-10-11 07:39:26', b'0', 1);
  811 +INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title`, `description`, `experience`, `total_experience`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (41, 248, '131', 11, '下单奖励', '下单获得 700100 经验', 700100, 700100, NULL, '2023-10-24 12:33:22', NULL, '2023-10-24 12:33:22', b'0', 1);
810 COMMIT; 812 COMMIT;
811 813
812 -- ---------------------------- 814 -- ----------------------------
@@ -825,7 +827,7 @@ CREATE TABLE `member_group` ( @@ -825,7 +827,7 @@ CREATE TABLE `member_group` (
825 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 827 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
826 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 828 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
827 PRIMARY KEY (`id`) USING BTREE 829 PRIMARY KEY (`id`) USING BTREE
828 -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户分组'; 830 +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户分组';
829 831
830 -- ---------------------------- 832 -- ----------------------------
831 -- Records of member_group 833 -- Records of member_group
@@ -853,7 +855,7 @@ CREATE TABLE `member_level` ( @@ -853,7 +855,7 @@ CREATE TABLE `member_level` (
853 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 855 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
854 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 856 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
855 PRIMARY KEY (`id`) USING BTREE 857 PRIMARY KEY (`id`) USING BTREE
856 -) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级'; 858 +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级';
857 859
858 -- ---------------------------- 860 -- ----------------------------
859 -- Records of member_level 861 -- Records of member_level
@@ -971,6 +973,7 @@ INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title @@ -971,6 +973,7 @@ INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title
971 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 (53, 248, '125', 21, '订单积分奖励', '下单获得 21003 积分', 21003, 21003, NULL, '2023-10-11 07:33:29', NULL, '2023-10-11 07:33:29', b'0', 1); 973 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 (53, 248, '125', 21, '订单积分奖励', '下单获得 21003 积分', 21003, 21003, NULL, '2023-10-11 07:33:29', NULL, '2023-10-11 07:33:29', b'0', 1);
972 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 (56, 248, '127', 21, '订单积分奖励', '下单获得 11554 积分', 11554, 11554, NULL, '2023-10-11 07:36:44', NULL, '2023-10-11 07:36:44', b'0', 1); 974 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 (56, 248, '127', 21, '订单积分奖励', '下单获得 11554 积分', 11554, 11554, NULL, '2023-10-11 07:36:44', NULL, '2023-10-11 07:36:44', b'0', 1);
973 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 (59, 248, '120', 23, '订单积分奖励(单个退款)', '订单退款,扣除赠送的 -11554 积分', -11554, 0, '1', '2023-10-11 07:39:26', '1', '2023-10-11 07:39:26', b'0', 1); 975 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 (59, 248, '120', 23, '订单积分奖励(单个退款)', '订单退款,扣除赠送的 -11554 积分', -11554, 0, '1', '2023-10-11 07:39:26', '1', '2023-10-11 07:39:26', b'0', 1);
  976 +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 (60, 248, '131', 21, '订单积分奖励', '下单获得 21003 积分', 21003, 21003, NULL, '2023-10-24 12:33:22', NULL, '2023-10-24 12:33:22', b'0', 1);
974 COMMIT; 977 COMMIT;
975 978
976 -- ---------------------------- 979 -- ----------------------------
@@ -1052,7 +1055,7 @@ CREATE TABLE `member_tag` ( @@ -1052,7 +1055,7 @@ CREATE TABLE `member_tag` (
1052 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1055 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1053 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 1056 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
1054 PRIMARY KEY (`id`) USING BTREE 1057 PRIMARY KEY (`id`) USING BTREE
1055 -) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员标签'; 1058 +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员标签';
1056 1059
1057 -- ---------------------------- 1060 -- ----------------------------
1058 -- Records of member_tag 1061 -- Records of member_tag
@@ -1162,7 +1165,7 @@ CREATE TABLE `system_dict_data` ( @@ -1162,7 +1165,7 @@ CREATE TABLE `system_dict_data` (
1162 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 1165 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
1163 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1166 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1164 PRIMARY KEY (`id`) USING BTREE 1167 PRIMARY KEY (`id`) USING BTREE
1165 -) ENGINE = InnoDB AUTO_INCREMENT = 1398 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; 1168 +) ENGINE = InnoDB AUTO_INCREMENT = 1435 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
1166 1169
1167 -- ---------------------------- 1170 -- ----------------------------
1168 -- Records of system_dict_data 1171 -- Records of system_dict_data
@@ -1248,6 +1251,11 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st @@ -1248,6 +1251,11 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1248 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (123, 10, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2023-07-19 18:04:28', b'0'); 1251 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (123, 10, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2023-07-19 18:04:28', b'0');
1249 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (124, 30, '支付关闭', '30', 'pay_order_status', 0, 'info', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2023-07-19 18:05:07', b'0'); 1252 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (124, 30, '支付关闭', '30', 'pay_order_status', 0, 'info', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2023-07-19 18:05:07', b'0');
1250 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (125, 0, '等待支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2023-07-19 18:04:15', b'0'); 1253 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (125, 0, '等待支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2023-07-19 18:04:15', b'0');
  1254 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (600, 5, '首页', '1', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0');
  1255 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (601, 4, '秒杀活动页', '2', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0');
  1256 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (602, 3, '砍价活动页', '3', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0');
  1257 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (603, 2, '限时折扣页', '4', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0');
  1258 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (604, 1, '满减送页', '5', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0');
1251 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, 0, '等待退款', '0', 'pay_refund_status', 0, 'info', '', '等待退款', '1', '2021-12-10 16:44:59', '1', '2023-07-19 10:14:39', b'0'); 1259 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1118, 0, '等待退款', '0', 'pay_refund_status', 0, 'info', '', '等待退款', '1', '2021-12-10 16:44:59', '1', '2023-07-19 10:14:39', b'0');
1252 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, 20, '退款失败', '20', 'pay_refund_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2023-07-19 10:15:10', b'0'); 1260 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1119, 20, '退款失败', '20', 'pay_refund_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2023-07-19 10:15:10', b'0');
1253 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1124, 10, '退款成功', '10', 'pay_refund_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:46:26', '1', '2023-07-19 10:15:00', b'0'); 1261 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1124, 10, '退款成功', '10', 'pay_refund_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:46:26', '1', '2023-07-19 10:15:00', b'0');
@@ -1427,6 +1435,45 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st @@ -1427,6 +1435,45 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1427 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1395, 22, '订单积分奖励(整单取消)', '22', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:42:55', '1', '2023-10-11 07:43:01', b'0'); 1435 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1395, 22, '订单积分奖励(整单取消)', '22', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:42:55', '1', '2023-10-11 07:43:01', b'0');
1428 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1396, 23, '订单积分奖励(单个退款)', '23', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:43:16', '1', '2023-10-11 07:43:16', b'0'); 1436 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1396, 23, '订单积分奖励(单个退款)', '23', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:43:16', '1', '2023-10-11 07:43:16', b'0');
1429 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1397, 13, '下单奖励(单个退款)', '13', 'member_experience_biz_type', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0'); 1437 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1397, 13, '下单奖励(单个退款)', '13', 'member_experience_biz_type', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', b'0');
  1438 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1402, 1, 'A 农、林、牧、渔业', '1', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:15', '1', '2023-10-28 23:02:15', b'0');
  1439 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1403, 2, 'B 采矿业', '2', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:29', '1', '2023-10-28 23:02:29', b'0');
  1440 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1404, 3, 'C 制造业', '3', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:41', '1', '2023-10-28 23:02:41', b'0');
  1441 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1405, 4, 'D 电力、热力、燃气及水生产和供应业', '4', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:54', '1', '2023-10-28 23:02:54', b'0');
  1442 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1406, 5, 'E 建筑业', '5', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:03', '1', '2023-10-28 23:03:03', b'0');
  1443 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1407, 6, 'F 批发和零售业', '6', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:13', '1', '2023-10-28 23:03:13', b'0');
  1444 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1408, 7, 'G 交通运输、仓储和邮政业', '7', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:27', '1', '2023-10-28 23:03:27', b'0');
  1445 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1409, 8, 'H 住宿和餐饮业', '8', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:37', '1', '2023-10-28 23:03:37', b'0');
  1446 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1410, 9, 'I 信息传输、软件和信息技术服务业', '9', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:47', '1', '2023-10-28 23:03:47', b'0');
  1447 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1411, 10, 'J 金融业', '10', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:57', '1', '2023-10-28 23:03:57', b'0');
  1448 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1412, 11, 'K 房地产业', '11', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:15', '1', '2023-10-28 23:04:22', b'0');
  1449 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1413, 12, 'L 租赁和商务服务业', '12', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:33', '1', '2023-10-28 23:04:33', b'0');
  1450 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1414, 13, 'M 科学研究和技术服务业', '13', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:43', '1', '2023-10-28 23:04:43', b'0');
  1451 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1415, 14, 'N 水利、环境和公共设施管理业', '14', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:53', '1', '2023-10-28 23:04:53', b'0');
  1452 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1416, 15, 'O 居民服务、修理和其他服务业', '15', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:05', '1', '2023-10-28 23:05:05', b'0');
  1453 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1417, 16, 'P 教育', '16', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:15', '1', '2023-10-28 23:05:15', b'0');
  1454 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1418, 17, 'Q 卫生和社会工作', '17', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:44', '1', '2023-10-28 23:05:44', b'0');
  1455 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1419, 18, 'R 文化、体育和娱乐业', '18', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:55', '1', '2023-10-28 23:05:55', b'0');
  1456 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1420, 19, 'S 公共管理、社会保障和社会组织', '19', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:06:05', '1', '2023-10-28 23:06:05', b'0');
  1457 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1421, 20, 'T 国际组织', '20', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:06:15', '1', '2023-10-28 23:06:15', b'0');
  1458 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1422, 1, 'A (重点客户)', '1', 'crm_customer_level', 0, 'primary', '', '', '1', '2023-10-28 23:07:13', '1', '2023-10-28 23:07:13', b'0');
  1459 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1423, 2, 'B (普通客户)', '2', 'crm_customer_level', 0, 'info', '', '', '1', '2023-10-28 23:07:35', '1', '2023-10-28 23:07:35', b'0');
  1460 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1424, 3, 'C (非优先客户)', '3', 'crm_customer_level', 0, 'default', '', '', '1', '2023-10-28 23:07:53', '1', '2023-10-28 23:07:53', b'0');
  1461 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1425, 1, '促销', '1', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:29', '1', '2023-10-28 23:08:29', b'0');
  1462 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1426, 2, '搜索引擎', '2', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:39', '1', '2023-10-28 23:08:39', b'0');
  1463 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1427, 3, '广告', '3', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:47', '1', '2023-10-28 23:08:47', b'0');
  1464 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1428, 4, '转介绍', '4', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:58', '1', '2023-10-28 23:08:58', b'0');
  1465 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1429, 5, '线上注册', '5', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:12', '1', '2023-10-28 23:09:12', b'0');
  1466 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1430, 6, '线上咨询', '6', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:22', '1', '2023-10-28 23:09:22', b'0');
  1467 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1431, 7, '预约上门', '7', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:39', '1', '2023-10-28 23:09:39', b'0');
  1468 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1432, 8, '陌拜', '8', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:04', '1', '2023-10-28 23:10:04', b'0');
  1469 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1433, 9, '电话咨询', '9', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:18', '1', '2023-10-28 23:10:18', b'0');
  1470 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1434, 10, '邮件咨询', '10', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:33', '1', '2023-10-28 23:10:33', b'0');
  1471 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1435, 10, 'Gitee', '10', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:04:42', '1', '2023-11-04 13:04:42', b'0');
  1472 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1436, 20, '钉钉', '20', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:04:54', '1', '2023-11-04 13:04:54', b'0');
  1473 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1437, 30, '企业微信', '30', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:09', '1', '2023-11-04 13:05:09', b'0');
  1474 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1438, 31, '微信公众平台', '31', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:18', '1', '2023-11-04 13:05:18', b'0');
  1475 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1439, 32, '微信开放平台', '32', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:30', '1', '2023-11-04 13:05:30', b'0');
  1476 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1440, 34, '微信小程序', '34', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:38', '1', '2023-11-04 13:07:16', b'0');
1430 COMMIT; 1477 COMMIT;
1431 1478
1432 -- ---------------------------- 1479 -- ----------------------------
@@ -1447,7 +1494,7 @@ CREATE TABLE `system_dict_type` ( @@ -1447,7 +1494,7 @@ CREATE TABLE `system_dict_type` (
1447 `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', 1494 `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
1448 PRIMARY KEY (`id`) USING BTREE, 1495 PRIMARY KEY (`id`) USING BTREE,
1449 UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE 1496 UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
1450 -) ENGINE = InnoDB AUTO_INCREMENT = 185 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; 1497 +) ENGINE = InnoDB AUTO_INCREMENT = 600 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
1451 1498
1452 -- ---------------------------- 1499 -- ----------------------------
1453 -- Records of system_dict_type 1500 -- Records of system_dict_type
@@ -1521,6 +1568,11 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat @@ -1521,6 +1568,11 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
1521 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (182, '佣金提现银行', 'brokerage_bank_name', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', b'0', NULL); 1568 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (182, '佣金提现银行', 'brokerage_bank_name', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', b'0', NULL);
1522 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (183, '砍价记录的状态', 'promotion_bargain_record_status', 0, '', '1', '2023-10-05 10:41:08', '1', '2023-10-05 10:41:08', b'0', '1970-01-01 00:00:00'); 1569 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (183, '砍价记录的状态', 'promotion_bargain_record_status', 0, '', '1', '2023-10-05 10:41:08', '1', '2023-10-05 10:41:08', b'0', '1970-01-01 00:00:00');
1523 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (184, '拼团记录的状态', 'promotion_combination_record_status', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-10-08 07:24:25', b'0', '1970-01-01 00:00:00'); 1570 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (184, '拼团记录的状态', 'promotion_combination_record_status', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-10-08 07:24:25', b'0', '1970-01-01 00:00:00');
  1571 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (186, '客户所属行业', 'crm_customer_industry', 0, 'CRM 客户所属行业', '1', '2023-10-28 22:57:07', '1', '2023-10-28 15:11:16', b'0', NULL);
  1572 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (187, '客户等级', 'crm_customer_level', 0, 'CRM 客户等级', '1', '2023-10-28 22:59:12', '1', '2023-10-28 15:11:16', b'0', NULL);
  1573 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (188, '客户来源', 'crm_customer_source', 0, 'CRM 客户来源', '1', '2023-10-28 23:00:34', '1', '2023-10-28 15:11:16', b'0', NULL);
  1574 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (600, 'Banner 位置', 'promotion_banner_position', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-11-04 13:04:02', b'0', '1970-01-01 00:00:00');
  1575 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (601, '社交类型', 'system_social_type', 0, '', '1', '2023-11-04 13:03:54', '1', '2023-11-04 13:03:54', b'0', '1970-01-01 00:00:00');
1524 COMMIT; 1576 COMMIT;
1525 1577
1526 -- ---------------------------- 1578 -- ----------------------------
@@ -1540,7 +1592,7 @@ CREATE TABLE `system_error_code` ( @@ -1540,7 +1592,7 @@ CREATE TABLE `system_error_code` (
1540 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 1592 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
1541 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1593 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1542 PRIMARY KEY (`id`) USING BTREE 1594 PRIMARY KEY (`id`) USING BTREE
1543 -) ENGINE = InnoDB AUTO_INCREMENT = 5933 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表'; 1595 +) ENGINE = InnoDB AUTO_INCREMENT = 5932 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
1544 1596
1545 -- ---------------------------- 1597 -- ----------------------------
1546 -- Records of system_error_code 1598 -- Records of system_error_code
@@ -1569,7 +1621,7 @@ CREATE TABLE `system_login_log` ( @@ -1569,7 +1621,7 @@ CREATE TABLE `system_login_log` (
1569 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1621 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1570 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 1622 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
1571 PRIMARY KEY (`id`) USING BTREE 1623 PRIMARY KEY (`id`) USING BTREE
1572 -) ENGINE = InnoDB AUTO_INCREMENT = 2599 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; 1624 +) ENGINE = InnoDB AUTO_INCREMENT = 2631 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
1573 1625
1574 -- ---------------------------- 1626 -- ----------------------------
1575 -- Records of system_login_log 1627 -- Records of system_login_log
@@ -1699,7 +1751,7 @@ CREATE TABLE `system_menu` ( @@ -1699,7 +1751,7 @@ CREATE TABLE `system_menu` (
1699 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 1751 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
1700 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 1752 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
1701 PRIMARY KEY (`id`) USING BTREE 1753 PRIMARY KEY (`id`) USING BTREE
1702 -) ENGINE = InnoDB AUTO_INCREMENT = 2389 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; 1754 +) ENGINE = InnoDB AUTO_INCREMENT = 2449 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
1703 1755
1704 -- ---------------------------- 1756 -- ----------------------------
1705 -- Records of system_menu 1757 -- Records of system_menu
@@ -1951,11 +2003,11 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i @@ -1951,11 +2003,11 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
1951 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2021, '规格创建', 'product:property:create', 3, 2, 2019, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:30', b'0'); 2003 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2021, '规格创建', 'product:property:create', 3, 2, 2019, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:30', b'0');
1952 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2022, '规格更新', 'product:property:update', 3, 3, 2019, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:33', b'0'); 2004 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2022, '规格更新', 'product:property:update', 3, 3, 2019, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:33', b'0');
1953 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2023, '规格删除', 'product:property:delete', 3, 4, 2019, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:37', b'0'); 2005 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2023, '规格删除', 'product:property:delete', 3, 4, 2019, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:37', b'0');
1954 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2025, 'Banner管理', '', 2, 100, 2387, 'banner', 'fa:bandcamp', 'mall/market/banner/index', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '1', '2023-10-16 09:41:54', b'0');  
1955 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2026, 'Banner查询', 'market:banner:query', 3, 1, 2025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');  
1956 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2027, 'Banner创建', 'market:banner:create', 3, 2, 2025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');  
1957 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2028, 'Banner更新', 'market:banner:update', 3, 3, 2025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');  
1958 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'market:banner:delete', 3, 4, 2025, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0'); 2006 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2025, 'Banner', '', 2, 100, 2387, 'banner', 'fa:bandcamp', 'mall/promotion/banner/index', NULL, 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:06', b'0');
  2007 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2026, 'Banner查询', 'promotion:banner:query', 3, 1, 2025, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:18', b'0');
  2008 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2027, 'Banner创建', 'promotion:banner:create', 3, 2, 2025, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:23', b'0');
  2009 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2028, 'Banner更新', 'promotion:banner:update', 3, 3, 2025, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:28', b'0');
  2010 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'promotion:banner:delete', 3, 4, 2025, '', '', '', '', 0, b'1', b'1', b'1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:36', b'0');
1959 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2030, '营销中心', '', 1, 70, 2362, 'promotion', 'ep:present', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-10-31 21:25:09', '1', '2023-09-30 11:54:27', b'0'); 2011 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2030, '营销中心', '', 1, 70, 2362, 'promotion', 'ep:present', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-10-31 21:25:09', '1', '2023-09-30 11:54:27', b'0');
1960 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2032, '优惠劵列表', '', 2, 1, 2365, 'template', 'ep:discount', 'mall/promotion/coupon/template/index', 'PromotionCouponTemplate', 0, b'1', b'1', b'1', '', '2022-10-31 22:27:14', '1', '2023-10-03 12:40:06', b'0'); 2012 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2032, '优惠劵列表', '', 2, 1, 2365, 'template', 'ep:discount', 'mall/promotion/coupon/template/index', 'PromotionCouponTemplate', 0, b'1', b'1', b'1', '', '2022-10-31 22:27:14', '1', '2023-10-03 12:40:06', b'0');
1961 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2033, '优惠劵模板查询', 'promotion:coupon-template:query', 3, 1, 2032, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-10-31 22:27:14', '', '2022-10-31 22:27:14', b'0'); 2013 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2033, '优惠劵模板查询', 'promotion:coupon-template:query', 3, 1, 2032, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-10-31 22:27:14', '', '2022-10-31 22:27:14', b'0');
@@ -1965,13 +2017,13 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i @@ -1965,13 +2017,13 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
1965 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2038, '领取记录', '', 2, 2, 2365, 'list', 'ep:collection-tag', 'mall/promotion/coupon/index', 'PromotionCoupon', 0, b'1', b'1', b'1', '', '2022-11-03 23:21:31', '1', '2023-10-03 12:55:30', b'0'); 2017 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2038, '领取记录', '', 2, 2, 2365, 'list', 'ep:collection-tag', 'mall/promotion/coupon/index', 'PromotionCoupon', 0, b'1', b'1', b'1', '', '2022-11-03 23:21:31', '1', '2023-10-03 12:55:30', b'0');
1966 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2039, '优惠劵查询', 'promotion:coupon:query', 3, 1, 2038, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-03 23:21:31', '', '2022-11-03 23:21:31', b'0'); 2018 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2039, '优惠劵查询', 'promotion:coupon:query', 3, 1, 2038, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-03 23:21:31', '', '2022-11-03 23:21:31', b'0');
1967 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2040, '优惠劵删除', 'promotion:coupon:delete', 3, 4, 2038, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-03 23:21:31', '', '2022-11-03 23:21:31', b'0'); 2019 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2040, '优惠劵删除', 'promotion:coupon:delete', 3, 4, 2038, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-03 23:21:31', '', '2022-11-03 23:21:31', b'0');
1968 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2041, '满减送活动', '', 2, 10, 2030, 'reward-activity', 'ep:goblet-square-full', 'mall/promotion/rewardActivity/index', 'PromotionRewardActivity', 0, b'1', b'1', b'1', '', '2022-11-04 23:47:49', '1', '2023-10-05 00:16:38', b'0'); 2020 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2041, '满减送', '', 2, 10, 2390, 'reward-activity', 'ep:goblet-square-full', 'mall/promotion/rewardActivity/index', 'PromotionRewardActivity', 0, b'1', b'1', b'1', '', '2022-11-04 23:47:49', '1', '2023-10-21 19:24:46', b'0');
1969 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2042, '满减送活动查询', 'promotion:reward-activity:query', 3, 1, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:49', '', '2022-11-04 23:47:49', b'0'); 2021 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2042, '满减送活动查询', 'promotion:reward-activity:query', 3, 1, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:49', '', '2022-11-04 23:47:49', b'0');
1970 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2043, '满减送活动创建', 'promotion:reward-activity:create', 3, 2, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:49', '', '2022-11-04 23:47:49', b'0'); 2022 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2043, '满减送活动创建', 'promotion:reward-activity:create', 3, 2, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:49', '', '2022-11-04 23:47:49', b'0');
1971 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2044, '满减送活动更新', 'promotion:reward-activity:update', 3, 3, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:50', '', '2022-11-04 23:47:50', b'0'); 2023 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2044, '满减送活动更新', 'promotion:reward-activity:update', 3, 3, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:50', '', '2022-11-04 23:47:50', b'0');
1972 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2045, '满减送活动删除', 'promotion:reward-activity:delete', 3, 4, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:50', '', '2022-11-04 23:47:50', b'0'); 2024 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2045, '满减送活动删除', 'promotion:reward-activity:delete', 3, 4, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-04 23:47:50', '', '2022-11-04 23:47:50', b'0');
1973 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2046, '满减送活动关闭', 'promotion:reward-activity:close', 3, 5, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-11-05 10:42:53', '1', '2022-11-05 10:42:53', b'0'); 2025 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2046, '满减送活动关闭', 'promotion:reward-activity:close', 3, 5, 2041, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-11-05 10:42:53', '1', '2022-11-05 10:42:53', b'0');
1974 -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2047, '限时折扣活动', '', 2, 7, 2030, 'discount-activity', 'ep:timer', 'mall/promotion/discountActivity/index', 'PromotionDiscountActivity', 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '1', '2023-10-05 00:16:25', b'0'); 2026 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2047, '限时折扣', '', 2, 7, 2390, 'discount-activity', 'ep:timer', 'mall/promotion/discountActivity/index', 'PromotionDiscountActivity', 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '1', '2023-10-21 19:24:21', b'0');
1975 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2048, '限时折扣活动查询', 'promotion:discount-activity:query', 3, 1, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0'); 2027 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2048, '限时折扣活动查询', 'promotion:discount-activity:query', 3, 1, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0');
1976 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0'); 2028 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', b'0');
1977 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0'); 2029 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', b'0');
@@ -2193,6 +2245,71 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i @@ -2193,6 +2245,71 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
2193 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2386, '文章管理删除', 'promotion:article:delete', 3, 4, 2382, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', b'0'); 2245 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2386, '文章管理删除', 'promotion:article:delete', 3, 4, 2382, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', b'0');
2194 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2387, '内容管理', '', 1, 1, 2030, 'content', 'ep:collection', '', '', 0, b'1', b'1', b'1', '1', '2023-10-16 09:37:31', '1', '2023-10-16 09:37:31', b'0'); 2246 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2387, '内容管理', '', 1, 1, 2030, 'content', 'ep:collection', '', '', 0, b'1', b'1', b'1', '1', '2023-10-16 09:37:31', '1', '2023-10-16 09:37:31', b'0');
2195 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2388, '商城首页', '', 2, 1, 2362, 'home', 'ep:home-filled', 'mall/home/index', 'MallHome', 0, b'1', b'1', b'1', '', '2023-10-16 12:10:33', '', '2023-10-16 12:10:33', b'0'); 2247 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2388, '商城首页', '', 2, 1, 2362, 'home', 'ep:home-filled', 'mall/home/index', 'MallHome', 0, b'1', b'1', b'1', '', '2023-10-16 12:10:33', '', '2023-10-16 12:10:33', b'0');
  2248 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2389, '核销订单', '', 2, 2, 2166, 'pick-up-order', 'ep:list', 'mall/trade/delivery/pickUpOrder/index', 'PickUpOrder', 0, b'1', b'1', b'1', '', '2023-10-19 16:09:51', '', '2023-10-19 16:09:51', b'0');
  2249 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2390, '优惠活动', '', 1, 99, 2030, 'youhui', 'ep:aim', '', '', 0, b'1', b'1', b'1', '1', '2023-10-21 19:23:49', '1', '2023-10-21 19:23:49', b'0');
  2250 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2391, '客户管理', '', 2, 0, 2397, 'customer', 'fa:address-book-o', 'crm/customer/index', 'CrmCustomer', 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '1', '2023-10-29 17:11:03', b'0');
  2251 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2392, '客户查询', 'crm:customer:query', 3, 1, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0');
  2252 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2393, '客户创建', 'crm:customer:create', 3, 2, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0');
  2253 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2394, '客户更新', 'crm:customer:update', 3, 3, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0');
  2254 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2395, '客户删除', 'crm:customer:delete', 3, 4, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0');
  2255 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2396, '客户导出', 'crm:customer:export', 3, 5, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0');
  2256 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2397, '客户管理系统', '', 1, 200, 0, '/crm', 'ep:avatar', '', '', 0, b'1', b'1', b'1', '1', '2023-10-29 17:08:30', '1', '2023-10-29 17:08:30', b'0');
  2257 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2398, '合同管理', '', 2, 1, 2397, 'contract', 'ep:notebook', 'crm/contract/index', 'CrmContract', 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '1', '2023-10-29 18:55:53', b'0');
  2258 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2399, '合同查询', 'crm:contract:query', 3, 1, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0');
  2259 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2400, '合同创建', 'crm:contract:create', 3, 2, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0');
  2260 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2401, '合同更新', 'crm:contract:update', 3, 3, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0');
  2261 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2402, '合同删除', 'crm:contract:delete', 3, 4, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0');
  2262 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2403, '合同导出', 'crm:contract:export', 3, 5, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0');
  2263 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2404, '线索管理', '', 2, 0, 2397, 'clue', 'fa:pagelines', 'crm/clue/index', 'CrmClue', 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '1', '2023-10-29 19:08:35', b'0');
  2264 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2405, '线索查询', 'crm:clue:query', 3, 1, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0');
  2265 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2406, '线索创建', 'crm:clue:create', 3, 2, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0');
  2266 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2407, '线索更新', 'crm:clue:update', 3, 3, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0');
  2267 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2408, '线索删除', 'crm:clue:delete', 3, 4, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0');
  2268 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2409, '线索导出', 'crm:clue:export', 3, 5, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0');
  2269 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2410, '商机管理', '', 2, 0, 2397, 'business', 'fa:bus', 'crm/business/index', 'CrmBusiness', 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '1', '2023-10-29 19:13:01', b'0');
  2270 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2411, '商机查询', 'crm:business:query', 3, 1, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0');
  2271 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2412, '商机创建', 'crm:business:create', 3, 2, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0');
  2272 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2413, '商机更新', 'crm:business:update', 3, 3, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0');
  2273 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2414, '商机删除', 'crm:business:delete', 3, 4, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0');
  2274 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2415, '商机导出', 'crm:business:export', 3, 5, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0');
  2275 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2416, '联系人管理', '', 2, 0, 2397, 'contact', 'fa:address-book-o', 'crm/contact/index', 'Contact', 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '1', '2023-10-29 19:15:32', b'0');
  2276 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2417, '联系人查询', 'crm:contact:query', 3, 1, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0');
  2277 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2418, '联系人创建', 'crm:contact:create', 3, 2, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0');
  2278 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2419, '联系人更新', 'crm:contact:update', 3, 3, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0');
  2279 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2420, '联系人删除', 'crm:contact:delete', 3, 4, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0');
  2280 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2421, '联系人导出', 'crm:contact:export', 3, 5, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0');
  2281 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2422, '回款管理', '', 2, 0, 2397, 'receivable', 'ep:money', 'crm/receivable/index', 'CrmReceivable', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-10-29 19:18:52', b'0');
  2282 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2423, '回款管理查询', 'crm:receivable:query', 3, 1, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2283 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2424, '回款管理创建', 'crm:receivable:create', 3, 2, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2284 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2425, '回款管理更新', 'crm:receivable:update', 3, 3, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2285 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2426, '回款管理删除', 'crm:receivable:delete', 3, 4, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2286 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2427, '回款管理导出', 'crm:receivable:export', 3, 5, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2287 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2428, '回款计划管理', '', 2, 0, 2397, 'receivable-plan', 'fa:money', 'crm/receivablePlan/index', 'CrmReceivablePlan', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-10-29 19:19:08', b'0');
  2288 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2429, '回款计划查询', 'crm:receivable-plan:query', 3, 1, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2289 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2430, '回款计划创建', 'crm:receivable-plan:create', 3, 2, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2290 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2431, '回款计划更新', 'crm:receivable-plan:update', 3, 3, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2291 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2432, '回款计划删除', 'crm:receivable-plan:delete', 3, 4, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2292 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2433, '回款计划导出', 'crm:receivable-plan:export', 3, 5, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0');
  2293 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2434, '核销订单', '', 2, 2, 2166, 'pick-up-order', 'ep:list', 'mall/trade/delivery/pickUpOrder/index', 'PickUpOrder', 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2294 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2435, '商城装修', '', 2, 20, 2030, 'diy-template', 'fa6-solid:brush', 'mall/promotion/diy/template/index', 'DiyTemplate', 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2295 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2436, '装修模板', '', 2, 1, 2435, 'diy-template', 'fa6-solid:brush', 'mall/promotion/diy/template/index', 'DiyTemplate', 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2296 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2437, '装修模板查询', 'promotion:diy-template:query', 3, 1, 2436, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2297 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2438, '装修模板创建', 'promotion:diy-template:create', 3, 2, 2436, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2298 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2439, '装修模板更新', 'promotion:diy-template:update', 3, 3, 2436, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2299 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2440, '装修模板删除', 'promotion:diy-template:delete', 3, 4, 2436, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2300 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2441, '装修模板使用', 'promotion:diy-template:use', 3, 5, 2436, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2301 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2442, '装修页面', '', 2, 2, 2435, 'diy-page', 'foundation:page-edit', 'mall/promotion/diy/page/index', 'DiyPage', 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2302 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2443, '装修页面查询', 'promotion:diy-page:query', 3, 1, 2442, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', b'0');
  2303 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2444, '装修页面创建', 'promotion:diy-page:create', 3, 2, 2442, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', b'0');
  2304 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2445, '装修页面更新', 'promotion:diy-page:update', 3, 3, 2442, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', b'0');
  2305 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2446, '装修页面删除', 'promotion:diy-page:delete', 3, 4, 2442, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', b'0');
  2306 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2447, '三方登录', '', 1, 10, 1, 'social', 'fa:500px', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:12:01', '1', '2023-11-04 13:06:45', b'0');
  2307 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2448, '三方应用', '', 2, 1, 2447, 'client', 'ep:set-up', 'views/system/social/client/index.vue', 'SocialClient', 0, b'1', b'1', b'1', '1', '2023-11-04 12:17:19', '1', '2023-11-04 12:17:19', b'0');
  2308 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2449, '三方应用查询', 'system:social-client:query', 3, 1, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:43:12', '1', '2023-11-04 12:43:33', b'0');
  2309 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2450, '三方应用创建', 'system:social-client:create', 3, 2, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:43:58', '1', '2023-11-04 12:43:58', b'0');
  2310 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2451, '三方应用更新', 'system:social-client:update', 3, 3, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:27', '1', '2023-11-04 12:44:27', b'0');
  2311 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2452, '三方应用删除', 'system:social-client:delete', 3, 4, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:43', '1', '2023-11-04 12:44:43', b'0');
  2312 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2453, '三方用户', 'system:social-user:query', 2, 2, 2447, 'user', 'ep:avatar', 'system/social/user/index.vue', 'SocialUser', 0, b'1', b'1', b'1', '1', '2023-11-04 14:01:05', '1', '2023-11-04 14:01:05', b'0');
2196 COMMIT; 2313 COMMIT;
2197 2314
2198 -- ---------------------------- 2315 -- ----------------------------
@@ -2283,7 +2400,7 @@ CREATE TABLE `system_notify_template` ( @@ -2283,7 +2400,7 @@ CREATE TABLE `system_notify_template` (
2283 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 2400 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
2284 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2401 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2285 PRIMARY KEY (`id`) USING BTREE 2402 PRIMARY KEY (`id`) USING BTREE
2286 -) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '站内信模板表'; 2403 +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '站内信模板表';
2287 2404
2288 -- ---------------------------- 2405 -- ----------------------------
2289 -- Records of system_notify_template 2406 -- Records of system_notify_template
@@ -2310,8 +2427,10 @@ CREATE TABLE `system_oauth2_access_token` ( @@ -2310,8 +2427,10 @@ CREATE TABLE `system_oauth2_access_token` (
2310 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 2427 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
2311 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2428 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2312 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 2429 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
2313 - PRIMARY KEY (`id`) USING BTREE  
2314 -) ENGINE = InnoDB AUTO_INCREMENT = 3063 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; 2430 + PRIMARY KEY (`id`) USING BTREE,
  2431 + INDEX `idx_access_token`(`access_token` ASC) USING BTREE,
  2432 + INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE
  2433 +) ENGINE = InnoDB AUTO_INCREMENT = 3152 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
2315 2434
2316 -- ---------------------------- 2435 -- ----------------------------
2317 -- Records of system_oauth2_access_token 2436 -- Records of system_oauth2_access_token
@@ -2433,7 +2552,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( @@ -2433,7 +2552,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
2433 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2552 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2434 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 2553 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
2435 PRIMARY KEY (`id`) USING BTREE 2554 PRIMARY KEY (`id`) USING BTREE
2436 -) ENGINE = InnoDB AUTO_INCREMENT = 1070 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; 2555 +) ENGINE = InnoDB AUTO_INCREMENT = 1099 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
2437 2556
2438 -- ---------------------------- 2557 -- ----------------------------
2439 -- Records of system_oauth2_refresh_token 2558 -- Records of system_oauth2_refresh_token
@@ -2473,7 +2592,7 @@ CREATE TABLE `system_operate_log` ( @@ -2473,7 +2592,7 @@ CREATE TABLE `system_operate_log` (
2473 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 2592 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
2474 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 2593 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
2475 PRIMARY KEY (`id`) USING BTREE 2594 PRIMARY KEY (`id`) USING BTREE
2476 -) ENGINE = InnoDB AUTO_INCREMENT = 8738 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; 2595 +) ENGINE = InnoDB AUTO_INCREMENT = 8845 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
2477 2596
2478 -- ---------------------------- 2597 -- ----------------------------
2479 -- Records of system_operate_log 2598 -- Records of system_operate_log
@@ -3481,7 +3600,7 @@ CREATE TABLE `system_sms_code` ( @@ -3481,7 +3600,7 @@ CREATE TABLE `system_sms_code` (
3481 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3600 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3482 PRIMARY KEY (`id`) USING BTREE, 3601 PRIMARY KEY (`id`) USING BTREE,
3483 INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号' 3602 INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
3484 -) ENGINE = InnoDB AUTO_INCREMENT = 531 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; 3603 +) ENGINE = InnoDB AUTO_INCREMENT = 535 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
3485 3604
3486 -- ---------------------------- 3605 -- ----------------------------
3487 -- Records of system_sms_code 3606 -- Records of system_sms_code
@@ -3524,7 +3643,7 @@ CREATE TABLE `system_sms_log` ( @@ -3524,7 +3643,7 @@ CREATE TABLE `system_sms_log` (
3524 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 3643 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
3525 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3644 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3526 PRIMARY KEY (`id`) USING BTREE 3645 PRIMARY KEY (`id`) USING BTREE
3527 -) ENGINE = InnoDB AUTO_INCREMENT = 445 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; 3646 +) ENGINE = InnoDB AUTO_INCREMENT = 503 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
3528 3647
3529 -- ---------------------------- 3648 -- ----------------------------
3530 -- Records of system_sms_log 3649 -- Records of system_sms_log
@@ -3585,6 +3704,7 @@ CREATE TABLE `system_social_client` ( @@ -3585,6 +3704,7 @@ CREATE TABLE `system_social_client` (
3585 `user_type` tinyint NOT NULL COMMENT '用户类型', 3704 `user_type` tinyint NOT NULL COMMENT '用户类型',
3586 `client_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户端编号', 3705 `client_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户端编号',
3587 `client_secret` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户端密钥', 3706 `client_secret` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户端密钥',
  3707 + `agent_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '代理编号',
3588 `status` tinyint NOT NULL COMMENT '状态', 3708 `status` tinyint NOT NULL COMMENT '状态',
3589 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', 3709 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
3590 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 3710 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@@ -3593,7 +3713,7 @@ CREATE TABLE `system_social_client` ( @@ -3593,7 +3713,7 @@ CREATE TABLE `system_social_client` (
3593 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3713 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3594 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3714 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3595 PRIMARY KEY (`id`) USING BTREE 3715 PRIMARY KEY (`id`) USING BTREE
3596 -) ENGINE = InnoDB AUTO_INCREMENT = 43 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交客户端表'; 3716 +) ENGINE = InnoDB AUTO_INCREMENT = 44 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交客户端表';
3597 3717
3598 -- ---------------------------- 3718 -- ----------------------------
3599 -- Records of system_social_client 3719 -- Records of system_social_client
@@ -3623,7 +3743,7 @@ CREATE TABLE `system_social_user` ( @@ -3623,7 +3743,7 @@ CREATE TABLE `system_social_user` (
3623 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3743 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3624 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3744 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3625 PRIMARY KEY (`id`) USING BTREE 3745 PRIMARY KEY (`id`) USING BTREE
3626 -) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; 3746 +) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
3627 3747
3628 -- ---------------------------- 3748 -- ----------------------------
3629 -- Records of system_social_user 3749 -- Records of system_social_user
@@ -3648,7 +3768,7 @@ CREATE TABLE `system_social_user_bind` ( @@ -3648,7 +3768,7 @@ CREATE TABLE `system_social_user_bind` (
3648 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 3768 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3649 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 3769 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3650 PRIMARY KEY (`id`) USING BTREE 3770 PRIMARY KEY (`id`) USING BTREE
3651 -) ENGINE = InnoDB AUTO_INCREMENT = 79 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; 3771 +) ENGINE = InnoDB AUTO_INCREMENT = 80 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
3652 3772
3653 -- ---------------------------- 3773 -- ----------------------------
3654 -- Records of system_social_user_bind 3774 -- Records of system_social_user_bind
@@ -3824,7 +3944,7 @@ CREATE TABLE `system_users` ( @@ -3824,7 +3944,7 @@ CREATE TABLE `system_users` (
3824 -- Records of system_users 3944 -- Records of system_users
3825 -- ---------------------------- 3945 -- ----------------------------
3826 BEGIN; 3946 BEGIN;
3827 -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-10-18 22:31:35', 'admin', '2021-01-05 17:03:47', NULL, '2023-10-18 22:31:35', b'0', 1); 3947 +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://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2023-11-04 10:33:16', 'admin', '2021-01-05 17:03:47', NULL, '2023-11-04 10:33:16', b'0', 1);
3828 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); 3948 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);
3829 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); 3949 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);
3830 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); 3950 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);
yudao-dependencies/pom.xml
@@ -14,28 +14,30 @@ @@ -14,28 +14,30 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.8.2-snapshot</revision> 17 + <revision>1.8.3-snapshot</revision>
18 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> 18 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
19 <!-- 统一依赖管理 --> 19 <!-- 统一依赖管理 -->
20 - <spring.boot.version>2.7.16</spring.boot.version> 20 + <spring.boot.version>2.7.17</spring.boot.version>
21 <!-- Web 相关 --> 21 <!-- Web 相关 -->
22 <springdoc.version>1.6.15</springdoc.version> 22 <springdoc.version>1.6.15</springdoc.version>
23 <knife4j.version>4.3.0</knife4j.version> 23 <knife4j.version>4.3.0</knife4j.version>
24 <servlet.versoin>2.5</servlet.versoin> 24 <servlet.versoin>2.5</servlet.versoin>
25 <!-- DB 相关 --> 25 <!-- DB 相关 -->
26 - <druid.version>1.2.19</druid.version>  
27 - <mybatis-plus.version>3.5.3.2</mybatis-plus.version>  
28 - <mybatis-plus-generator.version>3.5.3.2</mybatis-plus-generator.version> 26 + <druid.version>1.2.20</druid.version>
  27 + <mybatis-plus.version>3.5.4</mybatis-plus.version>
  28 + <mybatis-plus-generator.version>3.5.4</mybatis-plus-generator.version>
29 <dynamic-datasource.version>3.6.1</dynamic-datasource.version> 29 <dynamic-datasource.version>3.6.1</dynamic-datasource.version>
30 - <mybatis-plus-join.version>1.4.6</mybatis-plus-join.version> 30 + <mybatis-plus-join.version>1.4.7</mybatis-plus-join.version>
31 <redisson.version>3.18.0</redisson.version> 31 <redisson.version>3.18.0</redisson.version>
32 - <dm8.jdbc.version>8.1.2.141</dm8.jdbc.version> 32 + <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version>
  33 + <!-- 消息队列 -->
  34 + <rocketmq-spring.version>2.2.3</rocketmq-spring.version>
33 <!-- 服务保障相关 --> 35 <!-- 服务保障相关 -->
34 - <lock4j.version>2.2.3</lock4j.version> 36 + <lock4j.version>2.2.5</lock4j.version>
35 <resilience4j.version>1.7.1</resilience4j.version> 37 <resilience4j.version>1.7.1</resilience4j.version>
36 <!-- 监控相关 --> 38 <!-- 监控相关 -->
37 <skywalking.version>8.12.0</skywalking.version> 39 <skywalking.version>8.12.0</skywalking.version>
38 - <spring-boot-admin.version>2.7.10</spring-boot-admin.version> 40 + <spring-boot-admin.version>2.7.11</spring-boot-admin.version>
39 <opentracing.version>0.33.0</opentracing.version> 41 <opentracing.version>0.33.0</opentracing.version>
40 <!-- Test 测试相关 --> 42 <!-- Test 测试相关 -->
41 <podam.version>7.2.11.RELEASE</podam.version> 43 <podam.version>7.2.11.RELEASE</podam.version>
@@ -44,8 +46,8 @@ @@ -44,8 +46,8 @@
44 <!-- Bpm 工作流相关 --> 46 <!-- Bpm 工作流相关 -->
45 <flowable.version>6.8.0</flowable.version> 47 <flowable.version>6.8.0</flowable.version>
46 <!-- 工具类相关 --> 48 <!-- 工具类相关 -->
47 - <captcha-plus.version>1.0.8</captcha-plus.version>  
48 - <jsoup.version>1.16.1</jsoup.version> 49 + <captcha-plus.version>1.0.10</captcha-plus.version>
  50 + <jsoup.version>1.16.2</jsoup.version>
49 <lombok.version>1.18.30</lombok.version> 51 <lombok.version>1.18.30</lombok.version>
50 <mapstruct.version>1.5.5.Final</mapstruct.version> 52 <mapstruct.version>1.5.5.Final</mapstruct.version>
51 <hutool.version>5.8.22</hutool.version> 53 <hutool.version>5.8.22</hutool.version>
@@ -53,10 +55,10 @@ @@ -53,10 +55,10 @@
53 <velocity.version>2.3</velocity.version> 55 <velocity.version>2.3</velocity.version>
54 <screw.version>1.0.5</screw.version> 56 <screw.version>1.0.5</screw.version>
55 <fastjson.version>1.2.83</fastjson.version> 57 <fastjson.version>1.2.83</fastjson.version>
56 - <guava.version>32.1.2-jre</guava.version> 58 + <guava.version>32.1.3-jre</guava.version>
57 <guice.version>5.1.0</guice.version> 59 <guice.version>5.1.0</guice.version>
58 <transmittable-thread-local.version>2.14.2</transmittable-thread-local.version> 60 <transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
59 - <commons-net.version>3.9.0</commons-net.version> 61 + <commons-net.version>3.10.0</commons-net.version>
60 <jsch.version>0.1.55</jsch.version> 62 <jsch.version>0.1.55</jsch.version>
61 <tika-core.version>2.7.0</tika-core.version> 63 <tika-core.version>2.7.0</tika-core.version>
62 <ip2region.version>2.7.0</ip2region.version> 64 <ip2region.version>2.7.0</ip2region.version>
@@ -67,8 +69,8 @@ @@ -67,8 +69,8 @@
67 <minio.version>8.5.6</minio.version> 69 <minio.version>8.5.6</minio.version>
68 <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version> 70 <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version>
69 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version> 71 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
70 - <tencentcloud-sdk-java.version>3.1.853</tencentcloud-sdk-java.version>  
71 - <justauth.version>1.0.5</justauth.version> 72 + <tencentcloud-sdk-java.version>3.1.880</tencentcloud-sdk-java.version>
  73 + <justauth.version>1.0.7</justauth.version>
72 <jimureport.version>1.6.1</jimureport.version> 74 <jimureport.version>1.6.1</jimureport.version>
73 <xercesImpl.version>2.12.2</xercesImpl.version> 75 <xercesImpl.version>2.12.2</xercesImpl.version>
74 <weixin-java.version>4.5.0</weixin-java.version> 76 <weixin-java.version>4.5.0</weixin-java.version>
@@ -98,11 +100,6 @@ @@ -98,11 +100,6 @@
98 </dependency> 100 </dependency>
99 <dependency> 101 <dependency>
100 <groupId>cn.iocoder.boot</groupId> 102 <groupId>cn.iocoder.boot</groupId>
101 - <artifactId>yudao-spring-boot-starter-biz-trade</artifactId>  
102 - <version>${revision}</version>  
103 - </dependency>  
104 - <dependency>  
105 - <groupId>cn.iocoder.boot</groupId>  
106 <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> 103 <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
107 <version>${revision}</version> 104 <version>${revision}</version>
108 </dependency> 105 </dependency>
@@ -260,6 +257,12 @@ @@ -260,6 +257,12 @@
260 <version>${revision}</version> 257 <version>${revision}</version>
261 </dependency> 258 </dependency>
262 259
  260 + <dependency>
  261 + <groupId>org.apache.rocketmq</groupId>
  262 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  263 + <version>${rocketmq-spring.version}</version>
  264 + </dependency>
  265 +
263 <!-- 服务保障相关 --> 266 <!-- 服务保障相关 -->
264 <dependency> 267 <dependency>
265 <groupId>cn.iocoder.boot</groupId> 268 <groupId>cn.iocoder.boot</groupId>
yudao-example/yudao-sso-demo-by-code/pom.xml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <maven.compiler.target>8</maven.compiler.target> 21 <maven.compiler.target>8</maven.compiler.target>
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <!-- 统一依赖管理 --> 23 <!-- 统一依赖管理 -->
24 - <spring.boot.version>2.7.16</spring.boot.version> 24 + <spring.boot.version>2.7.17</spring.boot.version>
25 </properties> 25 </properties>
26 26
27 <dependencyManagement> 27 <dependencyManagement>
yudao-example/yudao-sso-demo-by-password/pom.xml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <maven.compiler.target>8</maven.compiler.target> 21 <maven.compiler.target>8</maven.compiler.target>
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <!-- 统一依赖管理 --> 23 <!-- 统一依赖管理 -->
24 - <spring.boot.version>2.7.16</spring.boot.version> 24 + <spring.boot.version>2.7.17</spring.boot.version>
25 </properties> 25 </properties>
26 26
27 <dependencyManagement> 27 <dependencyManagement>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/core/KeyValue.java
@@ -4,6 +4,8 @@ import lombok.AllArgsConstructor; @@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
4 import lombok.Data; 4 import lombok.Data;
5 import lombok.NoArgsConstructor; 5 import lombok.NoArgsConstructor;
6 6
  7 +import java.io.Serializable;
  8 +
7 /** 9 /**
8 * Key Value 的键值对 10 * Key Value 的键值对
9 * 11 *
@@ -12,7 +14,7 @@ import lombok.NoArgsConstructor; @@ -12,7 +14,7 @@ import lombok.NoArgsConstructor;
12 @Data 14 @Data
13 @NoArgsConstructor 15 @NoArgsConstructor
14 @AllArgsConstructor 16 @AllArgsConstructor
15 -public class KeyValue<K, V> { 17 +public class KeyValue<K, V> implements Serializable {
16 18
17 private K key; 19 private K key;
18 private V value; 20 private V value;
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap; @@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap;
8 import java.util.*; 8 import java.util.*;
9 import java.util.function.*; 9 import java.util.function.*;
10 import java.util.stream.Collectors; 10 import java.util.stream.Collectors;
  11 +import java.util.stream.Stream;
11 12
12 import static java.util.Arrays.asList; 13 import static java.util.Arrays.asList;
13 14
@@ -223,10 +224,14 @@ public class CollectionUtils { @@ -223,10 +224,14 @@ public class CollectionUtils {
223 } 224 }
224 225
225 public static <T> T findFirst(List<T> from, Predicate<T> predicate) { 226 public static <T> T findFirst(List<T> from, Predicate<T> predicate) {
  227 + return findFirst(from, predicate, Function.identity());
  228 + }
  229 +
  230 + public static <T, U> U findFirst(List<T> from, Predicate<T> predicate, Function<T, U> func) {
226 if (CollUtil.isEmpty(from)) { 231 if (CollUtil.isEmpty(from)) {
227 return null; 232 return null;
228 } 233 }
229 - return from.stream().filter(predicate).findFirst().orElse(null); 234 + return from.stream().filter(predicate).findFirst().map(func).orElse(null);
230 } 235 }
231 236
232 public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> from, Function<T, V> valueFunc) { 237 public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> from, Function<T, V> valueFunc) {
@@ -267,4 +272,20 @@ public class CollectionUtils { @@ -267,4 +272,20 @@ public class CollectionUtils {
267 return deptId == null ? Collections.emptyList() : Collections.singleton(deptId); 272 return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
268 } 273 }
269 274
  275 + public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
  276 + Function<T, ? extends Stream<? extends U>> func) {
  277 + if (CollUtil.isEmpty(from)) {
  278 + return new ArrayList<>();
  279 + }
  280 + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
  281 + }
  282 +
  283 + public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
  284 + Function<T, ? extends Stream<? extends U>> func) {
  285 + if (CollUtil.isEmpty(from)) {
  286 + return new HashSet<>();
  287 + }
  288 + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
  289 + }
  290 +
270 } 291 }
yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeConfiguration.java renamed to yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java
@@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
21 @ConditionalOnProperty(prefix = "yudao.error-code", value = "enable", matchIfMissing = true) // 允许使用 yudao.error-code.enable=false 禁用访问日志 21 @ConditionalOnProperty(prefix = "yudao.error-code", value = "enable", matchIfMissing = true) // 允许使用 yudao.error-code.enable=false 禁用访问日志
22 @EnableConfigurationProperties(ErrorCodeProperties.class) 22 @EnableConfigurationProperties(ErrorCodeProperties.class)
23 @EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 23 @EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码
24 -public class YudaoErrorCodeConfiguration { 24 +public class YudaoErrorCodeAutoConfiguration {
25 25
26 @Bean 26 @Bean
27 public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName, 27 public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName,
yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 -cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeConfiguration  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeAutoConfiguration
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
6 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; 6 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
7 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
8 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
  9 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
9 10
10 import java.util.Map; 11 import java.util.Map;
11 12
@@ -86,4 +87,12 @@ public interface PayClient { @@ -86,4 +87,12 @@ public interface PayClient {
86 */ 87 */
87 PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO); 88 PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO);
88 89
  90 + /**
  91 + * 获得转账订单信息
  92 + *
  93 + * @param outTradeNo 外部订单号
  94 + * @param type 转账类型
  95 + * @return 转账信息
  96 + */
  97 + PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type);
89 } 98 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferRespDTO.java
@@ -53,11 +53,24 @@ public class PayTransferRespDTO { @@ -53,11 +53,24 @@ public class PayTransferRespDTO {
53 /** 53 /**
54 * 创建【WAITING】状态的转账返回 54 * 创建【WAITING】状态的转账返回
55 */ 55 */
56 - public static PayTransferRespDTO waitingOf(String channelOrderNo, 56 + public static PayTransferRespDTO waitingOf(String channelTransferNo,
57 String outTransferNo, Object rawData) { 57 String outTransferNo, Object rawData) {
58 PayTransferRespDTO respDTO = new PayTransferRespDTO(); 58 PayTransferRespDTO respDTO = new PayTransferRespDTO();
59 respDTO.status = PayTransferStatusRespEnum.WAITING.getStatus(); 59 respDTO.status = PayTransferStatusRespEnum.WAITING.getStatus();
60 - respDTO.channelTransferNo = channelOrderNo; 60 + respDTO.channelTransferNo = channelTransferNo;
  61 + respDTO.outTransferNo = outTransferNo;
  62 + respDTO.rawData = rawData;
  63 + return respDTO;
  64 + }
  65 +
  66 + /**
  67 + * 创建【IN_PROGRESS】状态的转账返回
  68 + */
  69 + public static PayTransferRespDTO dealingOf(String channelTransferNo,
  70 + String outTransferNo, Object rawData) {
  71 + PayTransferRespDTO respDTO = new PayTransferRespDTO();
  72 + respDTO.status = PayTransferStatusRespEnum.IN_PROGRESS.getStatus();
  73 + respDTO.channelTransferNo = channelTransferNo;
61 respDTO.outTransferNo = outTransferNo; 74 respDTO.outTransferNo = outTransferNo;
62 respDTO.rawData = rawData; 75 respDTO.rawData = rawData;
63 return respDTO; 76 return respDTO;
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
@@ -188,11 +188,11 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -188,11 +188,11 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
188 188
189 @Override 189 @Override
190 public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { 190 public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  191 + validatePayTransferReqDTO(reqDTO);
191 PayTransferRespDTO resp; 192 PayTransferRespDTO resp;
192 - try{  
193 - validatePayTransferReqDTO(reqDTO); 193 + try {
194 resp = doUnifiedTransfer(reqDTO); 194 resp = doUnifiedTransfer(reqDTO);
195 - }catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可 195 + } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
196 throw ex; 196 throw ex;
197 } catch (Throwable ex) { 197 } catch (Throwable ex) {
198 // 系统异常,则包装成 PayException 异常抛出 198 // 系统异常,则包装成 PayException 异常抛出
@@ -219,9 +219,25 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -219,9 +219,25 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
219 } 219 }
220 } 220 }
221 221
  222 + @Override
  223 + public final PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type) {
  224 + try {
  225 + return doGetTransfer(outTradeNo, type);
  226 + } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
  227 + throw ex;
  228 + } catch (Throwable ex) {
  229 + log.error("[getTransfer][客户端({}) outTradeNo({}) type({}) 查询转账单异常]",
  230 + getId(), outTradeNo, type, ex);
  231 + throw buildPayException(ex);
  232 + }
  233 + }
  234 +
222 protected abstract PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) 235 protected abstract PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO)
223 throws Throwable; 236 throws Throwable;
224 237
  238 + protected abstract PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type)
  239 + throws Throwable;
  240 +
225 // ========== 各种工具方法 ========== 241 // ========== 各种工具方法 ==========
226 242
227 private PayException buildPayException(Throwable ex) { 243 private PayException buildPayException(Throwable ex) {
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
@@ -23,14 +23,8 @@ import com.alipay.api.AlipayResponse; @@ -23,14 +23,8 @@ import com.alipay.api.AlipayResponse;
23 import com.alipay.api.DefaultAlipayClient; 23 import com.alipay.api.DefaultAlipayClient;
24 import com.alipay.api.domain.*; 24 import com.alipay.api.domain.*;
25 import com.alipay.api.internal.util.AlipaySignature; 25 import com.alipay.api.internal.util.AlipaySignature;
26 -import com.alipay.api.request.AlipayFundTransUniTransferRequest;  
27 -import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;  
28 -import com.alipay.api.request.AlipayTradeQueryRequest;  
29 -import com.alipay.api.request.AlipayTradeRefundRequest;  
30 -import com.alipay.api.response.AlipayFundTransUniTransferResponse;  
31 -import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;  
32 -import com.alipay.api.response.AlipayTradeQueryResponse;  
33 -import com.alipay.api.response.AlipayTradeRefundResponse; 26 +import com.alipay.api.request.*;
  27 +import com.alipay.api.response.*;
34 import lombok.Getter; 28 import lombok.Getter;
35 import lombok.SneakyThrows; 29 import lombok.SneakyThrows;
36 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
@@ -126,7 +120,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -126,7 +120,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
126 } 120 }
127 // 2.2 解析订单的状态 121 // 2.2 解析订单的状态
128 Integer status = parseStatus(response.getTradeStatus()); 122 Integer status = parseStatus(response.getTradeStatus());
129 - Assert.notNull(status, () -> { 123 + Assert.notNull(status, () -> {
130 throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody())); 124 throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody()));
131 }); 125 });
132 return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()), 126 return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()),
@@ -228,7 +222,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -228,7 +222,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
228 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException { 222 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
229 // 1.1 校验公钥类型 必须使用公钥证书模式 223 // 1.1 校验公钥类型 必须使用公钥证书模式
230 if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) { 224 if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
231 - throw exception0(ERROR_CONFIGURATION.getCode(),"支付宝单笔转账必须使用公钥证书模式"); 225 + throw exception0(ERROR_CONFIGURATION.getCode(), "支付宝单笔转账必须使用公钥证书模式");
232 } 226 }
233 // 1.2 构建 AlipayFundTransUniTransferModel 227 // 1.2 构建 AlipayFundTransUniTransferModel
234 AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel(); 228 AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
@@ -238,44 +232,96 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -238,44 +232,96 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
238 model.setOutBizNo(reqDTO.getOutTransferNo()); 232 model.setOutBizNo(reqDTO.getOutTransferNo());
239 model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD 233 model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
240 model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER 234 model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER
241 - model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras())); 235 + if (reqDTO.getChannelExtras() != null) {
  236 + model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
  237 + }
  238 + // ② 个性化的参数
  239 + Participant payeeInfo = new Participant();
242 PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(reqDTO.getType()); 240 PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(reqDTO.getType());
243 switch (transferType) { 241 switch (transferType) {
244 // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦? 242 // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦?
245 // @芋艿。 是不是还要考虑转账到银行卡。所以传 transferType 但是转账到银行卡不知道要如何测试?? 243 // @芋艿。 是不是还要考虑转账到银行卡。所以传 transferType 但是转账到银行卡不知道要如何测试??
246 case ALIPAY_BALANCE: { 244 case ALIPAY_BALANCE: {
247 - // ② 个性化的参数  
248 - Participant payeeInfo = new Participant();  
249 payeeInfo.setIdentityType("ALIPAY_LOGON_ID"); 245 payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
250 payeeInfo.setIdentity(reqDTO.getAlipayLogonId()); // 支付宝登录号 246 payeeInfo.setIdentity(reqDTO.getAlipayLogonId()); // 支付宝登录号
251 payeeInfo.setName(reqDTO.getUserName()); // 支付宝账号姓名 247 payeeInfo.setName(reqDTO.getUserName()); // 支付宝账号姓名
252 model.setPayeeInfo(payeeInfo); 248 model.setPayeeInfo(payeeInfo);
253 - // 1.3 构建 AlipayFundTransUniTransferRequest  
254 - AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();  
255 - request.setBizModel(model);  
256 - // 执行请求  
257 - AlipayFundTransUniTransferResponse response = client.certificateExecute(request);  
258 - // 处理结果  
259 - if (!response.isSuccess()) {  
260 - // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询  
261 - if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {  
262 - return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);  
263 - }  
264 - return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),  
265 - reqDTO.getOutTransferNo(), response);  
266 - }  
267 - return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),  
268 - response.getOutBizNo(), response); 249 + break;
269 } 250 }
270 case BANK_CARD: { 251 case BANK_CARD: {
271 - Participant payeeInfo = new Participant();  
272 payeeInfo.setIdentityType("BANKCARD_ACCOUNT"); 252 payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
273 // TODO 待实现 253 // TODO 待实现
274 throw exception(NOT_IMPLEMENTED); 254 throw exception(NOT_IMPLEMENTED);
275 } 255 }
276 default: { 256 default: {
277 - throw exception0(BAD_REQUEST.getCode(),"不正确的转账类型: {}",transferType); 257 + throw exception0(BAD_REQUEST.getCode(), "不正确的转账类型: {}", transferType);
  258 + }
  259 + }
  260 + // 1.3 构建 AlipayFundTransUniTransferRequest
  261 + AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
  262 + request.setBizModel(model);
  263 + // 执行请求
  264 + AlipayFundTransUniTransferResponse response = client.certificateExecute(request);
  265 + // 处理结果
  266 + if (!response.isSuccess()) {
  267 + // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询,或相同 outBizNo 重新发起转账
  268 + // 发现 outBizNo 相同 两次请求参数相同. 会返回 "PAYMENT_INFO_INCONSISTENCY", 不知道哪里的问题. 暂时返回 WAIT. 后续job 会轮询
  269 + if (ObjectUtils.equalsAny(response.getSubCode(),"PAYMENT_INFO_INCONSISTENCY", "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
  270 + return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
  271 + }
  272 + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
  273 + reqDTO.getOutTransferNo(), response);
  274 + } else {
  275 + if (ObjectUtils.equalsAny(response.getStatus(), "REFUND", "FAIL")) { // 转账到银行卡会出现 "REFUND" "FAIL"
  276 + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
  277 + reqDTO.getOutTransferNo(), response);
  278 + }
  279 + if (Objects.equals(response.getStatus(), "DEALING")) { // 转账到银行卡会出现 "DEALING" 处理中
  280 + return PayTransferRespDTO.dealingOf(response.getOrderId(), reqDTO.getOutTransferNo(), response);
  281 + }
  282 + return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
  283 + response.getOutBizNo(), response);
  284 + }
  285 +
  286 + }
  287 +
  288 + @Override
  289 + protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) throws Throwable {
  290 + // 1.1 构建 AlipayFundTransCommonQueryModel
  291 + AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
  292 + model.setProductCode(type == PayTransferTypeEnum.BANK_CARD ? "TRANS_BANKCARD_NO_PWD" : "TRANS_ACCOUNT_NO_PWD");
  293 + model.setBizScene("DIRECT_TRANSFER"); //业务场景
  294 + model.setOutBizNo(outTradeNo);
  295 + // 1.2 构建 AlipayFundTransCommonQueryRequest
  296 + AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
  297 + request.setBizModel(model);
  298 +
  299 + // 2.1 执行请求
  300 + AlipayFundTransCommonQueryResponse response;
  301 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) { // 证书模式
  302 + response = client.certificateExecute(request);
  303 + } else {
  304 + response = client.execute(request);
  305 + }
  306 + // 2.2 处理返回结果
  307 + if (response.isSuccess()) {
  308 + if (ObjectUtils.equalsAny(response.getStatus(), "REFUND", "FAIL")) { // 转账到银行卡会出现 "REFUND" "FAIL"
  309 + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
  310 + outTradeNo, response);
  311 + }
  312 + if (Objects.equals(response.getStatus(), "DEALING")) { // 转账到银行卡会出现 "DEALING" 处理中
  313 + return PayTransferRespDTO.dealingOf(response.getOrderId(), outTradeNo, response);
278 } 314 }
  315 + return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getPayDate()),
  316 + response.getOutBizNo(), response);
  317 + } else {
  318 + // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询, 或相同 outBizNo 重新发起转账
  319 + // 当出现 ORDER_NOT_EXIST 可能是转账还在处理中,也可能是转账处理失败. 返回 WAIT 状态. 后续 job 会轮询, 或相同 outBizNo 重新发起转账
  320 + if (ObjectUtils.equalsAny(response.getSubCode(), "ORDER_NOT_EXIST", "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
  321 + return PayTransferRespDTO.waitingOf(null, outTradeNo, response);
  322 + }
  323 + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
  324 + outTradeNo, response);
279 } 325 }
280 } 326 }
281 327
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifie @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifie
9 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; 9 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
10 import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; 10 import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
11 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 11 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
  12 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
12 13
13 import java.time.LocalDateTime; 14 import java.time.LocalDateTime;
14 import java.util.Map; 15 import java.util.Map;
@@ -71,4 +72,9 @@ public class MockPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; { @@ -71,4 +72,9 @@ public class MockPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
71 throw new UnsupportedOperationException("待实现"); 72 throw new UnsupportedOperationException("待实现");
72 } 73 }
73 74
  75 + @Override
  76 + protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) {
  77 + throw new UnsupportedOperationException("待实现");
  78 + }
  79 +
74 } 80 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
@@ -16,6 +16,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDT @@ -16,6 +16,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDT
16 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; 16 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
17 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; 17 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
18 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; 18 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
  19 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
19 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; 20 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
20 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; 21 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
21 import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; 22 import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
@@ -431,6 +432,12 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC @@ -431,6 +432,12 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
431 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { 432 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
432 throw new UnsupportedOperationException("待实现"); 433 throw new UnsupportedOperationException("待实现");
433 } 434 }
  435 +
  436 + @Override
  437 + protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) {
  438 + throw new UnsupportedOperationException("待实现");
  439 + }
  440 +
434 // ========== 各种工具方法 ========== 441 // ========== 各种工具方法 ==========
435 442
436 static String formatDateV2(LocalDateTime time) { 443 static String formatDateV2(LocalDateTime time) {
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferStatusRespEnum.java
@@ -38,4 +38,8 @@ public enum PayTransferStatusRespEnum { @@ -38,4 +38,8 @@ public enum PayTransferStatusRespEnum {
38 public static boolean isClosed(Integer status) { 38 public static boolean isClosed(Integer status) {
39 return Objects.equals(status, CLOSED.getStatus()); 39 return Objects.equals(status, CLOSED.getStatus());
40 } 40 }
  41 +
  42 + public static boolean isInProgress(Integer status) {
  43 + return Objects.equals(status, IN_PROGRESS.getStatus());
  44 + }
41 } 45 }
yudao-framework/yudao-spring-boot-starter-biz-tenant/pom.xml
@@ -48,6 +48,22 @@ @@ -48,6 +48,22 @@
48 <dependency> 48 <dependency>
49 <groupId>cn.iocoder.boot</groupId> 49 <groupId>cn.iocoder.boot</groupId>
50 <artifactId>yudao-spring-boot-starter-mq</artifactId> 50 <artifactId>yudao-spring-boot-starter-mq</artifactId>
  51 + <optional>true</optional>
  52 + </dependency>
  53 + <dependency>
  54 + <groupId>org.springframework.kafka</groupId>
  55 + <artifactId>spring-kafka</artifactId>
  56 + <optional>true</optional>
  57 + </dependency>
  58 + <dependency>
  59 + <groupId>org.springframework.amqp</groupId>
  60 + <artifactId>spring-rabbit</artifactId>
  61 + <optional>true</optional>
  62 + </dependency>
  63 + <dependency>
  64 + <groupId>org.apache.rocketmq</groupId>
  65 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  66 + <optional>true</optional>
51 </dependency> 67 </dependency>
52 68
53 <!-- Test 测试相关 --> 69 <!-- Test 测试相关 -->
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
@@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties; @@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect; 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
7 import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; 7 import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
8 import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect; 8 import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
9 -import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor; 9 +import cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
  10 +import cn.iocoder.yudao.framework.tenant.core.mq.redis.TenantRedisMessageInterceptor;
  11 +import cn.iocoder.yudao.framework.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
10 import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager; 12 import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager;
11 import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; 13 import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
12 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; 14 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
@@ -18,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.tenant.TenantApi; @@ -18,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
18 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 20 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
19 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; 21 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
20 import org.springframework.boot.autoconfigure.AutoConfiguration; 22 import org.springframework.boot.autoconfigure.AutoConfiguration;
  23 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
21 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 24 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
22 import org.springframework.boot.context.properties.EnableConfigurationProperties; 25 import org.springframework.boot.context.properties.EnableConfigurationProperties;
23 import org.springframework.boot.web.servlet.FilterRegistrationBean; 26 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -92,6 +95,18 @@ public class YudaoTenantAutoConfiguration { @@ -92,6 +95,18 @@ public class YudaoTenantAutoConfiguration {
92 return new TenantRedisMessageInterceptor(); 95 return new TenantRedisMessageInterceptor();
93 } 96 }
94 97
  98 + @Bean
  99 + @ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
  100 + public TenantRabbitMQInitializer tenantRabbitMQInitializer() {
  101 + return new TenantRabbitMQInitializer();
  102 + }
  103 +
  104 + @Bean
  105 + @ConditionalOnClass(name = "org.apache.rocketmq.spring.core.RocketMQTemplate")
  106 + public TenantRocketMQInitializer tenantRocketMQInitializer() {
  107 + return new TenantRocketMQInitializer();
  108 + }
  109 +
95 // ========== Job ========== 110 // ========== Job ==========
96 111
97 @Bean 112 @Bean
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.kafka;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.boot.SpringApplication;
  6 +import org.springframework.boot.env.EnvironmentPostProcessor;
  7 +import org.springframework.core.env.ConfigurableEnvironment;
  8 +
  9 +/**
  10 + * 多租户的 Kafka 的 {@link EnvironmentPostProcessor} 实现类
  11 + *
  12 + * Kafka Producer 发送消息时,增加 {@link TenantKafkaProducerInterceptor} 拦截器
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Slf4j
  17 +public class TenantKafkaEnvironmentPostProcessor implements EnvironmentPostProcessor {
  18 +
  19 + private static final String PROPERTY_KEY_INTERCEPTOR_CLASSES = "spring.kafka.producer.properties.interceptor.classes";
  20 +
  21 + @Override
  22 + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
  23 + // 添加 TenantKafkaProducerInterceptor 拦截器
  24 + try {
  25 + String value = environment.getProperty(PROPERTY_KEY_INTERCEPTOR_CLASSES);
  26 + if (StrUtil.isEmpty(value)) {
  27 + value = TenantKafkaProducerInterceptor.class.getName();
  28 + } else {
  29 + value += "," + TenantKafkaProducerInterceptor.class.getName();
  30 + }
  31 + environment.getSystemProperties().put(PROPERTY_KEY_INTERCEPTOR_CLASSES, value);
  32 + } catch (NoClassDefFoundError ignore) {
  33 + // 如果触发 NoClassDefFoundError 异常,说明 TenantKafkaProducerInterceptor 类不存在,即没引入 kafka-spring 依赖
  34 + }
  35 + }
  36 +
  37 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.kafka;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  5 +import org.apache.kafka.clients.producer.ProducerInterceptor;
  6 +import org.apache.kafka.clients.producer.ProducerRecord;
  7 +import org.apache.kafka.clients.producer.RecordMetadata;
  8 +import org.apache.kafka.common.header.Headers;
  9 +import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
  10 +
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  14 +
  15 +/**
  16 + * Kafka 消息队列的多租户 {@link ProducerInterceptor} 实现类
  17 + *
  18 + * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
  19 + * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +public class TenantKafkaProducerInterceptor implements ProducerInterceptor<Object, Object> {
  24 +
  25 + @Override
  26 + public ProducerRecord<Object, Object> onSend(ProducerRecord<Object, Object> record) {
  27 + Long tenantId = TenantContextHolder.getTenantId();
  28 + if (tenantId != null) {
  29 + Headers headers = (Headers) ReflectUtil.getFieldValue(record, "headers"); // private 属性,没有 get 方法,智能反射
  30 + headers.add(HEADER_TENANT_ID, tenantId.toString().getBytes());
  31 + }
  32 + return record;
  33 + }
  34 +
  35 + @Override
  36 + public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
  37 + }
  38 +
  39 + @Override
  40 + public void close() {
  41 + }
  42 +
  43 + @Override
  44 + public void configure(Map<String, ?> configs) {
  45 + }
  46 +
  47 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rabbitmq/TenantRabbitMQInitializer.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq;
  2 +
  3 +import org.springframework.amqp.rabbit.core.RabbitTemplate;
  4 +import org.springframework.beans.BeansException;
  5 +import org.springframework.beans.factory.config.BeanPostProcessor;
  6 +
  7 +/**
  8 + * 多租户的 RabbitMQ 初始化器
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +public class TenantRabbitMQInitializer implements BeanPostProcessor {
  13 +
  14 + @Override
  15 + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  16 + if (bean instanceof RabbitTemplate) {
  17 + RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
  18 + rabbitTemplate.addBeforePublishPostProcessors(new TenantRabbitMQMessagePostProcessor());
  19 + }
  20 + return bean;
  21 + }
  22 +
  23 +}
0 \ No newline at end of file 24 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rabbitmq/TenantRabbitMQMessagePostProcessor.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq;
  2 +
  3 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  4 +import org.apache.kafka.clients.producer.ProducerInterceptor;
  5 +import org.springframework.amqp.AmqpException;
  6 +import org.springframework.amqp.core.Message;
  7 +import org.springframework.amqp.core.MessagePostProcessor;
  8 +import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
  9 +
  10 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  11 +
  12 +/**
  13 + * RabbitMQ 消息队列的多租户 {@link ProducerInterceptor} 实现类
  14 + *
  15 + * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
  16 + * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +public class TenantRabbitMQMessagePostProcessor implements MessagePostProcessor {
  21 +
  22 + @Override
  23 + public Message postProcessMessage(Message message) throws AmqpException {
  24 + Long tenantId = TenantContextHolder.getTenantId();
  25 + if (tenantId != null) {
  26 + message.getMessageProperties().getHeaders().put(HEADER_TENANT_ID, tenantId);
  27 + }
  28 + return message;
  29 + }
  30 +
  31 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/TenantRedisMessageInterceptor.java renamed to yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/redis/TenantRedisMessageInterceptor.java
1 -package cn.iocoder.yudao.framework.tenant.core.mq; 1 +package cn.iocoder.yudao.framework.tenant.core.mq.redis;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
5 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 4 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  5 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
6 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; 6 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
7 7
8 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; 8 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rocketmq/TenantRocketMQConsumeMessageHook.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rocketmq;
  2 +
  3 +import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  6 +import org.apache.rocketmq.client.hook.ConsumeMessageContext;
  7 +import org.apache.rocketmq.client.hook.ConsumeMessageHook;
  8 +import org.apache.rocketmq.common.message.MessageExt;
  9 +import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
  10 +
  11 +import java.util.List;
  12 +
  13 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  14 +
  15 +/**
  16 + * RocketMQ 消息队列的多租户 {@link ConsumeMessageHook} 实现类
  17 + *
  18 + * Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +public class TenantRocketMQConsumeMessageHook implements ConsumeMessageHook {
  23 +
  24 + @Override
  25 + public String hookName() {
  26 + return getClass().getSimpleName();
  27 + }
  28 +
  29 + @Override
  30 + public void consumeMessageBefore(ConsumeMessageContext context) {
  31 + // 校验,消息必须是单条,不然设置租户可能不正确
  32 + List<MessageExt> messages = context.getMsgList();
  33 + Assert.isTrue(messages.size() == 1, "消息条数({})不正确", messages.size());
  34 + // 设置租户编号
  35 + String tenantId = messages.get(0).getUserProperty(HEADER_TENANT_ID);
  36 + if (StrUtil.isNotEmpty(tenantId)) {
  37 + TenantContextHolder.setTenantId(Long.parseLong(tenantId));
  38 + }
  39 + }
  40 +
  41 + @Override
  42 + public void consumeMessageAfter(ConsumeMessageContext context) {
  43 + TenantContextHolder.clear();
  44 + }
  45 +
  46 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rocketmq/TenantRocketMQInitializer.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rocketmq;
  2 +
  3 +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
  4 +import org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl;
  5 +import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
  6 +import org.apache.rocketmq.client.producer.DefaultMQProducer;
  7 +import org.apache.rocketmq.spring.core.RocketMQTemplate;
  8 +import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer;
  9 +import org.springframework.beans.BeansException;
  10 +import org.springframework.beans.factory.config.BeanPostProcessor;
  11 +
  12 +/**
  13 + * 多租户的 RocketMQ 初始化器
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public class TenantRocketMQInitializer implements BeanPostProcessor {
  18 +
  19 + @Override
  20 + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  21 + if (bean instanceof DefaultRocketMQListenerContainer) {
  22 + DefaultRocketMQListenerContainer container = (DefaultRocketMQListenerContainer) bean;
  23 + initTenantConsumer(container.getConsumer());
  24 + } else if (bean instanceof RocketMQTemplate) {
  25 + RocketMQTemplate template = (RocketMQTemplate) bean;
  26 + initTenantProducer(template.getProducer());
  27 + }
  28 + return bean;
  29 + }
  30 +
  31 + private void initTenantProducer(DefaultMQProducer producer) {
  32 + if (producer == null) {
  33 + return;
  34 + }
  35 + DefaultMQProducerImpl producerImpl = producer.getDefaultMQProducerImpl();
  36 + if (producerImpl == null) {
  37 + return;
  38 + }
  39 + producerImpl.registerSendMessageHook(new TenantRocketMQSendMessageHook());
  40 + }
  41 +
  42 + private void initTenantConsumer(DefaultMQPushConsumer consumer) {
  43 + if (consumer == null) {
  44 + return;
  45 + }
  46 + DefaultMQPushConsumerImpl consumerImpl = consumer.getDefaultMQPushConsumerImpl();
  47 + if (consumerImpl == null) {
  48 + return;
  49 + }
  50 + consumerImpl.registerConsumeMessageHook(new TenantRocketMQConsumeMessageHook());
  51 + }
  52 +
  53 +}
0 \ No newline at end of file 54 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rocketmq/TenantRocketMQSendMessageHook.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rocketmq;
  2 +
  3 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  4 +import org.apache.rocketmq.client.hook.SendMessageContext;
  5 +import org.apache.rocketmq.client.hook.SendMessageHook;
  6 +
  7 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  8 +
  9 +/**
  10 + * RocketMQ 消息队列的多租户 {@link SendMessageHook} 实现类
  11 + *
  12 + * Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public class TenantRocketMQSendMessageHook implements SendMessageHook {
  17 +
  18 + @Override
  19 + public String hookName() {
  20 + return getClass().getSimpleName();
  21 + }
  22 +
  23 + @Override
  24 + public void sendMessageBefore(SendMessageContext sendMessageContext) {
  25 + Long tenantId = TenantContextHolder.getTenantId();
  26 + if (tenantId == null) {
  27 + return;
  28 + }
  29 + sendMessageContext.getMessage().putUserProperty(HEADER_TENANT_ID, tenantId.toString());
  30 + }
  31 +
  32 + @Override
  33 + public void sendMessageAfter(SendMessageContext sendMessageContext) {
  34 + }
  35 +
  36 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java 0 → 100644
  1 +/*
  2 + * Copyright 2002-2021 the original author or authors.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * https://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package org.springframework.messaging.handler.invocation;
  18 +
  19 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  20 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
  21 +import org.springframework.core.DefaultParameterNameDiscoverer;
  22 +import org.springframework.core.MethodParameter;
  23 +import org.springframework.core.ParameterNameDiscoverer;
  24 +import org.springframework.core.ResolvableType;
  25 +import org.springframework.lang.Nullable;
  26 +import org.springframework.messaging.Message;
  27 +import org.springframework.messaging.handler.HandlerMethod;
  28 +import org.springframework.util.ObjectUtils;
  29 +
  30 +import java.lang.reflect.InvocationTargetException;
  31 +import java.lang.reflect.Method;
  32 +import java.lang.reflect.Type;
  33 +import java.util.Arrays;
  34 +
  35 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  36 +
  37 +/**
  38 + * Extension of {@link HandlerMethod} that invokes the underlying method with
  39 + * argument values resolved from the current HTTP request through a list of
  40 + * {@link HandlerMethodArgumentResolver}.
  41 + *
  42 + * 针对 rabbitmq-spring 和 kafka-spring,不存在合适的拓展点,可以实现 Consumer 消费前,读取 Header 中的 tenant-id 设置到 {@link TenantContextHolder} 中
  43 + * TODO 芋艿:持续跟进,看看有没新的拓展点
  44 + *
  45 + * @author Rossen Stoyanchev
  46 + * @author Juergen Hoeller
  47 + * @since 4.0
  48 + */
  49 +public class InvocableHandlerMethod extends HandlerMethod {
  50 +
  51 + private static final Object[] EMPTY_ARGS = new Object[0];
  52 +
  53 + private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
  54 +
  55 + private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
  56 +
  57 + /**
  58 + * Create an instance from a {@code HandlerMethod}.
  59 + */
  60 + public InvocableHandlerMethod(HandlerMethod handlerMethod) {
  61 + super(handlerMethod);
  62 + }
  63 +
  64 + /**
  65 + * Create an instance from a bean instance and a method.
  66 + */
  67 + public InvocableHandlerMethod(Object bean, Method method) {
  68 + super(bean, method);
  69 + }
  70 +
  71 + /**
  72 + * Construct a new handler method with the given bean instance, method name and parameters.
  73 + * @param bean the object bean
  74 + * @param methodName the method name
  75 + * @param parameterTypes the method parameter types
  76 + * @throws NoSuchMethodException when the method cannot be found
  77 + */
  78 + public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
  79 + throws NoSuchMethodException {
  80 +
  81 + super(bean, methodName, parameterTypes);
  82 + }
  83 +
  84 + /**
  85 + * Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values.
  86 + */
  87 + public void setMessageMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
  88 + this.resolvers = argumentResolvers;
  89 + }
  90 +
  91 + /**
  92 + * Set the ParameterNameDiscoverer for resolving parameter names when needed
  93 + * (e.g. default request attribute name).
  94 + * <p>Default is a {@link DefaultParameterNameDiscoverer}.
  95 + */
  96 + public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
  97 + this.parameterNameDiscoverer = parameterNameDiscoverer;
  98 + }
  99 +
  100 + /**
  101 + * Invoke the method after resolving its argument values in the context of the given message.
  102 + * <p>Argument values are commonly resolved through
  103 + * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}.
  104 + * The {@code providedArgs} parameter however may supply argument values to be used directly,
  105 + * i.e. without argument resolution.
  106 + * <p>Delegates to {@link #getMethodArgumentValues} and calls {@link #doInvoke} with the
  107 + * resolved arguments.
  108 + * @param message the current message being processed
  109 + * @param providedArgs "given" arguments matched by type, not resolved
  110 + * @return the raw value returned by the invoked method
  111 + * @throws Exception raised if no suitable argument resolver can be found,
  112 + * or if the method raised an exception
  113 + * @see #getMethodArgumentValues
  114 + * @see #doInvoke
  115 + */
  116 + @Nullable
  117 + public Object invoke(Message<?> message, Object... providedArgs) throws Exception {
  118 + Object[] args = getMethodArgumentValues(message, providedArgs);
  119 + if (logger.isTraceEnabled()) {
  120 + logger.trace("Arguments: " + Arrays.toString(args));
  121 + }
  122 + // 注意:如下是本类的改动点!!!
  123 + // 情况一:无租户编号的情况
  124 + Long tenantId= parseTenantId(message);
  125 + if (tenantId == null) {
  126 + return doInvoke(args);
  127 + }
  128 + // 情况二:有租户的情况下
  129 + return TenantUtils.execute(tenantId, () -> doInvoke(args));
  130 + }
  131 +
  132 + private Long parseTenantId(Message<?> message) {
  133 + Object tenantId = message.getHeaders().get(HEADER_TENANT_ID);
  134 + if (tenantId == null) {
  135 + return null;
  136 + }
  137 + if (tenantId instanceof Long) {
  138 + return (Long) tenantId;
  139 + }
  140 + if (tenantId instanceof Number) {
  141 + return ((Number) tenantId).longValue();
  142 + }
  143 + if (tenantId instanceof String) {
  144 + return Long.parseLong((String) tenantId);
  145 + }
  146 + if (tenantId instanceof byte[]) {
  147 + return Long.parseLong(new String((byte[]) tenantId));
  148 + }
  149 + throw new IllegalArgumentException("未知的数据类型:" + tenantId);
  150 + }
  151 +
  152 + /**
  153 + * Get the method argument values for the current message, checking the provided
  154 + * argument values and falling back to the configured argument resolvers.
  155 + * <p>The resulting array will be passed into {@link #doInvoke}.
  156 + * @since 5.1.2
  157 + */
  158 + protected Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception {
  159 + MethodParameter[] parameters = getMethodParameters();
  160 + if (ObjectUtils.isEmpty(parameters)) {
  161 + return EMPTY_ARGS;
  162 + }
  163 +
  164 + Object[] args = new Object[parameters.length];
  165 + for (int i = 0; i < parameters.length; i++) {
  166 + MethodParameter parameter = parameters[i];
  167 + parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
  168 + args[i] = findProvidedArgument(parameter, providedArgs);
  169 + if (args[i] != null) {
  170 + continue;
  171 + }
  172 + if (!this.resolvers.supportsParameter(parameter)) {
  173 + throw new MethodArgumentResolutionException(
  174 + message, parameter, formatArgumentError(parameter, "No suitable resolver"));
  175 + }
  176 + try {
  177 + args[i] = this.resolvers.resolveArgument(parameter, message);
  178 + }
  179 + catch (Exception ex) {
  180 + // Leave stack trace for later, exception may actually be resolved and handled...
  181 + if (logger.isDebugEnabled()) {
  182 + String exMsg = ex.getMessage();
  183 + if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
  184 + logger.debug(formatArgumentError(parameter, exMsg));
  185 + }
  186 + }
  187 + throw ex;
  188 + }
  189 + }
  190 + return args;
  191 + }
  192 +
  193 + /**
  194 + * Invoke the handler method with the given argument values.
  195 + */
  196 + @Nullable
  197 + protected Object doInvoke(Object... args) throws Exception {
  198 + try {
  199 + return getBridgedMethod().invoke(getBean(), args);
  200 + }
  201 + catch (IllegalArgumentException ex) {
  202 + assertTargetBean(getBridgedMethod(), getBean(), args);
  203 + String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
  204 + throw new IllegalStateException(formatInvokeError(text, args), ex);
  205 + }
  206 + catch (InvocationTargetException ex) {
  207 + // Unwrap for HandlerExceptionResolvers ...
  208 + Throwable targetException = ex.getTargetException();
  209 + if (targetException instanceof RuntimeException) {
  210 + throw (RuntimeException) targetException;
  211 + }
  212 + else if (targetException instanceof Error) {
  213 + throw (Error) targetException;
  214 + }
  215 + else if (targetException instanceof Exception) {
  216 + throw (Exception) targetException;
  217 + }
  218 + else {
  219 + throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
  220 + }
  221 + }
  222 + }
  223 +
  224 + MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
  225 + return new AsyncResultMethodParameter(returnValue);
  226 + }
  227 +
  228 + private class AsyncResultMethodParameter extends HandlerMethodParameter {
  229 +
  230 + @Nullable
  231 + private final Object returnValue;
  232 +
  233 + private final ResolvableType returnType;
  234 +
  235 + public AsyncResultMethodParameter(@Nullable Object returnValue) {
  236 + super(-1);
  237 + this.returnValue = returnValue;
  238 + this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric();
  239 + }
  240 +
  241 + protected AsyncResultMethodParameter(AsyncResultMethodParameter original) {
  242 + super(original);
  243 + this.returnValue = original.returnValue;
  244 + this.returnType = original.returnType;
  245 + }
  246 +
  247 + @Override
  248 + public Class<?> getParameterType() {
  249 + if (this.returnValue != null) {
  250 + return this.returnValue.getClass();
  251 + }
  252 + if (!ResolvableType.NONE.equals(this.returnType)) {
  253 + return this.returnType.toClass();
  254 + }
  255 + return super.getParameterType();
  256 + }
  257 +
  258 + @Override
  259 + public Type getGenericParameterType() {
  260 + return this.returnType.getType();
  261 + }
  262 +
  263 + @Override
  264 + public AsyncResultMethodParameter clone() {
  265 + return new AsyncResultMethodParameter(this);
  266 + }
  267 + }
  268 +
  269 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories 0 → 100644
  1 +org.springframework.boot.env.EnvironmentPostProcessor=\
  2 + cn.iocoder.yudao.framework.tenant.core.mq.kafka.TenantKafkaEnvironmentPostProcessor
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/test/java/cn/iocoder/yudao/framework/tenant/core/job/TestJob.java deleted
1 -package cn.iocoder.yudao.framework.tenant.core.job;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;  
5 -import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;  
6 -import org.springframework.stereotype.Component;  
7 -  
8 -import java.util.List;  
9 -import java.util.concurrent.CopyOnWriteArrayList;  
10 -  
11 -@Component  
12 -public class TestJob implements JobHandler {  
13 -  
14 - private final List<Long> tenantIds = new CopyOnWriteArrayList<>();  
15 -  
16 - @Override  
17 - @TenantJob // 标记多租户  
18 - public String execute(String param) throws Exception {  
19 - tenantIds.add(TenantContextHolder.getTenantId());  
20 - return "success";  
21 - }  
22 -  
23 - public List<Long> getTenantIds() {  
24 - CollUtil.sort(tenantIds, Long::compareTo);  
25 - return tenantIds;  
26 - }  
27 -  
28 -}  
yudao-framework/yudao-spring-boot-starter-mq/pom.xml
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <packaging>jar</packaging> 12 <packaging>jar</packaging>
13 13
14 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
15 - <description>消息队列,基于 Redis Pub/Sub 实现广播消费,基于 Stream 实现集群消费</description> 15 + <description>消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种</description>
16 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 16 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
17 17
18 <dependencies> 18 <dependencies>
@@ -21,6 +21,23 @@ @@ -21,6 +21,23 @@
21 <groupId>cn.iocoder.boot</groupId> 21 <groupId>cn.iocoder.boot</groupId>
22 <artifactId>yudao-spring-boot-starter-redis</artifactId> 22 <artifactId>yudao-spring-boot-starter-redis</artifactId>
23 </dependency> 23 </dependency>
  24 +
  25 + <!-- 消息队列相关 -->
  26 + <dependency>
  27 + <groupId>org.springframework.kafka</groupId>
  28 + <artifactId>spring-kafka</artifactId>
  29 + <optional>true</optional>
  30 + </dependency>
  31 + <dependency>
  32 + <groupId>org.springframework.amqp</groupId>
  33 + <artifactId>spring-rabbit</artifactId>
  34 + <optional>true</optional>
  35 + </dependency>
  36 + <dependency>
  37 + <groupId>org.apache.rocketmq</groupId>
  38 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  39 + <optional>true</optional>
  40 + </dependency>
24 </dependencies> 41 </dependencies>
25 42
26 -</project> 43 -</project>
  44 +</project>
27 \ No newline at end of file 45 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/package-info.java
1 /** 1 /**
2 - * 消息队列,基于 Redis 提供:  
3 - * 1. 基于 Pub/Sub 实现广播消费  
4 - * 2. 基于 Stream 实现集群消费 2 + * 消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种
5 */ 3 */
6 package cn.iocoder.yudao.framework.mq; 4 package cn.iocoder.yudao.framework.mq;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/config/YudaoRabbitMQAutoConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mq.rabbitmq.config;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.amqp.utils.SerializationUtils;
  6 +import org.springframework.boot.autoconfigure.AutoConfiguration;
  7 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  8 +
  9 +import java.lang.reflect.Field;
  10 +
  11 +/**
  12 + * RabbitMQ 消息队列配置类
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@AutoConfiguration
  17 +@Slf4j
  18 +@ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
  19 +public class YudaoRabbitMQAutoConfiguration {
  20 +
  21 + static {
  22 + // 强制设置 SerializationUtils 的 TRUST_ALL 为 true,避免 RabbitMQ Consumer 反序列化消息报错
  23 + // 为什么不通过设置 spring.amqp.deserialization.trust.all 呢?因为可能在 SerializationUtils static 初始化后
  24 + Field trustAllField = ReflectUtil.getField(SerializationUtils.class, "TRUST_ALL");
  25 + ReflectUtil.removeFinalModify(trustAllField);
  26 + ReflectUtil.setFieldValue(SerializationUtils.class, trustAllField, true);
  27 + }
  28 +
  29 +}
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/core/package-info.java 0 → 100644
  1 +/**
  2 + * 占位符,无特殊逻辑
  3 + */
  4 +package cn.iocoder.yudao.framework.mq.rabbitmq.core;
0 \ No newline at end of file 5 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列,基于 RabbitMQ 提供
  3 + */
  4 +package cn.iocoder.yudao.framework.mq.rabbitmq;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQAutoConfiguration.java
1 -package cn.iocoder.yudao.framework.mq.config; 1 +package cn.iocoder.yudao.framework.mq.redis.config;
2 2
3 import cn.hutool.core.map.MapUtil; 3 import cn.hutool.core.map.MapUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.hutool.system.SystemUtil; 5 import cn.hutool.system.SystemUtil;
6 import cn.iocoder.yudao.framework.common.enums.DocumentEnum; 6 import cn.iocoder.yudao.framework.common.enums.DocumentEnum;
7 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
8 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
9 -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;  
10 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;  
11 -import cn.iocoder.yudao.framework.mq.job.RedisPendingMessageResendJob; 7 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  8 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  9 +import cn.iocoder.yudao.framework.mq.redis.core.job.RedisPendingMessageResendJob;
  10 +import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
  11 +import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
12 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; 12 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
14 import org.redisson.api.RedissonClient; 14 import org.redisson.api.RedissonClient;
15 import org.springframework.beans.factory.annotation.Value; 15 import org.springframework.beans.factory.annotation.Value;
16 import org.springframework.boot.autoconfigure.AutoConfiguration; 16 import org.springframework.boot.autoconfigure.AutoConfiguration;
17 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 17 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
18 -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
19 import org.springframework.context.annotation.Bean; 18 import org.springframework.context.annotation.Bean;
20 import org.springframework.data.redis.connection.RedisServerCommands; 19 import org.springframework.data.redis.connection.RedisServerCommands;
21 import org.springframework.data.redis.connection.stream.Consumer; 20 import org.springframework.data.redis.connection.stream.Consumer;
@@ -27,7 +26,6 @@ import org.springframework.data.redis.core.RedisTemplate; @@ -27,7 +26,6 @@ import org.springframework.data.redis.core.RedisTemplate;
27 import org.springframework.data.redis.core.StringRedisTemplate; 26 import org.springframework.data.redis.core.StringRedisTemplate;
28 import org.springframework.data.redis.listener.ChannelTopic; 27 import org.springframework.data.redis.listener.ChannelTopic;
29 import org.springframework.data.redis.listener.RedisMessageListenerContainer; 28 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
30 -import org.springframework.data.redis.stream.DefaultStreamMessageListenerContainerX;  
31 import org.springframework.data.redis.stream.StreamMessageListenerContainer; 29 import org.springframework.data.redis.stream.StreamMessageListenerContainer;
32 import org.springframework.scheduling.annotation.EnableScheduling; 30 import org.springframework.scheduling.annotation.EnableScheduling;
33 31
@@ -42,7 +40,7 @@ import java.util.Properties; @@ -42,7 +40,7 @@ import java.util.Properties;
42 @Slf4j 40 @Slf4j
43 @EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息 41 @EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息
44 @AutoConfiguration(after = YudaoRedisAutoConfiguration.class) 42 @AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
45 -public class YudaoMQAutoConfiguration { 43 +public class YudaoRedisMQAutoConfiguration {
46 44
47 @Bean 45 @Bean
48 public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate, 46 public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate,
@@ -59,10 +57,9 @@ public class YudaoMQAutoConfiguration { @@ -59,10 +57,9 @@ public class YudaoMQAutoConfiguration {
59 * 创建 Redis Pub/Sub 广播消费的容器 57 * 创建 Redis Pub/Sub 广播消费的容器
60 */ 58 */
61 @Bean(initMethod = "start", destroyMethod = "stop") 59 @Bean(initMethod = "start", destroyMethod = "stop")
62 - @ConditionalOnBean(AbstractChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听  
63 - @ConditionalOnProperty(prefix = "yudao.mq.redis.pubsub", value = "enable", matchIfMissing = true) // 允许使用 yudao.mq.redis.pubsub.enable=false 禁用多租户 60 + @ConditionalOnBean(AbstractRedisChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听
64 public RedisMessageListenerContainer redisMessageListenerContainer( 61 public RedisMessageListenerContainer redisMessageListenerContainer(
65 - RedisMQTemplate redisMQTemplate, List<AbstractChannelMessageListener<?>> listeners) { 62 + RedisMQTemplate redisMQTemplate, List<AbstractRedisChannelMessageListener<?>> listeners) {
66 // 创建 RedisMessageListenerContainer 对象 63 // 创建 RedisMessageListenerContainer 对象
67 RedisMessageListenerContainer container = new RedisMessageListenerContainer(); 64 RedisMessageListenerContainer container = new RedisMessageListenerContainer();
68 // 设置 RedisConnection 工厂。 65 // 设置 RedisConnection 工厂。
@@ -81,9 +78,8 @@ public class YudaoMQAutoConfiguration { @@ -81,9 +78,8 @@ public class YudaoMQAutoConfiguration {
81 * 创建 Redis Stream 重新消费的任务 78 * 创建 Redis Stream 重新消费的任务
82 */ 79 */
83 @Bean 80 @Bean
84 - @ConditionalOnBean(AbstractStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听  
85 - @ConditionalOnProperty(prefix = "yudao.mq.redis.stream", value = "enable", matchIfMissing = true) // 允许使用 yudao.mq.redis.stream.enable=false 禁用多租户  
86 - public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractStreamMessageListener<?>> listeners, 81 + @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
  82 + public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners,
87 RedisMQTemplate redisTemplate, 83 RedisMQTemplate redisTemplate,
88 @Value("${spring.application.name}") String groupName, 84 @Value("${spring.application.name}") String groupName,
89 RedissonClient redissonClient) { 85 RedissonClient redissonClient) {
@@ -92,14 +88,13 @@ public class YudaoMQAutoConfiguration { @@ -92,14 +88,13 @@ public class YudaoMQAutoConfiguration {
92 88
93 /** 89 /**
94 * 创建 Redis Stream 集群消费的容器 90 * 创建 Redis Stream 集群消费的容器
95 - * <p>  
96 - * Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html 91 + *
  92 + * 基础知识:<a href="https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html">Redis Stream 的 xreadgroup 命令</a>
97 */ 93 */
98 @Bean(initMethod = "start", destroyMethod = "stop") 94 @Bean(initMethod = "start", destroyMethod = "stop")
99 - @ConditionalOnBean(AbstractStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听  
100 - @ConditionalOnProperty(prefix = "yudao.mq.redis.stream", value = "enable", matchIfMissing = true) // 允许使用 yudao.mq.redis.stream.enable=false 禁用多租户 95 + @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
101 public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer( 96 public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(
102 - RedisMQTemplate redisMQTemplate, List<AbstractStreamMessageListener<?>> listeners) { 97 + RedisMQTemplate redisMQTemplate, List<AbstractRedisStreamMessageListener<?>> listeners) {
103 RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate(); 98 RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate();
104 checkRedisVersion(redisTemplate); 99 checkRedisVersion(redisTemplate);
105 // 第一步,创建 StreamMessageListenerContainer 容器 100 // 第一步,创建 StreamMessageListenerContainer 容器
@@ -111,8 +106,7 @@ public class YudaoMQAutoConfiguration { @@ -111,8 +106,7 @@ public class YudaoMQAutoConfiguration {
111 .build(); 106 .build();
112 // 创建 container 对象 107 // 创建 container 对象
113 StreamMessageListenerContainer<String, ObjectRecord<String, String>> container = 108 StreamMessageListenerContainer<String, ObjectRecord<String, String>> container =
114 -// StreamMessageListenerContainer.create(redisTemplate.getRequiredConnectionFactory(), containerOptions);  
115 - DefaultStreamMessageListenerContainerX.create(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory(), containerOptions); 109 + StreamMessageListenerContainer.create(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory(), containerOptions);
116 110
117 // 第二步,注册监听器,消费对应的 Stream 主题 111 // 第二步,注册监听器,消费对应的 Stream 主题
118 String consumerName = buildConsumerName(); 112 String consumerName = buildConsumerName();
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/RedisMQTemplate.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/RedisMQTemplate.java
1 -package cn.iocoder.yudao.framework.mq.core; 1 +package cn.iocoder.yudao.framework.mq.redis.core;
2 2
3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
5 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage;  
6 -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;  
7 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; 4 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  5 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
  6 +import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessage;
  7 +import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessage;
8 import lombok.AllArgsConstructor; 8 import lombok.AllArgsConstructor;
9 import lombok.Getter; 9 import lombok.Getter;
10 import org.springframework.data.redis.connection.stream.RecordId; 10 import org.springframework.data.redis.connection.stream.RecordId;
@@ -35,7 +35,7 @@ public class RedisMQTemplate { @@ -35,7 +35,7 @@ public class RedisMQTemplate {
35 * 35 *
36 * @param message 消息 36 * @param message 消息
37 */ 37 */
38 - public <T extends AbstractChannelMessage> void send(T message) { 38 + public <T extends AbstractRedisChannelMessage> void send(T message) {
39 try { 39 try {
40 sendMessageBefore(message); 40 sendMessageBefore(message);
41 // 发送消息 41 // 发送消息
@@ -51,7 +51,7 @@ public class RedisMQTemplate { @@ -51,7 +51,7 @@ public class RedisMQTemplate {
51 * @param message 消息 51 * @param message 消息
52 * @return 消息记录的编号对象 52 * @return 消息记录的编号对象
53 */ 53 */
54 - public <T extends AbstractStreamMessage> RecordId send(T message) { 54 + public <T extends AbstractRedisStreamMessage> RecordId send(T message) {
55 try { 55 try {
56 sendMessageBefore(message); 56 sendMessageBefore(message);
57 // 发送消息 57 // 发送消息
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/interceptor/RedisMessageInterceptor.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/interceptor/RedisMessageInterceptor.java
1 -package cn.iocoder.yudao.framework.mq.core.interceptor; 1 +package cn.iocoder.yudao.framework.mq.redis.core.interceptor;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 3 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
4 4
5 /** 5 /**
6 * {@link AbstractRedisMessage} 消息拦截器 6 * {@link AbstractRedisMessage} 消息拦截器
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/job/RedisPendingMessageResendJob.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/job/RedisPendingMessageResendJob.java
1 -package cn.iocoder.yudao.framework.mq.job; 1 +package cn.iocoder.yudao.framework.mq.redis.core.job;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
5 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; 4 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  5 +import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
6 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
7 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
8 import org.redisson.api.RLock; 8 import org.redisson.api.RLock;
@@ -33,7 +33,7 @@ public class RedisPendingMessageResendJob { @@ -33,7 +33,7 @@ public class RedisPendingMessageResendJob {
33 */ 33 */
34 private static final int EXPIRE_TIME = 5 * 60; 34 private static final int EXPIRE_TIME = 5 * 60;
35 35
36 - private final List<AbstractStreamMessageListener<?>> listeners; 36 + private final List<AbstractRedisStreamMessageListener<?>> listeners;
37 private final RedisMQTemplate redisTemplate; 37 private final RedisMQTemplate redisTemplate;
38 private final String groupName; 38 private final String groupName;
39 private final RedissonClient redissonClient; 39 private final RedissonClient redissonClient;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/message/AbstractRedisMessage.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/message/AbstractRedisMessage.java
1 -package cn.iocoder.yudao.framework.mq.core.message; 1 +package cn.iocoder.yudao.framework.mq.redis.core.message;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessage.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/pubsub/AbstractRedisChannelMessage.java
1 -package cn.iocoder.yudao.framework.mq.core.pubsub; 1 +package cn.iocoder.yudao.framework.mq.redis.core.pubsub;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 3 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
4 import com.fasterxml.jackson.annotation.JsonIgnore; 4 import com.fasterxml.jackson.annotation.JsonIgnore;
5 5
6 /** 6 /**
@@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
8 * 8 *
9 * @author 芋道源码 9 * @author 芋道源码
10 */ 10 */
11 -public abstract class AbstractChannelMessage extends AbstractRedisMessage { 11 +public abstract class AbstractRedisChannelMessage extends AbstractRedisMessage {
12 12
13 /** 13 /**
14 - * 获得 Redis Channel 14 + * 获得 Redis Channel,默认使用类名
15 * 15 *
16 * @return Channel 16 * @return Channel
17 */ 17 */
18 @JsonIgnore // 避免序列化。原因是,Redis 发布 Channel 消息的时候,已经会指定。 18 @JsonIgnore // 避免序列化。原因是,Redis 发布 Channel 消息的时候,已经会指定。
19 - public abstract String getChannel(); 19 + public String getChannel() {
  20 + return getClass().getSimpleName();
  21 + }
20 22
21 } 23 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java
1 -package cn.iocoder.yudao.framework.mq.core.pubsub; 1 +package cn.iocoder.yudao.framework.mq.redis.core.pubsub;
2 2
3 import cn.hutool.core.util.TypeUtil; 3 import cn.hutool.core.util.TypeUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
6 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
7 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 5 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  6 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  7 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
8 import lombok.Setter; 8 import lombok.Setter;
9 import lombok.SneakyThrows; 9 import lombok.SneakyThrows;
10 import org.springframework.data.redis.connection.Message; 10 import org.springframework.data.redis.connection.Message;
@@ -20,7 +20,7 @@ import java.util.List; @@ -20,7 +20,7 @@ import java.util.List;
20 * 20 *
21 * @author 芋道源码 21 * @author 芋道源码
22 */ 22 */
23 -public abstract class AbstractChannelMessageListener<T extends AbstractChannelMessage> implements MessageListener { 23 +public abstract class AbstractRedisChannelMessageListener<T extends AbstractRedisChannelMessage> implements MessageListener {
24 24
25 /** 25 /**
26 * 消息类型 26 * 消息类型
@@ -37,7 +37,7 @@ public abstract class AbstractChannelMessageListener&lt;T extends AbstractChannelMe @@ -37,7 +37,7 @@ public abstract class AbstractChannelMessageListener&lt;T extends AbstractChannelMe
37 private RedisMQTemplate redisMQTemplate; 37 private RedisMQTemplate redisMQTemplate;
38 38
39 @SneakyThrows 39 @SneakyThrows
40 - protected AbstractChannelMessageListener() { 40 + protected AbstractRedisChannelMessageListener() {
41 this.messageType = getMessageClass(); 41 this.messageType = getMessageClass();
42 this.channel = messageType.getDeclaredConstructor().newInstance().getChannel(); 42 this.channel = messageType.getDeclaredConstructor().newInstance().getChannel();
43 } 43 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/stream/AbstractStreamMessage.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/stream/AbstractRedisStreamMessage.java
1 -package cn.iocoder.yudao.framework.mq.core.stream; 1 +package cn.iocoder.yudao.framework.mq.redis.core.stream;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 3 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
4 import com.fasterxml.jackson.annotation.JsonIgnore; 4 import com.fasterxml.jackson.annotation.JsonIgnore;
5 5
6 /** 6 /**
@@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
8 * 8 *
9 * @author 芋道源码 9 * @author 芋道源码
10 */ 10 */
11 -public abstract class AbstractStreamMessage extends AbstractRedisMessage { 11 +public abstract class AbstractRedisStreamMessage extends AbstractRedisMessage {
12 12
13 /** 13 /**
14 - * 获得 Redis Stream Key 14 + * 获得 Redis Stream Key,默认使用类名
15 * 15 *
16 * @return Channel 16 * @return Channel
17 */ 17 */
18 @JsonIgnore // 避免序列化 18 @JsonIgnore // 避免序列化
19 - public abstract String getStreamKey(); 19 + public String getStreamKey() {
  20 + return getClass().getSimpleName();
  21 + }
20 22
21 } 23 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/stream/AbstractStreamMessageListener.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/stream/AbstractRedisStreamMessageListener.java
1 -package cn.iocoder.yudao.framework.mq.core.stream; 1 +package cn.iocoder.yudao.framework.mq.redis.core.stream;
2 2
3 import cn.hutool.core.util.TypeUtil; 3 import cn.hutool.core.util.TypeUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
6 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
7 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 5 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  6 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  7 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
8 import lombok.Getter; 8 import lombok.Getter;
9 import lombok.Setter; 9 import lombok.Setter;
10 import lombok.SneakyThrows; 10 import lombok.SneakyThrows;
@@ -22,7 +22,7 @@ import java.util.List; @@ -22,7 +22,7 @@ import java.util.List;
22 * 22 *
23 * @author 芋道源码 23 * @author 芋道源码
24 */ 24 */
25 -public abstract class AbstractStreamMessageListener<T extends AbstractStreamMessage> 25 +public abstract class AbstractRedisStreamMessageListener<T extends AbstractRedisStreamMessage>
26 implements StreamListener<String, ObjectRecord<String, String>> { 26 implements StreamListener<String, ObjectRecord<String, String>> {
27 27
28 /** 28 /**
@@ -48,7 +48,7 @@ public abstract class AbstractStreamMessageListener&lt;T extends AbstractStreamMess @@ -48,7 +48,7 @@ public abstract class AbstractStreamMessageListener&lt;T extends AbstractStreamMess
48 private RedisMQTemplate redisMQTemplate; 48 private RedisMQTemplate redisMQTemplate;
49 49
50 @SneakyThrows 50 @SneakyThrows
51 - protected AbstractStreamMessageListener() { 51 + protected AbstractRedisStreamMessageListener() {
52 this.messageType = getMessageClass(); 52 this.messageType = getMessageClass();
53 this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey(); 53 this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey();
54 } 54 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列,基于 Redis 提供:
  3 + * 1. 基于 Pub/Sub 实现广播消费
  4 + * 2. 基于 Stream 实现集群消费
  5 + */
  6 +package cn.iocoder.yudao.framework.mq.redis;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/org/springframework/data/redis/stream/DefaultStreamMessageListenerContainerX.java deleted
1 -package org.springframework.data.redis.stream;  
2 -  
3 -import cn.hutool.core.util.ReflectUtil;  
4 -import org.springframework.data.redis.connection.RedisConnectionFactory;  
5 -import org.springframework.data.redis.connection.stream.ByteRecord;  
6 -import org.springframework.data.redis.connection.stream.ReadOffset;  
7 -import org.springframework.data.redis.connection.stream.Record;  
8 -import org.springframework.util.Assert;  
9 -  
10 -import java.util.Collections;  
11 -import java.util.List;  
12 -import java.util.function.Function;  
13 -  
14 -/**  
15 - * 拓展 DefaultStreamMessageListenerContainer 实现,解决 Spring Data Redis + Redisson 结合使用时,Redisson 在 Stream 获得不到数据时,返回 null 而不是空 List,导致 NPE 异常。  
16 - * 对应 issue:https://github.com/spring-projects/spring-data-redis/issues/2147 和 https://github.com/redisson/redisson/issues/4006  
17 - * 目前看下来 Spring Data Redis 不肯加 null 判断,Redisson 暂时也没改返回 null 到空 List 的打算,所以暂时只能自己改,哽咽!  
18 - *  
19 - * @author 芋道源码  
20 - */  
21 -public class DefaultStreamMessageListenerContainerX<K, V extends Record<K, ?>> extends DefaultStreamMessageListenerContainer<K, V> {  
22 -  
23 - /**  
24 - * 参考 {@link StreamMessageListenerContainer#create(RedisConnectionFactory, StreamMessageListenerContainerOptions)} 的实现  
25 - */  
26 - public static <K, V extends Record<K, ?>> StreamMessageListenerContainer<K, V> create(RedisConnectionFactory connectionFactory, StreamMessageListenerContainer.StreamMessageListenerContainerOptions<K, V> options) {  
27 - Assert.notNull(connectionFactory, "RedisConnectionFactory must not be null!");  
28 - Assert.notNull(options, "StreamMessageListenerContainerOptions must not be null!");  
29 - return new DefaultStreamMessageListenerContainerX<>(connectionFactory, options);  
30 - }  
31 -  
32 - public DefaultStreamMessageListenerContainerX(RedisConnectionFactory connectionFactory, StreamMessageListenerContainerOptions<K, V> containerOptions) {  
33 - super(connectionFactory, containerOptions);  
34 - }  
35 -  
36 - /**  
37 - * 参考 {@link DefaultStreamMessageListenerContainer#register(StreamReadRequest, StreamListener)} 的实现  
38 - */  
39 - @Override  
40 - public Subscription register(StreamReadRequest<K> streamRequest, StreamListener<K, V> listener) {  
41 - return this.doRegisterX(getReadTaskX(streamRequest, listener));  
42 - }  
43 -  
44 - @SuppressWarnings("unchecked")  
45 - private StreamPollTask<K, V> getReadTaskX(StreamReadRequest<K> streamRequest, StreamListener<K, V> listener) {  
46 - StreamPollTask<K, V> task = ReflectUtil.invoke(this, "getReadTask", streamRequest, listener);  
47 - // 修改 readFunction 方法  
48 - Function<ReadOffset, List<ByteRecord>> readFunction = (Function<ReadOffset, List<ByteRecord>>) ReflectUtil.getFieldValue(task, "readFunction");  
49 - ReflectUtil.setFieldValue(task, "readFunction", (Function<ReadOffset, List<ByteRecord>>) readOffset -> {  
50 - List<ByteRecord> records = readFunction.apply(readOffset);  
51 - //【重点】保证 records 不是空,避免 NPE 的问题!!!  
52 - return records != null ? records : Collections.emptyList();  
53 - });  
54 - return task;  
55 - }  
56 -  
57 - private Subscription doRegisterX(Task task) {  
58 - return ReflectUtil.invoke(this, "doRegister", task);  
59 - }  
60 -  
61 -}  
62 -  
yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 -cn.iocoder.yudao.framework.mq.config.YudaoMQAutoConfiguration  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQAutoConfiguration
  3 +cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration
3 \ No newline at end of file 4 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 事件机制 Event 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/RocketMQ/?yudao>
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 消息队列 Kafka 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/Kafka/?yudao>
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 消息队列 RabbitMQ 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/RabbitMQ/?yudao>
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 消息队列 RocketMQ 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/RocketMQ/?yudao>
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java
@@ -5,7 +5,6 @@ import lombok.Data; @@ -5,7 +5,6 @@ import lombok.Data;
5 import javax.validation.constraints.NotNull; 5 import javax.validation.constraints.NotNull;
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
7 7
8 -// TODO @小吉祥:搞个 job,清理 14 天外的访问日志;  
9 /** 8 /**
10 * API 访问日志 9 * API 访问日志
11 * 10 *
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java
@@ -5,7 +5,6 @@ import lombok.Data; @@ -5,7 +5,6 @@ import lombok.Data;
5 import javax.validation.constraints.NotNull; 5 import javax.validation.constraints.NotNull;
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
7 7
8 -// TODO @小吉祥:搞个 job,清理 14 天外的异常日志;  
9 /** 8 /**
10 * API 错误日志 9 * API 错误日志
11 * 10 *
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmCommentTypeEnum.java
@@ -20,16 +20,16 @@ public enum BpmCommentTypeEnum { @@ -20,16 +20,16 @@ public enum BpmCommentTypeEnum {
20 ; 20 ;
21 21
22 /** 22 /**
23 - * 结果 23 + * 操作类型
24 */ 24 */
25 private final Integer type; 25 private final Integer type;
26 /** 26 /**
27 - * 描述 27 + * 操作名字
28 */ 28 */
29 - private final String desc; 29 + private final String name;
30 /** 30 /**
31 - * 模板信息 31 + * 操作描述
32 */ 32 */
33 - private final String templateComment; 33 + private final String comment;
34 34
35 } 35 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java
@@ -30,13 +30,13 @@ public enum BpmProcessInstanceResultEnum { @@ -30,13 +30,13 @@ public enum BpmProcessInstanceResultEnum {
30 * 相当于是 通过 APPROVE 的特殊状态 30 * 相当于是 通过 APPROVE 的特殊状态
31 * 例如:A审批, A 后加签了 B,并且审批通过了任务,但是 B 还未审批,则当前任务状态为“待后加签任务完成” 31 * 例如:A审批, A 后加签了 B,并且审批通过了任务,但是 B 还未审批,则当前任务状态为“待后加签任务完成”
32 */ 32 */
33 - ADD_SIGN_AFTER(7, "待后加签任务完成"), 33 + SIGN_AFTER(7, "待后加签任务完成"),
34 /** 34 /**
35 * 【加签】源任务未审批,但是向前加签了,所以源任务状态变为“待前加签任务完成” 35 * 【加签】源任务未审批,但是向前加签了,所以源任务状态变为“待前加签任务完成”
36 * 相当于是 处理中 PROCESS 的特殊状态 36 * 相当于是 处理中 PROCESS 的特殊状态
37 * 例如:A 审批, A 前加签了 B,B 还未审核 37 * 例如:A 审批, A 前加签了 B,B 还未审核
38 */ 38 */
39 - ADD_SIGN_BEFORE(8, "待前加签任务完成"), 39 + SIGN_BEFORE(8, "待前加签任务完成"),
40 /** 40 /**
41 * 【加签】后加签任务被创建时的初始状态 41 * 【加签】后加签任务被创建时的初始状态
42 * 相当于是 处理中 PROCESS 的特殊状态 42 * 相当于是 处理中 PROCESS 的特殊状态
@@ -71,7 +71,7 @@ public enum BpmProcessInstanceResultEnum { @@ -71,7 +71,7 @@ public enum BpmProcessInstanceResultEnum {
71 public static boolean isEndResult(Integer result) { 71 public static boolean isEndResult(Integer result) {
72 return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(), 72 return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(),
73 CANCEL.getResult(), BACK.getResult(), 73 CANCEL.getResult(), BACK.getResult(),
74 - ADD_SIGN_AFTER.getResult()); 74 + SIGN_AFTER.getResult());
75 } 75 }
76 76
77 } 77 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskAddSignTypeEnum.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.enums.task; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.enums.task;
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
5 5
6 -  
7 /** 6 /**
8 * 流程任务 -- 加签类型枚举类型 7 * 流程任务 -- 加签类型枚举类型
9 */ 8 */
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
@@ -74,7 +74,7 @@ public class BpmTaskController { @@ -74,7 +74,7 @@ public class BpmTaskController {
74 return success(true); 74 return success(true);
75 } 75 }
76 76
77 - @GetMapping("/get-return-list") 77 + @GetMapping("/return-list")
78 @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮") 78 @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮")
79 @Parameter(name = "taskId", description = "当前任务ID", required = true) 79 @Parameter(name = "taskId", description = "当前任务ID", required = true)
80 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 80 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
@@ -98,27 +98,28 @@ public class BpmTaskController { @@ -98,27 +98,28 @@ public class BpmTaskController {
98 return success(true); 98 return success(true);
99 } 99 }
100 100
101 - @PutMapping("/add-sign") 101 + @PutMapping("/create-sign")
102 @Operation(summary = "加签", description = "before 前加签,after 后加签") 102 @Operation(summary = "加签", description = "before 前加签,after 后加签")
103 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 103 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
104 - public CommonResult<Boolean> addSignTask(@Valid @RequestBody BpmTaskAddSignReqVO reqVO) {  
105 - taskService.addSignTask(getLoginUserId(), reqVO); 104 + public CommonResult<Boolean> createSignTask(@Valid @RequestBody BpmTaskAddSignReqVO reqVO) {
  105 + taskService.createSignTask(getLoginUserId(), reqVO);
106 return success(true); 106 return success(true);
107 } 107 }
108 108
109 - @PutMapping("/sub-sign") 109 + @DeleteMapping("/delete-sign")
110 @Operation(summary = "减签") 110 @Operation(summary = "减签")
111 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 111 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
112 - public CommonResult<Boolean> subSignTask(@Valid @RequestBody BpmTaskSubSignReqVO reqVO) {  
113 - taskService.subSignTask(getLoginUserId(), reqVO); 112 + public CommonResult<Boolean> deleteSignTask(@Valid @RequestBody BpmTaskSubSignReqVO reqVO) {
  113 + taskService.deleteSignTask(getLoginUserId(), reqVO);
114 return success(true); 114 return success(true);
115 } 115 }
116 116
117 - @GetMapping("/get-children-task-list") 117 + @GetMapping("children-list")
118 @Operation(summary = "获取能被减签的任务") 118 @Operation(summary = "获取能被减签的任务")
  119 + @Parameter(name = "parentId", description = "父级任务 ID", required = true)
119 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 120 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
120 - public CommonResult<List<BpmTaskSubSignRespVO>> getChildrenTaskList(@RequestParam("taskId") String taskId) {  
121 - return success(taskService.getChildrenTaskList(taskId)); 121 + public CommonResult<List<BpmTaskSubSignRespVO>> getChildrenTaskList(@RequestParam("parentId") String parentId) {
  122 + return success(taskService.getChildrenTaskList(parentId));
122 } 123 }
123 124
124 } 125 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskAddSignReqVO.java
@@ -6,6 +6,7 @@ import lombok.Data; @@ -6,6 +6,7 @@ import lombok.Data;
6 import javax.validation.constraints.NotEmpty; 6 import javax.validation.constraints.NotEmpty;
7 import java.util.Set; 7 import java.util.Set;
8 8
  9 +// TODO @海洋:类名,应该是 create 哈
9 @Schema(description = "管理后台 - 加签流程任务的 Request VO") 10 @Schema(description = "管理后台 - 加签流程任务的 Request VO")
10 @Data 11 @Data
11 public class BpmTaskAddSignReqVO { 12 public class BpmTaskAddSignReqVO {
@@ -26,4 +27,4 @@ public class BpmTaskAddSignReqVO { @@ -26,4 +27,4 @@ public class BpmTaskAddSignReqVO {
26 @NotEmpty(message = "加签原因不能为空") 27 @NotEmpty(message = "加签原因不能为空")
27 private String reason; 28 private String reason;
28 29
29 -}  
30 \ No newline at end of file 30 \ No newline at end of file
  31 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSubSignReqVO.java
@@ -5,6 +5,7 @@ import lombok.Data; @@ -5,6 +5,7 @@ import lombok.Data;
5 5
6 import javax.validation.constraints.NotEmpty; 6 import javax.validation.constraints.NotEmpty;
7 7
  8 +// TODO @海洋:类名,应该是 delete 哈
8 @Schema(description = "管理后台 - 减签流程任务的 Request VO") 9 @Schema(description = "管理后台 - 减签流程任务的 Request VO")
9 @Data 10 @Data
10 public class BpmTaskSubSignReqVO { 11 public class BpmTaskSubSignReqVO {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
1 package cn.iocoder.yudao.module.bpm.convert.task; 1 package cn.iocoder.yudao.module.bpm.convert.task;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 8 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
8 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 9 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 10 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
@@ -25,6 +26,9 @@ import java.util.Date; @@ -25,6 +26,9 @@ import java.util.Date;
25 import java.util.List; 26 import java.util.List;
26 import java.util.Map; 27 import java.util.Map;
27 28
  29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
  31 +
28 /** 32 /**
29 * Bpm 任务 Convert 33 * Bpm 任务 Convert
30 * 34 *
@@ -167,32 +171,31 @@ public interface BpmTaskConvert { @@ -167,32 +171,31 @@ public interface BpmTaskConvert {
167 default List<BpmTaskSubSignRespVO> convertList(List<BpmTaskExtDO> bpmTaskExtDOList, 171 default List<BpmTaskSubSignRespVO> convertList(List<BpmTaskExtDO> bpmTaskExtDOList,
168 Map<Long, AdminUserRespDTO> userMap, 172 Map<Long, AdminUserRespDTO> userMap,
169 Map<String, Task> idTaskMap){ 173 Map<String, Task> idTaskMap){
170 - return CollectionUtils.convertList(bpmTaskExtDOList, task->{  
171 - BpmTaskSubSignRespVO bpmTaskSubSignRespVO = new BpmTaskSubSignRespVO();  
172 - bpmTaskSubSignRespVO.setName(task.getName());  
173 - bpmTaskSubSignRespVO.setId(task.getTaskId());  
174 - Task sourceTask = idTaskMap.get(task.getTaskId()); 174 + return CollectionUtils.convertList(bpmTaskExtDOList, task -> {
  175 + BpmTaskSubSignRespVO bpmTaskSubSignRespVO = new BpmTaskSubSignRespVO()
  176 + .setId(task.getTaskId()).setName(task.getName());
175 // 后加签任务不会直接设置 assignee ,所以不存在 assignee 的情况,则去取 owner 177 // 后加签任务不会直接设置 assignee ,所以不存在 assignee 的情况,则去取 owner
176 - String assignee = StrUtil.isNotEmpty(sourceTask.getAssignee()) ? sourceTask.getAssignee() : sourceTask.getOwner();  
177 - AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(assignee));  
178 - if (assignUser != null) {  
179 - bpmTaskSubSignRespVO.setAssigneeUser(convert3(assignUser));  
180 - } 178 + Task sourceTask = idTaskMap.get(task.getTaskId());
  179 + String assignee = ObjectUtil.defaultIfBlank(sourceTask.getOwner(),sourceTask.getAssignee());
  180 + MapUtils.findAndThen(userMap,NumberUtils.parseLong(assignee),
  181 + assignUser-> bpmTaskSubSignRespVO.setAssigneeUser(convert3(assignUser)));
181 return bpmTaskSubSignRespVO; 182 return bpmTaskSubSignRespVO;
182 }); 183 });
183 } 184 }
184 185
185 /** 186 /**
186 * 转换任务为父子级 187 * 转换任务为父子级
  188 + *
187 * @param sourceList 原始数据 189 * @param sourceList 原始数据
188 * @return 转换后的父子级数组 190 * @return 转换后的父子级数组
189 */ 191 */
190 - default List<BpmTaskRespVO> convertChildrenList(List<BpmTaskRespVO> sourceList){  
191 - List<BpmTaskRespVO> childrenTaskList = CollectionUtils.filterList(sourceList, r -> StrUtil.isNotEmpty(r.getParentTaskId()));  
192 - Map<String, List<BpmTaskRespVO>> parentChildrenTaskListMap = CollectionUtils.convertMultiMap(childrenTaskList, BpmTaskRespVO::getParentTaskId); 192 + default List<BpmTaskRespVO> convertChildrenList(List<BpmTaskRespVO> sourceList) {
  193 + List<BpmTaskRespVO> childrenTaskList = filterList(sourceList, r -> StrUtil.isNotEmpty(r.getParentTaskId()));
  194 + Map<String, List<BpmTaskRespVO>> parentChildrenTaskListMap = convertMultiMap(childrenTaskList, BpmTaskRespVO::getParentTaskId);
193 for (BpmTaskRespVO bpmTaskRespVO : sourceList) { 195 for (BpmTaskRespVO bpmTaskRespVO : sourceList) {
194 bpmTaskRespVO.setChildren(parentChildrenTaskListMap.get(bpmTaskRespVO.getId())); 196 bpmTaskRespVO.setChildren(parentChildrenTaskListMap.get(bpmTaskRespVO.getId()));
195 } 197 }
196 - return CollectionUtils.filterList(sourceList, r -> StrUtil.isEmpty(r.getParentTaskId())); 198 + return filterList(sourceList, r -> StrUtil.isEmpty(r.getParentTaskId()));
197 } 199 }
  200 +
198 } 201 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java
@@ -21,13 +21,13 @@ public interface BpmTaskExtMapper extends BaseMapperX&lt;BpmTaskExtDO&gt; { @@ -21,13 +21,13 @@ public interface BpmTaskExtMapper extends BaseMapperX&lt;BpmTaskExtDO&gt; {
21 return selectList(BpmTaskExtDO::getTaskId, taskIds); 21 return selectList(BpmTaskExtDO::getTaskId, taskIds);
22 } 22 }
23 23
  24 + // TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务
24 default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) { 25 default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) {
25 return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>() 26 return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>()
26 .in(BpmTaskExtDO::getTaskId, taskIds) 27 .in(BpmTaskExtDO::getTaskId, taskIds)
27 .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST)); 28 .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST));
28 } 29 }
29 30
30 -  
31 default BpmTaskExtDO selectByTaskId(String taskId) { 31 default BpmTaskExtDO selectByTaskId(String taskId) {
32 return selectOne(BpmTaskExtDO::getTaskId, taskId); 32 return selectOne(BpmTaskExtDO::getTaskId, taskId);
33 } 33 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmSecurityConfiguration.java deleted
1 -package cn.iocoder.yudao.module.bpm.framework.bpm.config;  
2 -  
3 -import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;  
4 -import org.springframework.context.annotation.Bean;  
5 -import org.springframework.context.annotation.Configuration;  
6 -import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
7 -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;  
8 -  
9 -/**  
10 - * @author kemengkai  
11 - * @create 2022-05-07 08:15  
12 - */  
13 -@Configuration("bpmSecurityConfiguration")  
14 -public class BpmSecurityConfiguration {  
15 -  
16 - @Bean("bpmAuthorizeRequestsCustomizer")  
17 - public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {  
18 - return new AuthorizeRequestsCustomizer() {  
19 -  
20 - @Override  
21 - public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {  
22 - // 任务回退接口  
23 - registry.antMatchers(buildAdminApi("/bpm/task/back")).permitAll();  
24 - }  
25 -  
26 - };  
27 - }  
28 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
@@ -12,6 +12,7 @@ import javax.validation.Valid; @@ -12,6 +12,7 @@ import javax.validation.Valid;
12 * @author yunlongn 12 * @author yunlongn
13 */ 13 */
14 public interface BpmModelService { 14 public interface BpmModelService {
  15 +
15 /** 16 /**
16 * 获得流程模型分页 17 * 获得流程模型分页
17 * 18 *
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -288,5 +288,4 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -288,5 +288,4 @@ public class BpmModelServiceImpl implements BpmModelService {
288 processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode()); 288 processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
289 } 289 }
290 290
291 -  
292 } 291 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
@@ -163,7 +163,7 @@ public interface BpmTaskService { @@ -163,7 +163,7 @@ public interface BpmTaskService {
163 * @param userId 被加签的用户和任务 ID,加签类型 163 * @param userId 被加签的用户和任务 ID,加签类型
164 * @param reqVO 当前用户 ID 164 * @param reqVO 当前用户 ID
165 */ 165 */
166 - void addSignTask(Long userId, BpmTaskAddSignReqVO reqVO); 166 + void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO);
167 167
168 /** 168 /**
169 * 任务减签名 169 * 任务减签名
@@ -171,14 +171,14 @@ public interface BpmTaskService { @@ -171,14 +171,14 @@ public interface BpmTaskService {
171 * @param userId 当前用户ID 171 * @param userId 当前用户ID
172 * @param reqVO 被减签的任务 ID,理由 172 * @param reqVO 被减签的任务 ID,理由
173 */ 173 */
174 - void subSignTask(Long userId, BpmTaskSubSignReqVO reqVO); 174 + void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO);
175 175
176 /** 176 /**
177 * 获取指定任务的子任务和审批人信息 177 * 获取指定任务的子任务和审批人信息
178 * 178 *
179 - * @param taskId 指定任务ID 179 + * @param parentId 指定任务ID
180 * @return 子任务列表 180 * @return 子任务列表
181 */ 181 */
182 - List<BpmTaskSubSignRespVO> getChildrenTaskList(String taskId); 182 + List<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId);
183 183
184 } 184 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -53,7 +53,6 @@ import javax.annotation.Resource; @@ -53,7 +53,6 @@ import javax.annotation.Resource;
53 import javax.validation.Valid; 53 import javax.validation.Valid;
54 import java.time.LocalDateTime; 54 import java.time.LocalDateTime;
55 import java.util.*; 55 import java.util.*;
56 -import java.util.stream.Collectors;  
57 import java.util.stream.Stream; 56 import java.util.stream.Stream;
58 57
59 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 58 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -240,10 +239,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -240,10 +239,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
240 handleParentTask(task); 239 handleParentTask(task);
241 } 240 }
242 241
  242 +
243 /** 243 /**
244 * 审批通过存在“后加签”的任务。 244 * 审批通过存在“后加签”的任务。
245 * <p> 245 * <p>
246 - * 注意:该任务不能马上完成,需要一个中间状态(ADD_SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理 246 + * 注意:该任务不能马上完成,需要一个中间状态(SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理
247 * 247 *
248 * @param task 当前任务 248 * @param task 当前任务
249 * @param reqVO 前端请求参数 249 * @param reqVO 前端请求参数
@@ -251,7 +251,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -251,7 +251,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
251 private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) { 251 private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) {
252 // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态 252 // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态
253 taskExtMapper.updateByTaskId( 253 taskExtMapper.updateByTaskId(
254 - new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.ADD_SIGN_AFTER.getResult()) 254 + new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.SIGN_AFTER.getResult())
255 .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now())); 255 .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now()));
256 256
257 // 2. 激活子任务 257 // 2. 激活子任务
@@ -265,7 +265,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -265,7 +265,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
265 } 265 }
266 266
267 /** 267 /**
268 - * 处理当前任务的父任务 268 + * 处理当前任务的父任务,主要处理“加签”的情况
269 * 269 *
270 * @param task 当前任务 270 * @param task 当前任务
271 */ 271 */
@@ -274,76 +274,79 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -274,76 +274,79 @@ public class BpmTaskServiceImpl implements BpmTaskService {
274 if (StrUtil.isBlank(parentTaskId)) { 274 if (StrUtil.isBlank(parentTaskId)) {
275 return; 275 return;
276 } 276 }
277 - if (StrUtil.isNotBlank(parentTaskId)) {  
278 - // 1. 判断当前任务的父任务是否还有子任务  
279 - Long childrenTaskCount = getChildrenTaskCount(parentTaskId);  
280 - if (childrenTaskCount > 0) {  
281 - return;  
282 - }  
283 - // 2. 获取父任务  
284 - Task parentTask = validateTaskExist(parentTaskId);  
285 -  
286 - // 3. 情况一:处理向前加签  
287 - String scopeType = parentTask.getScopeType();  
288 - if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) {  
289 - // 3.1 如果是向前加签的任务,则调用 resolveTask 指派父任务,将 owner 重新赋值给父任务的 assignee  
290 - taskService.resolveTask(parentTaskId);  
291 - // 3.2 更新任务拓展表为处理中  
292 - taskExtMapper.updateByTaskId(  
293 - new BpmTaskExtDO().setTaskId(parentTask.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));  
294 - } else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) {  
295 - // 3. 情况二:处理向后加签  
296 - handleAfterSign(parentTask);  
297 - } 277 + // 1. 判断当前任务的父任务是否还有子任务
  278 + Long childrenTaskCount = getChildrenTaskCount(parentTaskId);
  279 + if (childrenTaskCount > 0) {
  280 + return;
  281 + }
  282 + // 2. 获取父任务
  283 + Task parentTask = validateTaskExist(parentTaskId);
298 284
299 - // 4. 子任务已处理完成,清空 scopeType 字段,修改 parentTask 信息,方便后续可以继续向前后向后加签  
300 - // 再查询一次的原因是避免报错:Task was updated by another transaction concurrently  
301 - // 因为前面处理后可能会导致 parentTask rev 字段被修改,需要重新获取最新的  
302 - parentTask = getTask(parentTaskId);  
303 - if (parentTask == null) {  
304 - // 为空的情况是:已经通过 handleAfterSign 方法将任务完成了,所以 ru_task 表会查不到数据  
305 - return;  
306 - }  
307 - clearTaskScopeTypeAndSave(parentTask); 285 + // 3. 处理加签情况
  286 + String scopeType = parentTask.getScopeType();
  287 + if(!validateSignType(scopeType)){
  288 + return;
308 } 289 }
  290 + // 3.1 情况一:处理向前加签
  291 + if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) {
  292 + // 3.1.1 如果是向前加签的任务,则调用 resolveTask 指派父任务,将 owner 重新赋值给父任务的 assignee,这样它就可以被审批
  293 + taskService.resolveTask(parentTaskId);
  294 + // 3.1.2 更新任务拓展表为处理中
  295 + taskExtMapper.updateByTaskId(
  296 + new BpmTaskExtDO().setTaskId(parentTask.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));
  297 + } else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) {
  298 + // 3.2 情况二:处理向后加签
  299 + handleParentTaskForAfterSign(parentTask);
  300 + }
  301 +
  302 + // 4. 子任务已处理完成,清空 scopeType 字段,修改 parentTask 信息,方便后续可以继续向前后向后加签
  303 + // 再查询一次的原因是避免报错:Task was updated by another transaction concurrently
  304 + // 因为前面处理后可能会导致 parentTask rev 字段被修改,需要重新获取最新的
  305 + parentTask = getTask(parentTaskId);
  306 + if (parentTask == null) {
  307 + // 为空的情况是:已经通过 handleAfterSign 方法将任务完成了,所以 ru_task 表会查不到数据
  308 + return;
  309 + }
  310 + clearTaskScopeTypeAndSave(parentTask);
309 } 311 }
310 312
  313 +
311 /** 314 /**
312 * 处理后加签任务 315 * 处理后加签任务
313 * 316 *
314 * @param parentTask 当前审批任务的父任务 317 * @param parentTask 当前审批任务的父任务
315 */ 318 */
316 - private void handleAfterSign(Task parentTask) { 319 + // TODO @海:这个逻辑,怎么感觉可以是 parentTask 的 parent,再去调用 handleParentTask 方法;可以微信聊下;
  320 + private void handleParentTaskForAfterSign(Task parentTask) {
317 String parentTaskId = parentTask.getId(); 321 String parentTaskId = parentTask.getId();
318 - //1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己 322 + // 1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己
319 BpmTaskExtDO currentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId()); 323 BpmTaskExtDO currentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId());
320 - BpmTaskExtDO currentTaskUpdateEntity = new BpmTaskExtDO().setTaskId(parentTask.getId()) 324 + BpmTaskExtDO currentTaskExtUpdateObj = new BpmTaskExtDO().setTaskId(parentTask.getId())
321 .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); 325 .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
322 if (currentTaskExt.getEndTime() == null) { 326 if (currentTaskExt.getEndTime() == null) {
323 // 1.1 有这个判断是因为,以前没设置过结束时间,才去设置 327 // 1.1 有这个判断是因为,以前没设置过结束时间,才去设置
324 - currentTaskUpdateEntity.setEndTime(LocalDateTime.now()); 328 + currentTaskExtUpdateObj.setEndTime(LocalDateTime.now());
325 } 329 }
326 - // 1.2 完成自己  
327 - taskExtMapper.updateByTaskId(currentTaskUpdateEntity); 330 + taskExtMapper.updateByTaskId(currentTaskExtUpdateObj);
  331 + // 1.2 完成自己(因为它已经没有子任务,所以也可以完成)
328 taskService.complete(parentTaskId); 332 taskService.complete(parentTaskId);
329 333
330 // 2. 如果有父级,递归查询上级任务是否都已经完成 334 // 2. 如果有父级,递归查询上级任务是否都已经完成
331 if (StrUtil.isEmpty(parentTask.getParentTaskId())) { 335 if (StrUtil.isEmpty(parentTask.getParentTaskId())) {
332 return; 336 return;
333 } 337 }
334 - // TODO @海:这块待讨论,脑子略乱;感觉 handleAfterSign 的后半段,和 handleParentTask 有点重叠???  
335 // 2.1 判断整条链路的任务是否完成 338 // 2.1 判断整条链路的任务是否完成
336 // 例如从 A 任务加签了一个 B 任务,B 任务又加签了一个 C 任务,C 任务加签了 D 任务 339 // 例如从 A 任务加签了一个 B 任务,B 任务又加签了一个 C 任务,C 任务加签了 D 任务
337 // 此时,D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务 340 // 此时,D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务
338 boolean allChildrenTaskFinish = true; 341 boolean allChildrenTaskFinish = true;
339 while (StrUtil.isNotBlank(parentTask.getParentTaskId())) { 342 while (StrUtil.isNotBlank(parentTask.getParentTaskId())) {
340 parentTask = validateTaskExist(parentTask.getParentTaskId()); 343 parentTask = validateTaskExist(parentTask.getParentTaskId());
341 - BpmTaskExtDO bpmTaskExtDO = taskExtMapper.selectByTaskId(parentTask.getId());  
342 - if (bpmTaskExtDO == null) { 344 + BpmTaskExtDO parentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId());
  345 + if (parentTaskExt == null) {
343 break; 346 break;
344 } 347 }
345 - boolean currentTaskFinish = BpmProcessInstanceResultEnum.isEndResult(bpmTaskExtDO.getResult());  
346 - // 2.2 如果 allChildrenTaskFinish 已经被赋值为 false ,则不会再赋值为 true,因为整个链路没有完成 348 + boolean currentTaskFinish = BpmProcessInstanceResultEnum.isEndResult(parentTaskExt.getResult());
  349 + // 2.2 如果 allChildrenTaskFinish 已经被赋值为 false,则不会再赋值为 true,因为整个链路没有完成
347 if (allChildrenTaskFinish) { 350 if (allChildrenTaskFinish) {
348 allChildrenTaskFinish = currentTaskFinish; 351 allChildrenTaskFinish = currentTaskFinish;
349 } 352 }
@@ -354,19 +357,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -354,19 +357,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
354 357
355 // 3 处理非完成状态的任务 358 // 3 处理非完成状态的任务
356 // 3.1 判断当前任务的父任务是否还有子任务 359 // 3.1 判断当前任务的父任务是否还有子任务
357 - Long childrenTaskCount = getChildrenTaskCount(bpmTaskExtDO.getTaskId()); 360 + Long childrenTaskCount = getChildrenTaskCount(parentTaskExt.getTaskId());
358 if (childrenTaskCount > 0) { 361 if (childrenTaskCount > 0) {
359 continue; 362 continue;
360 } 363 }
361 // 3.2 没有子任务,判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成 364 // 3.2 没有子任务,判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成
362 - if (BpmProcessInstanceResultEnum.ADD_SIGN_BEFORE.getResult().equals(bpmTaskExtDO.getResult())) { 365 + if (BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult().equals(parentTaskExt.getResult())) {
363 // 3.3 需要修改该任务状态为处理中 366 // 3.3 需要修改该任务状态为处理中
364 - taskService.resolveTask(bpmTaskExtDO.getTaskId());  
365 - bpmTaskExtDO.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());  
366 - taskExtMapper.updateByTaskId(bpmTaskExtDO); 367 + taskService.resolveTask(parentTaskExt.getTaskId());
  368 + parentTaskExt.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  369 + taskExtMapper.updateByTaskId(parentTaskExt);
367 } 370 }
368 // 3.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签 371 // 3.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签
369 - parentTask = validateTaskExist(bpmTaskExtDO.getTaskId()); 372 + parentTask = validateTaskExist(parentTaskExt.getTaskId());
370 clearTaskScopeTypeAndSave(parentTask); 373 clearTaskScopeTypeAndSave(parentTask);
371 } 374 }
372 375
@@ -387,7 +390,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -387,7 +390,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
387 taskService.saveTask(task); 390 taskService.saveTask(task);
388 } 391 }
389 392
390 -  
391 /** 393 /**
392 * 获取子任务个数 394 * 获取子任务个数
393 * 395 *
@@ -709,7 +711,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -709,7 +711,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
709 711
710 @Override 712 @Override
711 @Transactional(rollbackFor = Exception.class) 713 @Transactional(rollbackFor = Exception.class)
712 - public void addSignTask(Long userId, BpmTaskAddSignReqVO reqVO) { 714 + public void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO) {
713 // 1. 获取和校验任务 715 // 1. 获取和校验任务
714 TaskEntityImpl taskEntity = validateAddSign(userId, reqVO); 716 TaskEntityImpl taskEntity = validateAddSign(userId, reqVO);
715 List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList()); 717 List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList());
@@ -728,7 +730,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -728,7 +730,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
728 // 2.3 更新扩展表状态 730 // 2.3 更新扩展表状态
729 taskExtMapper.updateByTaskId( 731 taskExtMapper.updateByTaskId(
730 new BpmTaskExtDO().setTaskId(taskEntity.getId()) 732 new BpmTaskExtDO().setTaskId(taskEntity.getId())
731 - .setResult(BpmProcessInstanceResultEnum.ADD_SIGN_BEFORE.getResult()) 733 + .setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult())
732 .setReason(reqVO.getReason())); 734 .setReason(reqVO.getReason()));
733 } 735 }
734 // 2.4 记录加签方式,完成任务时需要用到判断 736 // 2.4 记录加签方式,完成任务时需要用到判断
@@ -737,12 +739,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -737,12 +739,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
737 taskService.saveTask(taskEntity); 739 taskService.saveTask(taskEntity);
738 740
739 // 3. 创建加签任务 741 // 3. 创建加签任务
740 - createAddSignChildrenTasks(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity); 742 + createSignTask(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity);
741 743
742 // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason 744 // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason
743 AdminUserRespDTO currentUser = adminUserApi.getUser(userId); 745 AdminUserRespDTO currentUser = adminUserApi.getUser(userId);
744 - String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getTemplateComment(), currentUser.getNickname(), BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()),  
745 - String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason()); 746 + String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getComment(), currentUser.getNickname(),
  747 + BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()), String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason());
746 taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), 748 taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(),
747 BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment); 749 BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment);
748 } 750 }
@@ -786,7 +788,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -786,7 +788,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
786 * @param addSingUserIdList 被加签的用户 ID 788 * @param addSingUserIdList 被加签的用户 ID
787 * @param taskEntity 被加签的任务 789 * @param taskEntity 被加签的任务
788 */ 790 */
789 - private void createAddSignChildrenTasks(List<String> addSingUserIdList, TaskEntityImpl taskEntity) { 791 + private void createSignTask(List<String> addSingUserIdList, TaskEntityImpl taskEntity) {
790 if (CollUtil.isEmpty(addSingUserIdList)) { 792 if (CollUtil.isEmpty(addSingUserIdList)) {
791 return; 793 return;
792 } 794 }
@@ -795,23 +797,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -795,23 +797,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
795 if (StrUtil.isBlank(addSignId)) { 797 if (StrUtil.isBlank(addSignId)) {
796 continue; 798 continue;
797 } 799 }
798 - createChildrenTask(taskEntity, addSignId); 800 + createSignTask(taskEntity, addSignId);
799 } 801 }
800 } 802 }
801 803
802 /** 804 /**
803 - * 创建子任务 805 + * 创建加签子任务
804 * 806 *
805 * @param parentTask 父任务 807 * @param parentTask 父任务
806 * @param assignee 子任务的执行人 808 * @param assignee 子任务的执行人
807 - * @return  
808 */ 809 */
809 - private void createChildrenTask(TaskEntityImpl parentTask, String assignee) { 810 + private void createSignTask(TaskEntityImpl parentTask, String assignee) {
810 // 1. 生成子任务 811 // 1. 生成子任务
811 TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID()); 812 TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID());
812 task = BpmTaskConvert.INSTANCE.convert(task, parentTask); 813 task = BpmTaskConvert.INSTANCE.convert(task, parentTask);
813 if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { 814 if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) {
814 - // 2.1 前加签,才设置审批人,否则设置 owner 815 + // 2.1 前加签,设置审批人
815 task.setAssignee(assignee); 816 task.setAssignee(assignee);
816 } else { 817 } else {
817 // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 818 // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成
@@ -825,9 +826,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -825,9 +826,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
825 826
826 @Override 827 @Override
827 @Transactional(rollbackFor = Exception.class) 828 @Transactional(rollbackFor = Exception.class)
828 - public void subSignTask(Long userId, BpmTaskSubSignReqVO reqVO) { 829 + public void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO) {
  830 + // 1.1 校验 task 可以被减签
829 Task task = validateSubSign(reqVO.getId()); 831 Task task = validateSubSign(reqVO.getId());
830 - AdminUserRespDTO user = adminUserApi.getUser(userId); 832 + // 1.2 校验取消人存在
831 AdminUserRespDTO cancelUser = null; 833 AdminUserRespDTO cancelUser = null;
832 if (StrUtil.isNotBlank(task.getAssignee())) { 834 if (StrUtil.isNotBlank(task.getAssignee())) {
833 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getAssignee())); 835 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getAssignee()));
@@ -836,20 +838,24 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -836,20 +838,24 @@ public class BpmTaskServiceImpl implements BpmTaskService {
836 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner())); 838 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner()));
837 } 839 }
838 Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误"); 840 Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误");
839 - //1. 获取所有需要删除的任务 ID ,包含当前任务和所有子任务 841 +
  842 + // 2. 删除任务和对应子任务
  843 + // 2.1 获取所有需要删除的任务 ID ,包含当前任务和所有子任务
840 List<String> allTaskIdList = getAllChildTaskIds(task.getId()); 844 List<String> allTaskIdList = getAllChildTaskIds(task.getId());
841 - //2. 删除任务和所有子任务 845 + // 2.2 删除任务和所有子任务
842 taskService.deleteTasks(allTaskIdList); 846 taskService.deleteTasks(allTaskIdList);
843 - //3. 修改扩展表状态为取消 847 + // 2.3 修改扩展表状态为取消
  848 + AdminUserRespDTO user = adminUserApi.getUser(userId);
844 taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()) 849 taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
845 .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname()))); 850 .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname())));
846 - //4.记录日志到父任务中 先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录  
847 - String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getTemplateComment(), user.getNickname(), cancelUser.getNickname()); 851 +
  852 + // 3. 记录日志到父任务中。先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录
  853 + String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname());
848 taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), 854 taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(),
849 BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment); 855 BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment);
850 - //5. 处理当前任务的父任务  
851 - this.handleParentTask(task);  
852 856
  857 + // 4. 处理当前任务的父任务
  858 + handleParentTask(task);
853 } 859 }
854 860
855 /** 861 /**
@@ -860,14 +866,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -860,14 +866,29 @@ public class BpmTaskServiceImpl implements BpmTaskService {
860 */ 866 */
861 private Task validateSubSign(String id) { 867 private Task validateSubSign(String id) {
862 Task task = validateTaskExist(id); 868 Task task = validateTaskExist(id);
863 - //必须有parentId  
864 - if (StrUtil.isEmpty(task.getParentTaskId())) { 869 +
  870 + // 必须有 scopeType
  871 + String scopeType = task.getScopeType();
  872 + if (StrUtil.isEmpty(scopeType)) {
  873 + throw exception(TASK_SUB_SIGN_NO_PARENT);
  874 + }
  875 + // 并且值为 向前和向后加签
  876 + if (!validateSignType(scopeType)) {
865 throw exception(TASK_SUB_SIGN_NO_PARENT); 877 throw exception(TASK_SUB_SIGN_NO_PARENT);
866 } 878 }
867 return task; 879 return task;
868 } 880 }
869 881
870 /** 882 /**
  883 + * 判断当前类型是否为加签
  884 + * @param scopeType 任务的 scopeType
  885 + * @return 当前 scopeType 为加签则返回 true
  886 + */
  887 + private boolean validateSignType(String scopeType){
  888 + return StrUtil.equalsAny(scopeType,BpmTaskAddSignTypeEnum.BEFORE.getType(),scopeType, BpmTaskAddSignTypeEnum.AFTER.getType());
  889 + }
  890 +
  891 + /**
871 * 获取所有要被取消的删除的任务 ID 集合 892 * 获取所有要被取消的删除的任务 ID 集合
872 * 893 *
873 * @param parentTaskId 父级任务ID 894 * @param parentTaskId 父级任务ID
@@ -875,25 +896,40 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -875,25 +896,40 @@ public class BpmTaskServiceImpl implements BpmTaskService {
875 */ 896 */
876 public List<String> getAllChildTaskIds(String parentTaskId) { 897 public List<String> getAllChildTaskIds(String parentTaskId) {
877 List<String> allChildTaskIds = new ArrayList<>(); 898 List<String> allChildTaskIds = new ArrayList<>();
878 - //1. 先将自己放入  
879 - allChildTaskIds.add(parentTaskId);  
880 - //2. 递归获取子级  
881 - recursiveGetChildTaskIds(parentTaskId, allChildTaskIds); 899 + // 1. 递归获取子级
  900 + Stack<String> stack = new Stack<>();
  901 + // 1.1 将根任务ID入栈
  902 + stack.push(parentTaskId);
  903 + //控制遍历的次数不超过 Byte.MAX_VALUE,避免脏数据造成死循环
  904 + int count = 0;
  905 + // TODO @海:< 的前后空格,要注意哈;
  906 + while (!stack.isEmpty() && count<Byte.MAX_VALUE) {
  907 + // 1.2 弹出栈顶任务ID
  908 + String taskId = stack.pop();
  909 + // 1.3 将任务ID添加到结果集合中
  910 + allChildTaskIds.add(taskId);
  911 + // 1.4 获取该任务的子任务列表
  912 + // TODO @海:有个更高效的写法;一次性去 in 一层;不然每个节点,都去查询一次 db, 太浪费了;每次 in,最终就是 O(h) 查询,而不是 O(n) 查询;
  913 + List<String> childrenTaskIdList = getChildrenTaskIdList(taskId);
  914 + if (CollUtil.isNotEmpty(childrenTaskIdList)) {
  915 + for (String childTaskId : childrenTaskIdList) {
  916 + // 1.5 将子任务ID入栈,以便后续处理
  917 + stack.push(childTaskId);
  918 + }
  919 + }
  920 + count++;
  921 + }
882 return allChildTaskIds; 922 return allChildTaskIds;
883 } 923 }
884 924
885 /** 925 /**
886 - * 递归处理子级任务 926 + * 获取指定父级任务的所有子任务 ID 集合
887 * 927 *
888 - * @param taskId 当前任务ID  
889 - * @param taskIds 结果 928 + * @param parentTaskId 父任务 ID
  929 + * @return 所有子任务的 ID 集合
890 */ 930 */
891 - private void recursiveGetChildTaskIds(String taskId, List<String> taskIds) {  
892 - List<String> childrenTaskIdList = getChildrenTaskIdList(taskId);  
893 - for (String childTaskId : childrenTaskIdList) {  
894 - taskIds.add(childTaskId); // 将子任务的ID添加到集合中  
895 - recursiveGetChildTaskIds(childTaskId, taskIds); // 递归获取子任务的子任务  
896 - } 931 + private List<String> getChildrenTaskIdList(String parentTaskId) {
  932 + return convertList(getChildrenTaskList0(parentTaskId), Task::getId);
897 } 933 }
898 934
899 /** 935 /**
@@ -902,33 +938,32 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -902,33 +938,32 @@ public class BpmTaskServiceImpl implements BpmTaskService {
902 * @param parentTaskId 父任务 ID 938 * @param parentTaskId 父任务 ID
903 * @return 所有子任务的 ID 集合 939 * @return 所有子任务的 ID 集合
904 */ 940 */
905 - private List<String> getChildrenTaskIdList(String parentTaskId) { 941 + private List<Task> getChildrenTaskList0(String parentTaskId) {
906 String tableName = managementService.getTableName(TaskEntity.class); 942 String tableName = managementService.getTableName(TaskEntity.class);
907 - String sql = "select ID_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";  
908 - List<Task> childrenTaskList = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list();  
909 - return convertList(childrenTaskList, Task::getId); 943 + // taskService.createTaskQuery() 没有 parentId 参数,所以写 sql 查询
  944 + String sql = "select ID_,OWNER_,ASSIGNEE_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
  945 + return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list();
910 } 946 }
911 947
  948 +
912 @Override 949 @Override
913 - public List<BpmTaskSubSignRespVO> getChildrenTaskList(String taskId) {  
914 - List<String> childrenTaskIdList = getChildrenTaskIdList(taskId);  
915 - if (CollUtil.isEmpty(childrenTaskIdList)) { 950 + public List<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId) {
  951 + // 1. 只查询进行中的任务 后加签的任务,可能不存在 assignee,所以还需要查询 owner
  952 + List<Task> taskList = getChildrenTaskList0(parentId);
  953 + if (CollUtil.isEmpty(taskList)) {
916 return Collections.emptyList(); 954 return Collections.emptyList();
917 } 955 }
918 - //1. 只查询进行中的任务  
919 - List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList);  
920 - //2. 后加签的任务,可能不存在 assignee,所以还需要查询 owner  
921 - List<Task> taskList = taskService.createTaskQuery().taskIds(childrenTaskIdList).list();  
922 - Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId);  
923 - //3. 将 owner 和 assignee 统一到一个集合中  
924 - List<Long> userIds = taskList.stream()  
925 - .flatMap(control ->  
926 - Stream.of(control.getAssignee(), control.getOwner())  
927 - .filter(Objects::nonNull))  
928 - .distinct()  
929 - .map(NumberUtils::parseLong)  
930 - .collect(Collectors.toList()); 956 + List<String> childrenTaskIdList = convertList(taskList, Task::getId);
  957 +
  958 + // 2.1 将 owner 和 assignee 统一到一个集合中
  959 + List<Long> userIds = convertListByFlatMap(taskList, control ->
  960 + Stream.of(NumberUtils.parseLong(control.getAssignee()), NumberUtils.parseLong(control.getOwner()))
  961 + .filter(Objects::nonNull));
  962 + // 2.2 组装数据
931 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); 963 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
932 - return BpmTaskConvert.INSTANCE.convertList(bpmTaskExtDOList, userMap, idTaskMap); 964 + List<BpmTaskExtDO> taskExtList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList);
  965 + Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId);
  966 + return BpmTaskConvert.INSTANCE.convertList(taskExtList, userMap, idTaskMap);
933 } 967 }
  968 +
934 } 969 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java
@@ -147,7 +147,7 @@ public class DatabaseDocController { @@ -147,7 +147,7 @@ public class DatabaseDocController {
147 */ 147 */
148 private static ProcessConfig buildProcessConfig() { 148 private static ProcessConfig buildProcessConfig() {
149 return ProcessConfig.builder() 149 return ProcessConfig.builder()
150 - .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_")) // 忽略表前缀 150 + .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_", "FLW_")) // 忽略表前缀
151 .build(); 151 .build();
152 } 152 }
153 153
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java
@@ -29,8 +29,6 @@ public class SecurityConfiguration { @@ -29,8 +29,6 @@ public class SecurityConfiguration {
29 .antMatchers("/swagger-resources/**").anonymous() 29 .antMatchers("/swagger-resources/**").anonymous()
30 .antMatchers("/webjars/**").anonymous() 30 .antMatchers("/webjars/**").anonymous()
31 .antMatchers("/*/api-docs").anonymous(); 31 .antMatchers("/*/api-docs").anonymous();
32 - // 积木报表  
33 - registry.antMatchers("/jmreport/**").permitAll();  
34 // Spring Boot Actuator 的安全配置 32 // Spring Boot Actuator 的安全配置
35 registry.antMatchers("/actuator").anonymous() 33 registry.antMatchers("/actuator").anonymous()
36 .antMatchers("/actuator/**").anonymous(); 34 .antMatchers("/actuator/**").anonymous();
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/JobLogCleanJob.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/job/JobLogCleanJob.java
1 -package cn.iocoder.yudao.module.infra.job.logger; 1 +package cn.iocoder.yudao.module.infra.job.job;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -33,7 +33,7 @@ public class JobLogCleanJob implements JobHandler { @@ -33,7 +33,7 @@ public class JobLogCleanJob implements JobHandler {
33 @TenantIgnore 33 @TenantIgnore
34 public String execute(String param) { 34 public String execute(String param) {
35 Integer count = jobLogService.cleanJobLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); 35 Integer count = jobLogService.cleanJobLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
36 - log.info("[count][定时执行清理定时任务日志数量 ({}) 个]", count); 36 + log.info("[execute][定时执行清理定时任务日志数量 ({}) 个]", count);
37 return String.format("定时执行清理定时任务日志数量 %s 个", count); 37 return String.format("定时执行清理定时任务日志数量 %s 个", count);
38 } 38 }
39 39
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/job/AccessLogCleanJob.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/AccessLogCleanJob.java
1 -package cn.iocoder.yudao.module.infra.job.job; 1 +package cn.iocoder.yudao.module.infra.job.logger;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -34,7 +34,7 @@ public class AccessLogCleanJob implements JobHandler { @@ -34,7 +34,7 @@ public class AccessLogCleanJob implements JobHandler {
34 @TenantIgnore 34 @TenantIgnore
35 public String execute(String param) { 35 public String execute(String param) {
36 Integer count = apiAccessLogService.cleanAccessLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); 36 Integer count = apiAccessLogService.cleanAccessLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
37 - log.info("[count][定时执行清理访问日志数量 ({}) 个]", count); 37 + log.info("[execute][定时执行清理访问日志数量 ({}) 个]", count);
38 return String.format("定时执行清理错误日志数量 %s 个", count); 38 return String.format("定时执行清理错误日志数量 %s 个", count);
39 } 39 }
40 40
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/job/ErrorLogCleanJob.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/ErrorLogCleanJob.java
1 -package cn.iocoder.yudao.module.infra.job.job; 1 +package cn.iocoder.yudao.module.infra.job.logger;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -34,7 +34,7 @@ public class ErrorLogCleanJob implements JobHandler { @@ -34,7 +34,7 @@ public class ErrorLogCleanJob implements JobHandler {
34 @TenantIgnore 34 @TenantIgnore
35 public String execute(String param) { 35 public String execute(String param) {
36 Integer count = apiErrorLogService.cleanErrorLog(JOB_CLEAN_RETAIN_DAY,DELETE_LIMIT); 36 Integer count = apiErrorLogService.cleanErrorLog(JOB_CLEAN_RETAIN_DAY,DELETE_LIMIT);
37 - log.info("[count][定时执行清理错误日志数量 ({}) 个]", count); 37 + log.info("[execute][定时执行清理错误日志数量 ({}) 个]", count);
38 return String.format("定时执行清理错误日志数量 %s 个", count); 38 return String.format("定时执行清理错误日志数量 %s 个", count);
39 } 39 }
40 40
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
@@ -58,9 +58,9 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -58,9 +58,9 @@ public class FileConfigServiceImpl implements FileConfigService {
58 FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ? 58 FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
59 fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id); 59 fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
60 if (config != null) { 60 if (config != null) {
61 - fileClientFactory.createOrUpdateFileClient(id, config.getStorage(), config.getConfig()); 61 + fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
62 } 62 }
63 - return fileClientFactory.getFileClient(id); 63 + return fileClientFactory.getFileClient(null == config ? id : config.getId());
64 } 64 }
65 65
66 }); 66 });
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/api/api.ts.vm
@@ -28,5 +28,5 @@ export function delete${simpleClassName}(id: number) { @@ -28,5 +28,5 @@ export function delete${simpleClassName}(id: number) {
28 28
29 // 导出${table.classComment} Excel 29 // 导出${table.classComment} Excel
30 export function export${simpleClassName}(params) { 30 export function export${simpleClassName}(params) {
31 - return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls') 31 + return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls')
32 } 32 }
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm
1 -import type { BasicColumn, FormSchema } from '@/components/Table'  
2 -import { useRender } from '@/components/Table'  
3 -import { DICT_TYPE, getDictOptions } from '@/utils/dict' 1 +import type {BasicColumn, FormSchema} from '@/components/Table'
  2 +import {useRender} from '@/components/Table'
  3 +import {DICT_TYPE, getDictOptions} from '@/utils/dict'
4 4
5 export const columns: BasicColumn[] = [ 5 export const columns: BasicColumn[] = [
6 #foreach($column in $columns) 6 #foreach($column in $columns)
@@ -50,7 +50,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -50,7 +50,7 @@ export const searchFormSchema: FormSchema[] = [
50 field: '${javaField}', 50 field: '${javaField}',
51 #if ($column.htmlType == "input") 51 #if ($column.htmlType == "input")
52 component: 'Input', 52 component: 'Input',
53 - #elseif ($column.htmlType == "select" || $column.htmlType == "radio") 53 + #elseif ($column.htmlType == "select")
54 component: 'Select', 54 component: 'Select',
55 componentProps: { 55 componentProps: {
56 #if ("" != $dictType)## 设置了 dictType 数据字典的情况 56 #if ("" != $dictType)## 设置了 dictType 数据字典的情况
@@ -59,6 +59,15 @@ export const searchFormSchema: FormSchema[] = [ @@ -59,6 +59,15 @@ export const searchFormSchema: FormSchema[] = [
59 options: [], 59 options: [],
60 #end 60 #end
61 }, 61 },
  62 + #elseif ($column.htmlType == "radio")
  63 + component: 'Radio',
  64 + componentProps: {
  65 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  66 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase()),
  67 + #else## 未设置 dictType 数据字典的情况
  68 + options: [],
  69 + #end
  70 + },
62 #elseif($column.htmlType == "datetime") 71 #elseif($column.htmlType == "datetime")
63 component: 'RangePicker', 72 component: 'RangePicker',
64 #end 73 #end
@@ -181,7 +190,8 @@ export const updateFormSchema: FormSchema[] = [ @@ -181,7 +190,8 @@ export const updateFormSchema: FormSchema[] = [
181 fileType: 'file', 190 fileType: 'file',
182 maxCount: 1, 191 maxCount: 1,
183 }, 192 },
184 - #elseif($column.htmlType == "editor")## 文本编辑器component: 'Editor', 193 + #elseif($column.htmlType == "editor")## 文本编辑器
  194 + component: 'Editor',
185 #elseif($column.htmlType == "select")## 下拉框 195 #elseif($column.htmlType == "select")## 下拉框
186 component: 'Select', 196 component: 'Select',
187 componentProps: { 197 componentProps: {
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/index.vue.vm
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 -import ${ simpleClassName }Modal from './${simpleClassName}Modal.vue' 2 +import ${simpleClassName}Modal from './${simpleClassName}Modal.vue'
3 import { columns, searchFormSchema } from './${classNameVar}.data' 3 import { columns, searchFormSchema } from './${classNameVar}.data'
4 import { useI18n } from '@/hooks/web/useI18n' 4 import { useI18n } from '@/hooks/web/useI18n'
5 import { useMessage } from '@/hooks/web/useMessage' 5 import { useMessage } from '@/hooks/web/useMessage'
6 import { useModal } from '@/components/Modal' 6 import { useModal } from '@/components/Modal'
7 -import { IconEnum } from '@/enums/appEnum'  
8 -import { BasicTable, useTable, TableAction } from '@/components/Table'  
9 -import { delete${ simpleClassName }, export${ simpleClassName }, get${ simpleClassName } Page } from '@/api/${table.moduleName}/${classNameVar}' 7 +import { useTable } from '@/components/Table'
  8 +import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${classNameVar}'
10 9
11 defineOptions({ name: '${table.className}' }) 10 defineOptions({ name: '${table.className}' })
12 11
@@ -16,7 +15,7 @@ const [registerModal, { openModal }] = useModal() @@ -16,7 +15,7 @@ const [registerModal, { openModal }] = useModal()
16 15
17 const [registerTable, { getForm, reload }] = useTable({ 16 const [registerTable, { getForm, reload }] = useTable({
18 title: '${table.classComment}列表', 17 title: '${table.classComment}列表',
19 - api: get${ simpleClassName }Page, 18 + api: get${simpleClassName}Page,
20 columns, 19 columns,
21 formConfig: { labelWidth: 120, schemas: searchFormSchema }, 20 formConfig: { labelWidth: 120, schemas: searchFormSchema },
22 useSearchForm: true, 21 useSearchForm: true,
@@ -43,14 +42,14 @@ async function handleExport() { @@ -43,14 +42,14 @@ async function handleExport() {
43 iconType: 'warning', 42 iconType: 'warning',
44 content: t('common.exportMessage'), 43 content: t('common.exportMessage'),
45 async onOk() { 44 async onOk() {
46 - await export${ simpleClassName } (getForm().getFieldsValue()) 45 + await export${simpleClassName}(getForm().getFieldsValue())
47 createMessage.success(t('common.exportSuccessText')) 46 createMessage.success(t('common.exportSuccessText'))
48 }, 47 },
49 }) 48 })
50 } 49 }
51 50
52 async function handleDelete(record: Recordable) { 51 async function handleDelete(record: Recordable) {
53 - await delete${ simpleClassName } (record.id) 52 + await delete${simpleClassName}(record.id)
54 createMessage.success(t('common.delSuccessText')) 53 createMessage.success(t('common.delSuccessText'))
55 reload() 54 reload()
56 } 55 }
@@ -62,7 +61,7 @@ async function handleDelete(record: Recordable) { @@ -62,7 +61,7 @@ async function handleDelete(record: Recordable) {
62 <a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate"> 61 <a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate">
63 {{ t('action.create') }} 62 {{ t('action.create') }}
64 </a-button> 63 </a-button>
65 - <a-button type="warning" v-auth="['${permissionPrefix}:export']" :preIcon="IconEnum.EXPORT" @click="handleExport"> 64 + <a-button v-auth="['${permissionPrefix}:export']" :preIcon="IconEnum.EXPORT" @click="handleExport">
66 {{ t('action.export') }} 65 {{ t('action.export') }}
67 </a-button> 66 </a-button>
68 </template> 67 </template>
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
@@ -258,12 +258,12 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -258,12 +258,12 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
258 Long id = fileConfig.getId(); 258 Long id = fileConfig.getId();
259 // mock 获得 Client 259 // mock 获得 Client
260 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig()); 260 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
261 - when(fileClientFactory.getFileClient(eq(0L))).thenReturn(fileClient); 261 + when(fileClientFactory.getFileClient(eq(fileConfig.getId()))).thenReturn(fileClient);
262 262
263 // 调用,并断言 263 // 调用,并断言
264 assertSame(fileClient, fileConfigService.getMasterFileClient()); 264 assertSame(fileClient, fileConfigService.getMasterFileClient());
265 // 断言缓存 265 // 断言缓存
266 - verify(fileClientFactory).createOrUpdateFileClient(eq(0L), eq(fileConfig.getStorage()), 266 + verify(fileClientFactory).createOrUpdateFileClient(eq(fileConfig.getId()), eq(fileConfig.getStorage()),
267 eq(fileConfig.getConfig())); 267 eq(fileConfig.getConfig()));
268 } 268 }
269 269
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.api.comment.dto; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.api.comment.dto;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
  5 +import javax.validation.constraints.NotNull;
5 import java.util.List; 6 import java.util.List;
6 7
7 /** 8 /**
@@ -15,6 +16,7 @@ public class ProductCommentCreateReqDTO { @@ -15,6 +16,7 @@ public class ProductCommentCreateReqDTO {
15 /** 16 /**
16 * 商品 SKU 编号 17 * 商品 SKU 编号
17 */ 18 */
  19 + @NotNull(message = "商品 SKU 编号不能为空")
18 private Long skuId; 20 private Long skuId;
19 /** 21 /**
20 * 订单编号 22 * 订单编号
@@ -26,20 +28,19 @@ public class ProductCommentCreateReqDTO { @@ -26,20 +28,19 @@ public class ProductCommentCreateReqDTO {
26 private Long orderItemId; 28 private Long orderItemId;
27 29
28 /** 30 /**
29 - * 评分星级 1-5 分  
30 - */  
31 - private Integer scores;  
32 - /**  
33 * 描述星级 1-5 分 31 * 描述星级 1-5 分
34 */ 32 */
  33 + @NotNull(message = "描述星级不能为空")
35 private Integer descriptionScores; 34 private Integer descriptionScores;
36 /** 35 /**
37 * 服务星级 1-5 分 36 * 服务星级 1-5 分
38 */ 37 */
  38 + @NotNull(message = "服务星级不能为空")
39 private Integer benefitScores; 39 private Integer benefitScores;
40 /** 40 /**
41 * 评论内容 41 * 评论内容
42 */ 42 */
  43 + @NotNull(message = "评论内容不能为空")
43 private String content; 44 private String content;
44 /** 45 /**
45 * 评论图片地址数组,以逗号分隔最多上传 9 张 46 * 评论图片地址数组,以逗号分隔最多上传 9 张
@@ -49,11 +50,12 @@ public class ProductCommentCreateReqDTO { @@ -49,11 +50,12 @@ public class ProductCommentCreateReqDTO {
49 /** 50 /**
50 * 是否匿名 51 * 是否匿名
51 */ 52 */
  53 + @NotNull(message = "是否匿名不能为空")
52 private Boolean anonymous; 54 private Boolean anonymous;
53 /** 55 /**
54 * 评价人 56 * 评价人
55 */ 57 */
  58 + @NotNull(message = "评价人不能为空")
56 private Long userId; 59 private Long userId;
57 60
58 -  
59 } 61 }
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java deleted
1 -package cn.iocoder.yudao.module.product.api.property;  
2 -  
3 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
4 -  
5 -import java.util.Collection;  
6 -import java.util.List;  
7 -  
8 -/**  
9 - * 商品属性值 API 接口  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -public interface ProductPropertyValueApi {  
14 -  
15 - /**  
16 - * 根据编号数组,获得属性值列表  
17 - *  
18 - * @param ids 编号数组  
19 - * @return 属性值明细列表  
20 - */  
21 - List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids);  
22 -  
23 -}  
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
@@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu.dto; @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu.dto;
3 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; 3 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 -import java.util.List;  
7 -  
8 // TODO @LeeYan9: ProductSpuRespDTO 6 // TODO @LeeYan9: ProductSpuRespDTO
9 /** 7 /**
10 * 商品 SPU 信息 Response DTO 8 * 商品 SPU 信息 Response DTO
@@ -27,55 +25,22 @@ public class ProductSpuRespDTO { @@ -27,55 +25,22 @@ public class ProductSpuRespDTO {
27 */ 25 */
28 private String name; 26 private String name;
29 /** 27 /**
30 - * 关键字  
31 - */  
32 - private String keyword;  
33 - /**  
34 * 单位 28 * 单位
35 * 29 *
36 * 对应 product_unit 数据字典 30 * 对应 product_unit 数据字典
37 */ 31 */
38 private Integer unit; 32 private Integer unit;
39 - /**  
40 - * 商品简介  
41 - */  
42 - private String introduction;  
43 - /**  
44 - * 商品详情  
45 - */  
46 - private String description;  
47 - // TODO @芋艿:是不是要删除  
48 - /**  
49 - * 商品条码(一维码)  
50 - */  
51 - private String barCode;  
52 33
53 /** 34 /**
54 * 商品分类编号 35 * 商品分类编号
55 */ 36 */
56 private Long categoryId; 37 private Long categoryId;
57 /** 38 /**
58 - * 商品品牌编号  
59 - */  
60 - private Long brandId;  
61 - /**  
62 * 商品封面图 39 * 商品封面图
63 */ 40 */
64 private String picUrl; 41 private String picUrl;
65 - /**  
66 - * 商品轮播图  
67 - */  
68 - private List<String> sliderPicUrls;  
69 - /**  
70 - * 商品视频  
71 - */  
72 - private String videoUrl;  
73 42
74 /** 43 /**
75 - * 排序字段  
76 - */  
77 - private Integer sort;  
78 - /**  
79 * 商品状态 44 * 商品状态
80 * <p> 45 * <p>
81 * 枚举 {@link ProductSpuStatusEnum} 46 * 枚举 {@link ProductSpuStatusEnum}
@@ -124,22 +89,6 @@ public class ProductSpuRespDTO { @@ -124,22 +89,6 @@ public class ProductSpuRespDTO {
124 */ 89 */
125 private Integer giveIntegral; 90 private Integer giveIntegral;
126 91
127 - // ========== 统计相关字段 =========  
128 -  
129 - /**  
130 - * 商品销量  
131 - */  
132 - private Integer salesCount;  
133 - /**  
134 - * 虚拟销量  
135 - */  
136 - private Integer virtualSalesCount;  
137 - /**  
138 - * 商品点击量  
139 - */  
140 - private Integer clickCount;  
141 -  
142 -  
143 // ========== 分销相关字段 ========= 92 // ========== 分销相关字段 =========
144 93
145 /** 94 /**
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/group/ProductGroupStyleEnum.java deleted
1 -package cn.iocoder.yudao.module.product.enums.group;  
2 -  
3 -import cn.iocoder.yudao.framework.common.core.IntArrayValuable;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Getter;  
6 -  
7 -import java.util.Arrays;  
8 -  
9 -/**  
10 - * 商品分组的样式枚举  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@Getter  
15 -@AllArgsConstructor  
16 -public enum ProductGroupStyleEnum implements IntArrayValuable {  
17 -  
18 - ONE(1, "每列一个"),  
19 - TWO(2, "每列两个"),  
20 - THREE(2, "每列三个"),;  
21 -  
22 - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductGroupStyleEnum::getStyle).toArray();  
23 -  
24 - /**  
25 - * 列表样式  
26 - */  
27 - private final Integer style;  
28 - /**  
29 - * 状态名  
30 - */  
31 - private final String name;  
32 -  
33 - @Override  
34 - public int[] array() {  
35 - return ARRAYS;  
36 - }  
37 -  
38 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java deleted
1 -package cn.iocoder.yudao.module.product.api.property;  
2 -  
3 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
4 -import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;  
5 -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;  
6 -import org.springframework.stereotype.Service;  
7 -import org.springframework.validation.annotation.Validated;  
8 -  
9 -import javax.annotation.Resource;  
10 -import java.util.Collection;  
11 -import java.util.List;  
12 -  
13 -/**  
14 - * 商品属性值 API 实现类  
15 - *  
16 - * @author 芋道源码  
17 - */  
18 -@Service  
19 -@Validated  
20 -public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {  
21 -  
22 - @Resource  
23 - private ProductPropertyValueService productPropertyValueService;  
24 -  
25 - @Override  
26 - public List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids) {  
27 - return ProductPropertyValueConvert.INSTANCE.convertList02(  
28 - productPropertyValueService.getPropertyValueDetailList(ids));  
29 - }  
30 -  
31 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
1 package cn.iocoder.yudao.module.product.api.sku; 1 package cn.iocoder.yudao.module.product.api.sku;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
5 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 4 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
6 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; 5 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
@@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated; @@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated;
11 10
12 import javax.annotation.Resource; 11 import javax.annotation.Resource;
13 import java.util.Collection; 12 import java.util.Collection;
14 -import java.util.Collections;  
15 import java.util.List; 13 import java.util.List;
16 14
17 /** 15 /**
@@ -35,18 +33,12 @@ public class ProductSkuApiImpl implements ProductSkuApi { @@ -35,18 +33,12 @@ public class ProductSkuApiImpl implements ProductSkuApi {
35 33
36 @Override 34 @Override
37 public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) { 35 public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) {
38 - if (CollUtil.isEmpty(ids)) {  
39 - return Collections.emptyList();  
40 - }  
41 List<ProductSkuDO> skus = productSkuService.getSkuList(ids); 36 List<ProductSkuDO> skus = productSkuService.getSkuList(ids);
42 return ProductSkuConvert.INSTANCE.convertList04(skus); 37 return ProductSkuConvert.INSTANCE.convertList04(skus);
43 } 38 }
44 39
45 @Override 40 @Override
46 public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) { 41 public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
47 - if (CollUtil.isEmpty(spuIds)) {  
48 - return Collections.emptyList();  
49 - }  
50 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds); 42 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
51 return ProductSkuConvert.INSTANCE.convertList04(skus); 43 return ProductSkuConvert.INSTANCE.convertList04(skus);
52 } 44 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
@@ -27,9 +27,6 @@ public class ProductSpuApiImpl implements ProductSpuApi { @@ -27,9 +27,6 @@ public class ProductSpuApiImpl implements ProductSpuApi {
27 27
28 @Override 28 @Override
29 public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) { 29 public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
30 - if (CollectionUtil.isEmpty(ids)) {  
31 - return Collections.emptyList();  
32 - }  
33 return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids)); 30 return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
34 } 31 }
35 32
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyValueConvert.java
1 package cn.iocoder.yudao.module.product.convert.property; 1 package cn.iocoder.yudao.module.product.convert.property;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
5 -import cn.iocoder.yudao.framework.common.util.collection.MapUtils;  
6 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
8 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
9 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
10 -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;  
11 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
12 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
13 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
14 import org.mapstruct.factory.Mappers; 9 import org.mapstruct.factory.Mappers;
15 10
16 import java.util.List; 11 import java.util.List;
17 -import java.util.Map;  
18 -  
19 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
20 12
21 /** 13 /**
22 * 属性值 Convert 14 * 属性值 Convert
@@ -38,18 +30,4 @@ public interface ProductPropertyValueConvert { @@ -38,18 +30,4 @@ public interface ProductPropertyValueConvert {
38 30
39 PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page); 31 PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page);
40 32
41 - default List<ProductPropertyValueDetailRespBO> convertList(List<ProductPropertyValueDO> values, List<ProductPropertyDO> keys) {  
42 - Map<Long, ProductPropertyDO> keyMap = convertMap(keys, ProductPropertyDO::getId);  
43 - return CollectionUtils.convertList(values, value -> {  
44 - ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()  
45 - .setValueId(value.getId()).setValueName(value.getName());  
46 - // 设置属性项  
47 - MapUtils.findAndThen(keyMap, value.getPropertyId(),  
48 - key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));  
49 - return valueDetail;  
50 - });  
51 - }  
52 -  
53 - List<ProductPropertyValueDetailRespDTO> convertList02(List<ProductPropertyValueDetailRespBO> list);  
54 -  
55 } 33 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc @@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
8 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
9 8
10 import java.util.Collection; 9 import java.util.Collection;
11 import java.util.List; 10 import java.util.List;
@@ -57,14 +56,6 @@ public interface ProductPropertyValueService { @@ -57,14 +56,6 @@ public interface ProductPropertyValueService {
57 List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds); 56 List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds);
58 57
59 /** 58 /**
60 - * 根据编号数组,获得属性值列表  
61 - *  
62 - * @param ids 编号数组  
63 - * @return 属性值明细列表  
64 - */  
65 - List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids);  
66 -  
67 - /**  
68 * 根据属性项编号,活的属性值数量 59 * 根据属性项编号,活的属性值数量
69 * 60 *
70 * @param propertyId 属性项编号数 61 * @param propertyId 属性项编号数
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
1 package cn.iocoder.yudao.module.product.service.property; 1 package cn.iocoder.yudao.module.product.service.property;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
8 import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert; 7 import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
9 -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;  
10 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 8 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
11 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; 9 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
12 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
13 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 10 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
14 import org.springframework.context.annotation.Lazy; 11 import org.springframework.context.annotation.Lazy;
15 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
@@ -17,11 +14,9 @@ import org.springframework.validation.annotation.Validated; @@ -17,11 +14,9 @@ import org.springframework.validation.annotation.Validated;
17 14
18 import javax.annotation.Resource; 15 import javax.annotation.Resource;
19 import java.util.Collection; 16 import java.util.Collection;
20 -import java.util.Collections;  
21 import java.util.List; 17 import java.util.List;
22 18
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
25 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS; 20 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS;
26 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS; 21 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS;
27 22
@@ -100,23 +95,6 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ @@ -100,23 +95,6 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
100 } 95 }
101 96
102 @Override 97 @Override
103 - public List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids) {  
104 - // 获得属性值列表  
105 - if (CollUtil.isEmpty(ids)) {  
106 - return Collections.emptyList();  
107 - }  
108 - List<ProductPropertyValueDO> values = productPropertyValueMapper.selectBatchIds(ids);  
109 - if (CollUtil.isEmpty(values)) {  
110 - return Collections.emptyList();  
111 - }  
112 - // 获得属性项列表  
113 - List<ProductPropertyDO> keys = productPropertyService.getPropertyList(  
114 - convertSet(values, ProductPropertyValueDO::getPropertyId));  
115 - // 组装明细  
116 - return ProductPropertyValueConvert.INSTANCE.convertList(values, keys);  
117 - }  
118 -  
119 - @Override  
120 public Integer getPropertyValueCountByPropertyId(Long propertyId) { 98 public Integer getPropertyValueCountByPropertyId(Long propertyId) {
121 return productPropertyValueMapper.selectCountByPropertyId(propertyId); 99 return productPropertyValueMapper.selectCountByPropertyId(propertyId);
122 } 100 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java deleted
1 -package cn.iocoder.yudao.module.product.service.property.bo;  
2 -  
3 -import lombok.Data;  
4 -  
5 -/**  
6 - * 商品属性项的明细 Response BO  
7 - *  
8 - * @author 芋道源码  
9 - */  
10 -@Data  
11 -public class ProductPropertyValueDetailRespBO {  
12 -  
13 - /**  
14 - * 属性的编号  
15 - */  
16 - private Long propertyId;  
17 -  
18 - /**  
19 - * 属性的名称  
20 - */  
21 - private String propertyName;  
22 -  
23 - /**  
24 - * 属性值的编号  
25 - */  
26 - private Long valueId;  
27 -  
28 - /**  
29 - * 属性值的名称  
30 - */  
31 - private String valueName;  
32 -  
33 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -153,6 +153,9 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -153,6 +153,9 @@ public class ProductSkuServiceImpl implements ProductSkuService {
153 153
154 @Override 154 @Override
155 public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) { 155 public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) {
  156 + if (CollUtil.isEmpty(spuIds)) {
  157 + return Collections.emptyList();
  158 + }
156 return productSkuMapper.selectListBySpuId(spuIds); 159 return productSkuMapper.selectListBySpuId(spuIds);
157 } 160 }
158 161
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -188,6 +188,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -188,6 +188,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
188 188
189 @Override 189 @Override
190 public List<ProductSpuDO> getSpuList(Collection<Long> ids) { 190 public List<ProductSpuDO> getSpuList(Collection<Long> ids) {
  191 + if (CollUtil.isEmpty(ids)) {
  192 + return Collections.emptyList();
  193 + }
191 return productSpuMapper.selectBatchIds(ids); 194 return productSpuMapper.selectBatchIds(ids);
192 } 195 }
193 196
yudao-module-mall/yudao-module-promotion-api/pom.xml
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 13
14 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
15 <description> 15 <description>
16 - market 模块 API,暴露给其它模块调用 16 + promotion 模块 API,暴露给其它模块调用
17 </description> 17 </description>
18 18
19 <dependencies> 19 <dependencies>
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.combination;  
2 -  
3 -/**  
4 - * 拼团活动 Api 接口  
5 - *  
6 - * @author HUIHUI  
7 - */  
8 -public interface CombinationActivityApi {  
9 -  
10 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
@@ -42,14 +42,6 @@ public interface CombinationRecordApi { @@ -42,14 +42,6 @@ public interface CombinationRecordApi {
42 boolean isCombinationRecordSuccess(Long userId, Long orderId); 42 boolean isCombinationRecordSuccess(Long userId, Long orderId);
43 43
44 /** 44 /**
45 - * 更新拼团状态为【失败】  
46 - *  
47 - * @param userId 用户编号  
48 - * @param orderId 订单编号  
49 - */  
50 - void updateRecordStatusToFailed(Long userId, Long orderId);  
51 -  
52 - /**  
53 * 【下单前】校验是否满足拼团活动条件 45 * 【下单前】校验是否满足拼团活动条件
54 * 46 *
55 * 如果校验失败,则抛出业务异常 47 * 如果校验失败,则抛出业务异常
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/PriceApi.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
4 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
5 -  
6 -/**  
7 - * 价格 API 接口  
8 - *  
9 - * @author 芋道源码  
10 - */  
11 -public interface PriceApi {  
12 -  
13 - /**  
14 - * 计算商品的价格  
15 - *  
16 - * @param calculateReqDTO 价格请求  
17 - * @return 价格相应  
18 - */  
19 - PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO);  
20 -  
21 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/CouponMeetRespDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -/**  
6 - * 优惠劵的匹配信息 Response DTO  
7 - *  
8 - * why 放在 price 包下?主要获取的时候,需要涉及到较多的价格计算逻辑,放在 price 可以更好的复用逻辑  
9 - *  
10 - * @author 芋道源码  
11 - */  
12 -@Data  
13 -public class CouponMeetRespDTO {  
14 -  
15 - /**  
16 - * 优惠劵编号  
17 - */  
18 - private Long id;  
19 -  
20 - // ========== 非优惠劵的基本信息字段 ==========  
21 - /**  
22 - * 是否匹配  
23 - */  
24 - private Boolean meet;  
25 - /**  
26 - * 不匹配的提示,即 {@link #meet} = true 才有值  
27 - *  
28 - * 例如说:  
29 - * 1. 所结算商品没有符合条件的商品  
30 - * 2. 差 XXX 元可用优惠劵  
31 - * 3. 优惠劵未到使用时间  
32 - */  
33 - private String meetTip;  
34 -  
35 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import javax.validation.constraints.Min;  
6 -import javax.validation.constraints.NotNull;  
7 -import java.util.List;  
8 -  
9 -/**  
10 - * 价格计算 Request DTO  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@Data  
15 -@Deprecated  
16 -public class PriceCalculateReqDTO {  
17 -  
18 - /**  
19 - * 用户编号  
20 - *  
21 - * 对应 MemberUserDO 的 id 编号  
22 - */  
23 - private Long userId;  
24 -  
25 - /**  
26 - * 优惠劵编号  
27 - */  
28 - private Long couponId;  
29 -  
30 - /**  
31 - * 收货地址编号  
32 - */  
33 - private Long addressId;  
34 -  
35 - /**  
36 - * 商品 SKU 数组  
37 - */  
38 - @NotNull(message = "商品数组不能为空")  
39 - private List<Item> items;  
40 -  
41 - /**  
42 - * 商品 SKU  
43 - */  
44 - @Data  
45 - public static class Item {  
46 -  
47 - /**  
48 - * SKU 编号  
49 - */  
50 - @NotNull(message = "商品 SKU 编号不能为空")  
51 - private Long skuId;  
52 -  
53 - /**  
54 - * SKU 数量  
55 - */  
56 - @NotNull(message = "商品 SKU 数量不能为空")  
57 - @Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") // 可传递 0 数量,用于购物车未选中的情况  
58 - private Integer count;  
59 -  
60 - }  
61 -  
62 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price.dto;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;  
4 -import lombok.Data;  
5 -  
6 -import java.util.List;  
7 -  
8 -/**  
9 - * 价格计算 Response DTO  
10 - *  
11 - * 整体设计,参考 taobao 的技术文档:  
12 - * 1. <a href="https://developer.alibaba.com/docs/doc.htm?treeId=1&articleId=1029&docType=1">订单管理</a>  
13 - * 2. <a href="https://open.taobao.com/docV3.htm?docId=108471&docType=1">常用订单金额说明</a>  
14 - *  
15 - * 举个例子:<a href="https://img.alicdn.com/top/i1/LB1mALAi4HI8KJjy1zbXXaxdpXa">订单图</a>  
16 - * 输入:  
17 - * 1. 订单实付: trade.payment = 198.00;订单邮费:5 元;  
18 - * 2. 商品级优惠 圣诞价: 省 29.00 元 和 圣诞价:省 150.00 元; 订单级优惠,圣诞 2:省 5.00 元;  
19 - * 分摊:  
20 - * 1. 商品 1:原价 108 元,优惠 29 元,子订单实付 79 元,分摊主订单优惠 1.99 元;  
21 - * 2. 商品 2:原价 269 元,优惠 150 元,子订单实付 119 元,分摊主订单优惠 3.01 元;  
22 - *  
23 - * @author 芋道源码  
24 - */  
25 -@Data  
26 -@Deprecated  
27 -public class PriceCalculateRespDTO {  
28 -  
29 - /**  
30 - * 订单  
31 - */  
32 - private Order order;  
33 -  
34 - /**  
35 - * 营销活动数组  
36 - *  
37 - * 只对应 {@link Order#items} 商品匹配的活动  
38 - */  
39 - private List<Promotion> promotions;  
40 -  
41 - // TODO @芋艿:需要改造下,主要是价格字段  
42 - /**  
43 - * 订单  
44 - */  
45 - @Data  
46 - public static class Order {  
47 -  
48 - /**  
49 - * 商品原价(总),单位:分  
50 - *  
51 - * 基于 {@link OrderItem#getOriginalPrice()} 求和  
52 - *  
53 - * 对应 taobao 的 trade.total_fee 字段  
54 - */  
55 - private Integer totalPrice;  
56 - /**  
57 - * 订单优惠(总),单位:分  
58 - *  
59 - * 订单级优惠:对主订单的优惠,常见如:订单满 200 元减 10 元;订单满 80 包邮。  
60 - *  
61 - * 对应 taobao 的 order.discount_fee 字段  
62 - */  
63 - private Integer discountPrice;  
64 - /**  
65 - * 优惠劵减免金额(总),单位:分  
66 - *  
67 - * 对应 taobao 的 trade.coupon_fee 字段  
68 - */  
69 - private Integer couponPrice;  
70 - /**  
71 - * 积分减免金额(总),单位:分  
72 - *  
73 - * 对应 taobao 的 trade.point_fee 字段  
74 - */  
75 - private Integer pointPrice;  
76 - /**  
77 - * 运费金额,单位:分  
78 - */  
79 - private Integer deliveryPrice;  
80 - /**  
81 - * 最终购买金额(总),单位:分  
82 - *  
83 - * = {@link OrderItem#getPayPrice()} 求和  
84 - * - {@link #couponPrice}  
85 - * - {@link #pointPrice}  
86 - * + {@link #deliveryPrice}  
87 - * - {@link #discountPrice}  
88 - */  
89 - private Integer payPrice;  
90 - /**  
91 - * 商品 SKU 数组  
92 - */  
93 - private List<OrderItem> items;  
94 -  
95 - // ========== 营销基本信息 ==========  
96 - /**  
97 - * 优惠劵编号  
98 - */  
99 - private Long couponId;  
100 -  
101 - }  
102 -  
103 - /**  
104 - * 订单商品 SKU  
105 - */  
106 - @Data  
107 - public static class OrderItem {  
108 -  
109 - /**  
110 - * SPU 编号  
111 - */  
112 - private Long spuId;  
113 - /**  
114 - * SKU 编号  
115 - */  
116 - private Long skuId;  
117 - /**  
118 - * 购买数量  
119 - */  
120 - private Integer count;  
121 -  
122 - /**  
123 - * 商品原价(总),单位:分  
124 - *  
125 - * = {@link #originalUnitPrice} * {@link #getCount()}  
126 - */  
127 - private Integer originalPrice;  
128 - /**  
129 - * 商品原价(单),单位:分  
130 - *  
131 - * 对应 ProductSkuDO 的 price 字段  
132 - * 对应 taobao 的 order.price 字段  
133 - */  
134 - private Integer originalUnitPrice;  
135 - /**  
136 - * 商品优惠(总),单位:分  
137 - *  
138 - * 商品级优惠:对单个商品的,常见如:商品原价的 8 折;商品原价的减 50 元  
139 - *  
140 - * 对应 taobao 的 order.discount_fee 字段  
141 - */  
142 - private Integer discountPrice;  
143 - /**  
144 - * 子订单实付金额,不算主订单分摊金额,单位:分  
145 - *  
146 - * = {@link #originalPrice}  
147 - * - {@link #discountPrice}  
148 - *  
149 - * 对应 taobao 的 order.payment 字段  
150 - */  
151 - private Integer payPrice;  
152 -  
153 - /**  
154 - * 子订单分摊金额(总),单位:分  
155 - * 需要分摊 {@link Order#discountPrice}、{@link Order#couponPrice}、{@link Order#pointPrice}  
156 - *  
157 - * 对应 taobao 的 order.part_mjz_discount 字段  
158 - * 淘宝说明:子订单分摊优惠基础逻辑:一般正常优惠券和满减优惠按照子订单的金额进行分摊,特殊情况如果优惠券是指定商品使用的,只会分摊到对应商品子订单上不分摊。  
159 - */  
160 - private Integer orderPartPrice;  
161 - /**  
162 - * 分摊后子订单实付金额(总),单位:分  
163 - *  
164 - * = {@link #payPrice}  
165 - * - {@link #orderPartPrice}  
166 - *  
167 - * 对应 taobao 的 divide_order_fee 字段  
168 - */  
169 - private Integer orderDividePrice;  
170 -  
171 - }  
172 -  
173 - /**  
174 - * 营销明细  
175 - */  
176 - @Data  
177 - @Deprecated  
178 - public static class Promotion {  
179 -  
180 - /**  
181 - * 营销编号  
182 - *  
183 - * 例如说:营销活动的编号、优惠劵的编号  
184 - */  
185 - private Long id;  
186 - /**  
187 - * 营销名字  
188 - */  
189 - private String name;  
190 - /**  
191 - * 营销类型  
192 - *  
193 - * 枚举 {@link PromotionTypeEnum}  
194 - */  
195 - private Integer type;  
196 - /**  
197 - * 营销级别  
198 - *  
199 - * 枚举 @link PromotionLevelEnum} TODO PromotionLevelEnum 没有这个枚举类  
200 - */  
201 - private Integer level;  
202 - /**  
203 - * 计算时的原价(总),单位:分  
204 - */  
205 - private Integer totalPrice;  
206 - /**  
207 - * 计算时的优惠(总),单位:分  
208 - */  
209 - private Integer discountPrice;  
210 - /**  
211 - * 匹配的商品 SKU 数组  
212 - */  
213 - private List<PromotionItem> items;  
214 -  
215 - // ========== 匹配情况 ==========  
216 -  
217 - /**  
218 - * 是否满足优惠条件  
219 - */  
220 - private Boolean match;  
221 - /**  
222 - * 满足条件的提示  
223 - *  
224 - * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元”  
225 - * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元”  
226 - */  
227 - private String description;  
228 -  
229 - }  
230 -  
231 - /**  
232 - * 营销匹配的商品 SKU  
233 - */  
234 - @Data  
235 - public static class PromotionItem {  
236 -  
237 - /**  
238 - * 商品 SKU 编号  
239 - */  
240 - private Long skuId;  
241 - /**  
242 - * 计算时的原价(总),单位:分  
243 - */  
244 - private Integer originalPrice;  
245 - /**  
246 - * 计算时的优惠(总),单位:分  
247 - */  
248 - private Integer discountPrice;  
249 -  
250 - }  
251 -  
252 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -118,9 +118,11 @@ public interface ErrorCodeConstants { @@ -118,9 +118,11 @@ public interface ErrorCodeConstants {
118 118
119 // ========== 装修模板 1-013-017-000 ========== 119 // ========== 装修模板 1-013-017-000 ==========
120 ErrorCode DIY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_017_000, "装修模板不存在"); 120 ErrorCode DIY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_017_000, "装修模板不存在");
121 - ErrorCode DIY_TEMPLATE_USED_CANNOT_DELETE = new ErrorCode(1_013_017_001, "不能删除正在使用的装修模板"); 121 + ErrorCode DIY_TEMPLATE_NAME_USED = new ErrorCode(1_013_017_001, "装修模板名称({})已经被使用");
  122 + ErrorCode DIY_TEMPLATE_USED_CANNOT_DELETE = new ErrorCode(1_013_017_002, "不能删除正在使用的装修模板");
122 123
123 // ========== 装修页面 1-013-018-000 ========== 124 // ========== 装修页面 1-013-018-000 ==========
124 ErrorCode DIY_PAGE_NOT_EXISTS = new ErrorCode(1_013_018_000, "装修页面不存在"); 125 ErrorCode DIY_PAGE_NOT_EXISTS = new ErrorCode(1_013_018_000, "装修页面不存在");
  126 + ErrorCode DIY_PAGE_NAME_USED = new ErrorCode(1_013_018_001, "装修页面名称({})已经被使用");
125 127
126 } 128 }
yudao-module-mall/yudao-module-promotion-biz/pom.xml
@@ -14,8 +14,8 @@ @@ -14,8 +14,8 @@
14 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
15 15
16 <description> 16 <description>
17 - market模块,主要实现营销相关功能  
18 - 例如:营销活动、banner广告、优惠券、优惠码等功能。 17 + promotion 模块,主要实现营销相关功能
  18 + 例如:营销活动、banner 广告、优惠券、优惠码等功能。
19 </description> 19 </description>
20 20
21 <dependencies> 21 <dependencies>
@@ -49,10 +49,6 @@ @@ -49,10 +49,6 @@
49 <groupId>cn.iocoder.boot</groupId> 49 <groupId>cn.iocoder.boot</groupId>
50 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> 50 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
51 </dependency> 51 </dependency>
52 - <dependency>  
53 - <groupId>cn.iocoder.boot</groupId>  
54 - <artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>  
55 - </dependency>  
56 52
57 <!-- Web 相关 --> 53 <!-- Web 相关 -->
58 <dependency> 54 <dependency>
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain;
2 2
3 import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; 3 import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
4 import org.springframework.stereotype.Service; 4 import org.springframework.stereotype.Service;
  5 +import org.springframework.validation.annotation.Validated;
5 6
6 import javax.annotation.Resource; 7 import javax.annotation.Resource;
7 8
@@ -11,6 +12,7 @@ import javax.annotation.Resource; @@ -11,6 +12,7 @@ import javax.annotation.Resource;
11 * @author HUIHUI 12 * @author HUIHUI
12 */ 13 */
13 @Service 14 @Service
  15 +@Validated
14 public class BargainActivityApiImpl implements BargainActivityApi { 16 public class BargainActivityApiImpl implements BargainActivityApi {
15 17
16 @Resource 18 @Resource