Commit cbaadc3a77b99126978e39c768bbf08fdceaf352
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 | 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 | 260 | | [MySQL](https://www.mysql.com/cn/) | 鏁版嵁搴撴湇鍔″櫒 | 5.7 / 8.0+ | | |
| 261 | 261 | | [Druid](https://github.com/alibaba/druid) | JDBC 杩炴帴姹犮佺洃鎺х粍浠 | 1.2.19 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | |
| 262 | 262 | | [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 澧炲己宸ュ叿鍖 | 3.5.3.2 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | | ... | ... |
pom.xml
| ... | ... | @@ -13,16 +13,16 @@ |
| 13 | 13 | <!-- Server 主项目 --> |
| 14 | 14 | <module>yudao-server</module> |
| 15 | 15 | <!-- 各种 module 拓展 --> |
| 16 | - <module>yudao-module-member</module> | |
| 17 | 16 | <module>yudao-module-system</module> |
| 18 | 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 | 20 | <!-- <module>yudao-module-report</module>--> |
| 21 | 21 | <!-- <module>yudao-module-mp</module>--> |
| 22 | 22 | <module>yudao-module-pay</module> |
| 23 | 23 | <module>yudao-module-mall</module> |
| 24 | 24 | <!-- 示例项目 --> |
| 25 | - <module>yudao-example</module> | |
| 25 | +<!-- <module>yudao-example</module>--> | |
| 26 | 26 | </modules> |
| 27 | 27 | |
| 28 | 28 | <name>${project.artifactId}</name> |
| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 31 | 31 | |
| 32 | 32 | <properties> |
| 33 | - <revision>1.8.2-snapshot</revision> | |
| 33 | + <revision>1.8.3-snapshot</revision> | |
| 34 | 34 | <!-- Maven 相关 --> |
| 35 | 35 | <java.version>1.8</java.version> |
| 36 | 36 | <maven.compiler.source>${java.version}</maven.compiler.source> |
| ... | ... | @@ -40,7 +40,7 @@ |
| 40 | 40 | <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> |
| 41 | 41 | <!-- 看看咋放到 bom 里 --> |
| 42 | 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 | 44 | <mapstruct.version>1.5.5.Final</mapstruct.version> |
| 45 | 45 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| 46 | 46 | </properties> | ... | ... |
sql/mysql/pay_wallet.sql
| ... | ... | @@ -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 | 257 | \ No newline at end of file | ... | ... |
sql/mysql/ruoyi-vue-pro.sql
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | Target Server Version : 80034 |
| 12 | 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 | 17 | SET NAMES utf8mb4; |
| ... | ... | @@ -341,7 +341,8 @@ CREATE TABLE `infra_api_access_log` ( |
| 341 | 341 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 342 | 342 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 343 | 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 | 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 | 385 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 385 | 386 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 386 | 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 | 391 | -- Records of infra_api_error_log |
| ... | ... | @@ -422,7 +423,7 @@ CREATE TABLE `infra_codegen_column` ( |
| 422 | 423 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 423 | 424 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 424 | 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 | 429 | -- Records of infra_codegen_column |
| ... | ... | @@ -455,7 +456,7 @@ CREATE TABLE `infra_codegen_table` ( |
| 455 | 456 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 456 | 457 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 457 | 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 | 462 | -- Records of infra_codegen_table |
| ... | ... | @@ -538,7 +539,7 @@ CREATE TABLE `infra_file` ( |
| 538 | 539 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 539 | 540 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 540 | 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 | 545 | -- Records of infra_file |
| ... | ... | @@ -587,7 +588,7 @@ CREATE TABLE `infra_file_content` ( |
| 587 | 588 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 588 | 589 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 589 | 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 | 594 | -- Records of infra_file_content |
| ... | ... | @@ -615,7 +616,7 @@ CREATE TABLE `infra_job` ( |
| 615 | 616 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 616 | 617 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 617 | 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 | 622 | -- Records of infra_job |
| ... | ... | @@ -656,7 +657,7 @@ CREATE TABLE `infra_job_log` ( |
| 656 | 657 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 657 | 658 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 658 | 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 | 663 | -- Records of infra_job_log |
| ... | ... | @@ -709,7 +710,7 @@ CREATE TABLE `member_address` ( |
| 709 | 710 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 710 | 711 | PRIMARY KEY (`id`) USING BTREE, |
| 711 | 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 | 716 | -- Records of member_address |
| ... | ... | @@ -807,6 +808,7 @@ INSERT INTO `member_experience_record` (`id`, `user_id`, `biz_id`, `biz_type`, ` |
| 807 | 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 | 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 | 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 | 812 | COMMIT; |
| 811 | 813 | |
| 812 | 814 | -- ---------------------------- |
| ... | ... | @@ -825,7 +827,7 @@ CREATE TABLE `member_group` ( |
| 825 | 827 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 826 | 828 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 827 | 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 | 833 | -- Records of member_group |
| ... | ... | @@ -853,7 +855,7 @@ CREATE TABLE `member_level` ( |
| 853 | 855 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 854 | 856 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 855 | 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 | 861 | -- Records of member_level |
| ... | ... | @@ -971,6 +973,7 @@ INSERT INTO `member_point_record` (`id`, `user_id`, `biz_id`, `biz_type`, `title |
| 971 | 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 | 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 | 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 | 977 | COMMIT; |
| 975 | 978 | |
| 976 | 979 | -- ---------------------------- |
| ... | ... | @@ -1052,7 +1055,7 @@ CREATE TABLE `member_tag` ( |
| 1052 | 1055 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1053 | 1056 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 1054 | 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 | 1061 | -- Records of member_tag |
| ... | ... | @@ -1162,7 +1165,7 @@ CREATE TABLE `system_dict_data` ( |
| 1162 | 1165 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 1163 | 1166 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1164 | 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 | 1171 | -- Records of system_dict_data |
| ... | ... | @@ -1248,6 +1251,11 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st |
| 1248 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1477 | COMMIT; |
| 1431 | 1478 | |
| 1432 | 1479 | -- ---------------------------- |
| ... | ... | @@ -1447,7 +1494,7 @@ CREATE TABLE `system_dict_type` ( |
| 1447 | 1494 | `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', |
| 1448 | 1495 | PRIMARY KEY (`id`) USING BTREE, |
| 1449 | 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 | 1500 | -- Records of system_dict_type |
| ... | ... | @@ -1521,6 +1568,11 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat |
| 1521 | 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 | 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 | 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 | 1576 | COMMIT; |
| 1525 | 1577 | |
| 1526 | 1578 | -- ---------------------------- |
| ... | ... | @@ -1540,7 +1592,7 @@ CREATE TABLE `system_error_code` ( |
| 1540 | 1592 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 1541 | 1593 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1542 | 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 | 1598 | -- Records of system_error_code |
| ... | ... | @@ -1569,7 +1621,7 @@ CREATE TABLE `system_login_log` ( |
| 1569 | 1621 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1570 | 1622 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 1571 | 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 | 1627 | -- Records of system_login_log |
| ... | ... | @@ -1699,7 +1751,7 @@ CREATE TABLE `system_menu` ( |
| 1699 | 1751 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 1700 | 1752 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1701 | 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 | 1757 | -- Records of system_menu |
| ... | ... | @@ -1951,11 +2003,11 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i |
| 1951 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 2313 | COMMIT; |
| 2197 | 2314 | |
| 2198 | 2315 | -- ---------------------------- |
| ... | ... | @@ -2283,7 +2400,7 @@ CREATE TABLE `system_notify_template` ( |
| 2283 | 2400 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 2284 | 2401 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2285 | 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 | 2406 | -- Records of system_notify_template |
| ... | ... | @@ -2310,8 +2427,10 @@ CREATE TABLE `system_oauth2_access_token` ( |
| 2310 | 2427 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 2311 | 2428 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2312 | 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 | 2436 | -- Records of system_oauth2_access_token |
| ... | ... | @@ -2433,7 +2552,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( |
| 2433 | 2552 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2434 | 2553 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2435 | 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 | 2558 | -- Records of system_oauth2_refresh_token |
| ... | ... | @@ -2473,7 +2592,7 @@ CREATE TABLE `system_operate_log` ( |
| 2473 | 2592 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2474 | 2593 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2475 | 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 | 2598 | -- Records of system_operate_log |
| ... | ... | @@ -3481,7 +3600,7 @@ CREATE TABLE `system_sms_code` ( |
| 3481 | 3600 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 3482 | 3601 | PRIMARY KEY (`id`) USING BTREE, |
| 3483 | 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 | 3606 | -- Records of system_sms_code |
| ... | ... | @@ -3524,7 +3643,7 @@ CREATE TABLE `system_sms_log` ( |
| 3524 | 3643 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 3525 | 3644 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 3526 | 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 | 3649 | -- Records of system_sms_log |
| ... | ... | @@ -3585,6 +3704,7 @@ CREATE TABLE `system_social_client` ( |
| 3585 | 3704 | `user_type` tinyint NOT NULL COMMENT '用户类型', |
| 3586 | 3705 | `client_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户端编号', |
| 3587 | 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 | 3708 | `status` tinyint NOT NULL COMMENT '状态', |
| 3589 | 3709 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 3590 | 3710 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| ... | ... | @@ -3593,7 +3713,7 @@ CREATE TABLE `system_social_client` ( |
| 3593 | 3713 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 3594 | 3714 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 3595 | 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 | 3719 | -- Records of system_social_client |
| ... | ... | @@ -3623,7 +3743,7 @@ CREATE TABLE `system_social_user` ( |
| 3623 | 3743 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 3624 | 3744 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 3625 | 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 | 3749 | -- Records of system_social_user |
| ... | ... | @@ -3648,7 +3768,7 @@ CREATE TABLE `system_social_user_bind` ( |
| 3648 | 3768 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 3649 | 3769 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 3650 | 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 | 3774 | -- Records of system_social_user_bind |
| ... | ... | @@ -3824,7 +3944,7 @@ CREATE TABLE `system_users` ( |
| 3824 | 3944 | -- Records of system_users |
| 3825 | 3945 | -- ---------------------------- |
| 3826 | 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 | 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 | 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 | 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 | 14 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 15 | 15 | |
| 16 | 16 | <properties> |
| 17 | - <revision>1.8.2-snapshot</revision> | |
| 17 | + <revision>1.8.3-snapshot</revision> | |
| 18 | 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 | 21 | <!-- Web 相关 --> |
| 22 | 22 | <springdoc.version>1.6.15</springdoc.version> |
| 23 | 23 | <knife4j.version>4.3.0</knife4j.version> |
| 24 | 24 | <servlet.versoin>2.5</servlet.versoin> |
| 25 | 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 | 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 | 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 | 37 | <resilience4j.version>1.7.1</resilience4j.version> |
| 36 | 38 | <!-- 监控相关 --> |
| 37 | 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 | 41 | <opentracing.version>0.33.0</opentracing.version> |
| 40 | 42 | <!-- Test 测试相关 --> |
| 41 | 43 | <podam.version>7.2.11.RELEASE</podam.version> |
| ... | ... | @@ -44,8 +46,8 @@ |
| 44 | 46 | <!-- Bpm 工作流相关 --> |
| 45 | 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 | 51 | <lombok.version>1.18.30</lombok.version> |
| 50 | 52 | <mapstruct.version>1.5.5.Final</mapstruct.version> |
| 51 | 53 | <hutool.version>5.8.22</hutool.version> |
| ... | ... | @@ -53,10 +55,10 @@ |
| 53 | 55 | <velocity.version>2.3</velocity.version> |
| 54 | 56 | <screw.version>1.0.5</screw.version> |
| 55 | 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 | 59 | <guice.version>5.1.0</guice.version> |
| 58 | 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 | 62 | <jsch.version>0.1.55</jsch.version> |
| 61 | 63 | <tika-core.version>2.7.0</tika-core.version> |
| 62 | 64 | <ip2region.version>2.7.0</ip2region.version> |
| ... | ... | @@ -67,8 +69,8 @@ |
| 67 | 69 | <minio.version>8.5.6</minio.version> |
| 68 | 70 | <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version> |
| 69 | 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 | 74 | <jimureport.version>1.6.1</jimureport.version> |
| 73 | 75 | <xercesImpl.version>2.12.2</xercesImpl.version> |
| 74 | 76 | <weixin-java.version>4.5.0</weixin-java.version> |
| ... | ... | @@ -98,11 +100,6 @@ |
| 98 | 100 | </dependency> |
| 99 | 101 | <dependency> |
| 100 | 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 | 103 | <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> |
| 107 | 104 | <version>${revision}</version> |
| 108 | 105 | </dependency> |
| ... | ... | @@ -260,6 +257,12 @@ |
| 260 | 257 | <version>${revision}</version> |
| 261 | 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 | 267 | <dependency> |
| 265 | 268 | <groupId>cn.iocoder.boot</groupId> | ... | ... |
yudao-example/yudao-sso-demo-by-code/pom.xml
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | <maven.compiler.target>8</maven.compiler.target> |
| 22 | 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 | 25 | </properties> |
| 26 | 26 | |
| 27 | 27 | <dependencyManagement> | ... | ... |
yudao-example/yudao-sso-demo-by-password/pom.xml
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | <maven.compiler.target>8</maven.compiler.target> |
| 22 | 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 | 25 | </properties> |
| 26 | 26 | |
| 27 | 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 | 4 | import lombok.Data; |
| 5 | 5 | import lombok.NoArgsConstructor; |
| 6 | 6 | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 7 | 9 | /** |
| 8 | 10 | * Key Value 的键值对 |
| 9 | 11 | * |
| ... | ... | @@ -12,7 +14,7 @@ import lombok.NoArgsConstructor; |
| 12 | 14 | @Data |
| 13 | 15 | @NoArgsConstructor |
| 14 | 16 | @AllArgsConstructor |
| 15 | -public class KeyValue<K, V> { | |
| 17 | +public class KeyValue<K, V> implements Serializable { | |
| 16 | 18 | |
| 17 | 19 | private K key; |
| 18 | 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 | 8 | import java.util.*; |
| 9 | 9 | import java.util.function.*; |
| 10 | 10 | import java.util.stream.Collectors; |
| 11 | +import java.util.stream.Stream; | |
| 11 | 12 | |
| 12 | 13 | import static java.util.Arrays.asList; |
| 13 | 14 | |
| ... | ... | @@ -223,10 +224,14 @@ public class CollectionUtils { |
| 223 | 224 | } |
| 224 | 225 | |
| 225 | 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 | 231 | if (CollUtil.isEmpty(from)) { |
| 227 | 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 | 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 | 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 | 21 | @ConditionalOnProperty(prefix = "yudao.error-code", value = "enable", matchIfMissing = true) // 允许使用 yudao.error-code.enable=false 禁用访问日志 |
| 22 | 22 | @EnableConfigurationProperties(ErrorCodeProperties.class) |
| 23 | 23 | @EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 |
| 24 | -public class YudaoErrorCodeConfiguration { | |
| 24 | +public class YudaoErrorCodeAutoConfiguration { | |
| 25 | 25 | |
| 26 | 26 | @Bean |
| 27 | 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
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 | import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |
| 7 | 7 | import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; |
| 8 | 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 | 11 | import java.util.Map; |
| 11 | 12 | |
| ... | ... | @@ -86,4 +87,12 @@ public interface PayClient { |
| 86 | 87 | */ |
| 87 | 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 | 53 | /** |
| 54 | 54 | * 创建【WAITING】状态的转账返回 |
| 55 | 55 | */ |
| 56 | - public static PayTransferRespDTO waitingOf(String channelOrderNo, | |
| 56 | + public static PayTransferRespDTO waitingOf(String channelTransferNo, | |
| 57 | 57 | String outTransferNo, Object rawData) { |
| 58 | 58 | PayTransferRespDTO respDTO = new PayTransferRespDTO(); |
| 59 | 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 | 74 | respDTO.outTransferNo = outTransferNo; |
| 62 | 75 | respDTO.rawData = rawData; |
| 63 | 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<Config extends PayClientConfig> implemen |
| 188 | 188 | |
| 189 | 189 | @Override |
| 190 | 190 | public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { |
| 191 | + validatePayTransferReqDTO(reqDTO); | |
| 191 | 192 | PayTransferRespDTO resp; |
| 192 | - try{ | |
| 193 | - validatePayTransferReqDTO(reqDTO); | |
| 193 | + try { | |
| 194 | 194 | resp = doUnifiedTransfer(reqDTO); |
| 195 | - }catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可 | |
| 195 | + } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可 | |
| 196 | 196 | throw ex; |
| 197 | 197 | } catch (Throwable ex) { |
| 198 | 198 | // 系统异常,则包装成 PayException 异常抛出 |
| ... | ... | @@ -219,9 +219,25 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> 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 | 235 | protected abstract PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) |
| 223 | 236 | throws Throwable; |
| 224 | 237 | |
| 238 | + protected abstract PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) | |
| 239 | + throws Throwable; | |
| 240 | + | |
| 225 | 241 | // ========== 各种工具方法 ========== |
| 226 | 242 | |
| 227 | 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 | 23 | import com.alipay.api.DefaultAlipayClient; |
| 24 | 24 | import com.alipay.api.domain.*; |
| 25 | 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 | 28 | import lombok.Getter; |
| 35 | 29 | import lombok.SneakyThrows; |
| 36 | 30 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -126,7 +120,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa |
| 126 | 120 | } |
| 127 | 121 | // 2.2 解析订单的状态 |
| 128 | 122 | Integer status = parseStatus(response.getTradeStatus()); |
| 129 | - Assert.notNull(status, () -> { | |
| 123 | + Assert.notNull(status, () -> { | |
| 130 | 124 | throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody())); |
| 131 | 125 | }); |
| 132 | 126 | return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()), |
| ... | ... | @@ -228,7 +222,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa |
| 228 | 222 | protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException { |
| 229 | 223 | // 1.1 校验公钥类型 必须使用公钥证书模式 |
| 230 | 224 | if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) { |
| 231 | - throw exception0(ERROR_CONFIGURATION.getCode(),"支付宝单笔转账必须使用公钥证书模式"); | |
| 225 | + throw exception0(ERROR_CONFIGURATION.getCode(), "支付宝单笔转账必须使用公钥证书模式"); | |
| 232 | 226 | } |
| 233 | 227 | // 1.2 构建 AlipayFundTransUniTransferModel |
| 234 | 228 | AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel(); |
| ... | ... | @@ -238,44 +232,96 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa |
| 238 | 232 | model.setOutBizNo(reqDTO.getOutTransferNo()); |
| 239 | 233 | model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD |
| 240 | 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 | 240 | PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(reqDTO.getType()); |
| 243 | 241 | switch (transferType) { |
| 244 | 242 | // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦? |
| 245 | 243 | // @芋艿。 是不是还要考虑转账到银行卡。所以传 transferType 但是转账到银行卡不知道要如何测试?? |
| 246 | 244 | case ALIPAY_BALANCE: { |
| 247 | - // ② 个性化的参数 | |
| 248 | - Participant payeeInfo = new Participant(); | |
| 249 | 245 | payeeInfo.setIdentityType("ALIPAY_LOGON_ID"); |
| 250 | 246 | payeeInfo.setIdentity(reqDTO.getAlipayLogonId()); // 支付宝登录号 |
| 251 | 247 | payeeInfo.setName(reqDTO.getUserName()); // 支付宝账号姓名 |
| 252 | 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 | 251 | case BANK_CARD: { |
| 271 | - Participant payeeInfo = new Participant(); | |
| 272 | 252 | payeeInfo.setIdentityType("BANKCARD_ACCOUNT"); |
| 273 | 253 | // TODO 待实现 |
| 274 | 254 | throw exception(NOT_IMPLEMENTED); |
| 275 | 255 | } |
| 276 | 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 | 9 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |
| 10 | 10 | import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; |
| 11 | 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 | 14 | import java.time.LocalDateTime; |
| 14 | 15 | import java.util.Map; |
| ... | ... | @@ -71,4 +72,9 @@ public class MockPayClient extends AbstractPayClient<NonePayClientConfig> { |
| 71 | 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 | 16 | import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; |
| 17 | 17 | import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |
| 18 | 18 | import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; |
| 19 | +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum; | |
| 19 | 20 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| 20 | 21 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; |
| 21 | 22 | import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; |
| ... | ... | @@ -431,6 +432,12 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC |
| 431 | 432 | protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { |
| 432 | 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 | 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 | 38 | public static boolean isClosed(Integer status) { |
| 39 | 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 | 48 | <dependency> |
| 49 | 49 | <groupId>cn.iocoder.boot</groupId> |
| 50 | 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 | 67 | </dependency> |
| 52 | 68 | |
| 53 | 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 | 6 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect; |
| 7 | 7 | import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; |
| 8 | 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 | 12 | import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager; |
| 11 | 13 | import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; |
| 12 | 14 | import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; |
| ... | ... | @@ -18,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.tenant.TenantApi; |
| 18 | 20 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
| 19 | 21 | import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; |
| 20 | 22 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 23 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |
| 21 | 24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 22 | 25 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 23 | 26 | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| ... | ... | @@ -92,6 +95,18 @@ public class YudaoTenantAutoConfiguration { |
| 92 | 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 | 110 | // ========== Job ========== |
| 96 | 111 | |
| 97 | 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 | 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 | 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 | 6 | import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; |
| 7 | 7 | |
| 8 | 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 | 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
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 | 12 | <packaging>jar</packaging> |
| 13 | 13 | |
| 14 | 14 | <name>${project.artifactId}</name> |
| 15 | - <description>消息队列,基于 Redis Pub/Sub 实现广播消费,基于 Stream 实现集群消费</description> | |
| 15 | + <description>消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种</description> | |
| 16 | 16 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 17 | 17 | |
| 18 | 18 | <dependencies> |
| ... | ... | @@ -21,6 +21,23 @@ |
| 21 | 21 | <groupId>cn.iocoder.boot</groupId> |
| 22 | 22 | <artifactId>yudao-spring-boot-starter-redis</artifactId> |
| 23 | 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 | 41 | </dependencies> |
| 25 | 42 | |
| 26 | 43 | -</project> |
| 44 | +</project> | |
| 27 | 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
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
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/package-info.java
0 → 100644
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 | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | 5 | import cn.hutool.system.SystemUtil; |
| 6 | 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 | 12 | import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; |
| 13 | 13 | import lombok.extern.slf4j.Slf4j; |
| 14 | 14 | import org.redisson.api.RedissonClient; |
| 15 | 15 | import org.springframework.beans.factory.annotation.Value; |
| 16 | 16 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 17 | 17 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; |
| 18 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
| 19 | 18 | import org.springframework.context.annotation.Bean; |
| 20 | 19 | import org.springframework.data.redis.connection.RedisServerCommands; |
| 21 | 20 | import org.springframework.data.redis.connection.stream.Consumer; |
| ... | ... | @@ -27,7 +26,6 @@ import org.springframework.data.redis.core.RedisTemplate; |
| 27 | 26 | import org.springframework.data.redis.core.StringRedisTemplate; |
| 28 | 27 | import org.springframework.data.redis.listener.ChannelTopic; |
| 29 | 28 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; |
| 30 | -import org.springframework.data.redis.stream.DefaultStreamMessageListenerContainerX; | |
| 31 | 29 | import org.springframework.data.redis.stream.StreamMessageListenerContainer; |
| 32 | 30 | import org.springframework.scheduling.annotation.EnableScheduling; |
| 33 | 31 | |
| ... | ... | @@ -42,7 +40,7 @@ import java.util.Properties; |
| 42 | 40 | @Slf4j |
| 43 | 41 | @EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息 |
| 44 | 42 | @AutoConfiguration(after = YudaoRedisAutoConfiguration.class) |
| 45 | -public class YudaoMQAutoConfiguration { | |
| 43 | +public class YudaoRedisMQAutoConfiguration { | |
| 46 | 44 | |
| 47 | 45 | @Bean |
| 48 | 46 | public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate, |
| ... | ... | @@ -59,10 +57,9 @@ public class YudaoMQAutoConfiguration { |
| 59 | 57 | * 创建 Redis Pub/Sub 广播消费的容器 |
| 60 | 58 | */ |
| 61 | 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 | 61 | public RedisMessageListenerContainer redisMessageListenerContainer( |
| 65 | - RedisMQTemplate redisMQTemplate, List<AbstractChannelMessageListener<?>> listeners) { | |
| 62 | + RedisMQTemplate redisMQTemplate, List<AbstractRedisChannelMessageListener<?>> listeners) { | |
| 66 | 63 | // 创建 RedisMessageListenerContainer 对象 |
| 67 | 64 | RedisMessageListenerContainer container = new RedisMessageListenerContainer(); |
| 68 | 65 | // 设置 RedisConnection 工厂。 |
| ... | ... | @@ -81,9 +78,8 @@ public class YudaoMQAutoConfiguration { |
| 81 | 78 | * 创建 Redis Stream 重新消费的任务 |
| 82 | 79 | */ |
| 83 | 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 | 83 | RedisMQTemplate redisTemplate, |
| 88 | 84 | @Value("${spring.application.name}") String groupName, |
| 89 | 85 | RedissonClient redissonClient) { |
| ... | ... | @@ -92,14 +88,13 @@ public class YudaoMQAutoConfiguration { |
| 92 | 88 | |
| 93 | 89 | /** |
| 94 | 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 | 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 | 96 | public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer( |
| 102 | - RedisMQTemplate redisMQTemplate, List<AbstractStreamMessageListener<?>> listeners) { | |
| 97 | + RedisMQTemplate redisMQTemplate, List<AbstractRedisStreamMessageListener<?>> listeners) { | |
| 103 | 98 | RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate(); |
| 104 | 99 | checkRedisVersion(redisTemplate); |
| 105 | 100 | // 第一步,创建 StreamMessageListenerContainer 容器 |
| ... | ... | @@ -111,8 +106,7 @@ public class YudaoMQAutoConfiguration { |
| 111 | 106 | .build(); |
| 112 | 107 | // 创建 container 对象 |
| 113 | 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 | 111 | // 第二步,注册监听器,消费对应的 Stream 主题 |
| 118 | 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 | 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 | 8 | import lombok.AllArgsConstructor; |
| 9 | 9 | import lombok.Getter; |
| 10 | 10 | import org.springframework.data.redis.connection.stream.RecordId; |
| ... | ... | @@ -35,7 +35,7 @@ public class RedisMQTemplate { |
| 35 | 35 | * |
| 36 | 36 | * @param message 消息 |
| 37 | 37 | */ |
| 38 | - public <T extends AbstractChannelMessage> void send(T message) { | |
| 38 | + public <T extends AbstractRedisChannelMessage> void send(T message) { | |
| 39 | 39 | try { |
| 40 | 40 | sendMessageBefore(message); |
| 41 | 41 | // 发送消息 |
| ... | ... | @@ -51,7 +51,7 @@ public class RedisMQTemplate { |
| 51 | 51 | * @param message 消息 |
| 52 | 52 | * @return 消息记录的编号对象 |
| 53 | 53 | */ |
| 54 | - public <T extends AbstractStreamMessage> RecordId send(T message) { | |
| 54 | + public <T extends AbstractRedisStreamMessage> RecordId send(T message) { | |
| 55 | 55 | try { |
| 56 | 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 | 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 | 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 | 6 | import lombok.AllArgsConstructor; |
| 7 | 7 | import lombok.extern.slf4j.Slf4j; |
| 8 | 8 | import org.redisson.api.RLock; |
| ... | ... | @@ -33,7 +33,7 @@ public class RedisPendingMessageResendJob { |
| 33 | 33 | */ |
| 34 | 34 | private static final int EXPIRE_TIME = 5 * 60; |
| 35 | 35 | |
| 36 | - private final List<AbstractStreamMessageListener<?>> listeners; | |
| 36 | + private final List<AbstractRedisStreamMessageListener<?>> listeners; | |
| 37 | 37 | private final RedisMQTemplate redisTemplate; |
| 38 | 38 | private final String groupName; |
| 39 | 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
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 | 4 | import com.fasterxml.jackson.annotation.JsonIgnore; |
| 5 | 5 | |
| 6 | 6 | /** |
| ... | ... | @@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; |
| 8 | 8 | * |
| 9 | 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 | 16 | * @return Channel |
| 17 | 17 | */ |
| 18 | 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 | 3 | import cn.hutool.core.util.TypeUtil; |
| 4 | 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 | 8 | import lombok.Setter; |
| 9 | 9 | import lombok.SneakyThrows; |
| 10 | 10 | import org.springframework.data.redis.connection.Message; |
| ... | ... | @@ -20,7 +20,7 @@ import java.util.List; |
| 20 | 20 | * |
| 21 | 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<T extends AbstractChannelMe |
| 37 | 37 | private RedisMQTemplate redisMQTemplate; |
| 38 | 38 | |
| 39 | 39 | @SneakyThrows |
| 40 | - protected AbstractChannelMessageListener() { | |
| 40 | + protected AbstractRedisChannelMessageListener() { | |
| 41 | 41 | this.messageType = getMessageClass(); |
| 42 | 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 | 4 | import com.fasterxml.jackson.annotation.JsonIgnore; |
| 5 | 5 | |
| 6 | 6 | /** |
| ... | ... | @@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; |
| 8 | 8 | * |
| 9 | 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 | 16 | * @return Channel |
| 17 | 17 | */ |
| 18 | 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 | 3 | import cn.hutool.core.util.TypeUtil; |
| 4 | 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 | 8 | import lombok.Getter; |
| 9 | 9 | import lombok.Setter; |
| 10 | 10 | import lombok.SneakyThrows; |
| ... | ... | @@ -22,7 +22,7 @@ import java.util.List; |
| 22 | 22 | * |
| 23 | 23 | * @author 芋道源码 |
| 24 | 24 | */ |
| 25 | -public abstract class AbstractStreamMessageListener<T extends AbstractStreamMessage> | |
| 25 | +public abstract class AbstractRedisStreamMessageListener<T extends AbstractRedisStreamMessage> | |
| 26 | 26 | implements StreamListener<String, ObjectRecord<String, String>> { |
| 27 | 27 | |
| 28 | 28 | /** |
| ... | ... | @@ -48,7 +48,7 @@ public abstract class AbstractStreamMessageListener<T extends AbstractStreamMess |
| 48 | 48 | private RedisMQTemplate redisMQTemplate; |
| 49 | 49 | |
| 50 | 50 | @SneakyThrows |
| 51 | - protected AbstractStreamMessageListener() { | |
| 51 | + protected AbstractRedisStreamMessageListener() { | |
| 52 | 52 | this.messageType = getMessageClass(); |
| 53 | 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
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
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
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java
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 | 20 | ; |
| 21 | 21 | |
| 22 | 22 | /** |
| 23 | - * 结果 | |
| 23 | + * 操作类型 | |
| 24 | 24 | */ |
| 25 | 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 | 30 | * 相当于是 通过 APPROVE 的特殊状态 |
| 31 | 31 | * 例如:A审批, A 后加签了 B,并且审批通过了任务,但是 B 还未审批,则当前任务状态为“待后加签任务完成” |
| 32 | 32 | */ |
| 33 | - ADD_SIGN_AFTER(7, "待后加签任务完成"), | |
| 33 | + SIGN_AFTER(7, "待后加签任务完成"), | |
| 34 | 34 | /** |
| 35 | 35 | * 【加签】源任务未审批,但是向前加签了,所以源任务状态变为“待前加签任务完成” |
| 36 | 36 | * 相当于是 处理中 PROCESS 的特殊状态 |
| 37 | 37 | * 例如:A 审批, A 前加签了 B,B 还未审核 |
| 38 | 38 | */ |
| 39 | - ADD_SIGN_BEFORE(8, "待前加签任务完成"), | |
| 39 | + SIGN_BEFORE(8, "待前加签任务完成"), | |
| 40 | 40 | /** |
| 41 | 41 | * 【加签】后加签任务被创建时的初始状态 |
| 42 | 42 | * 相当于是 处理中 PROCESS 的特殊状态 |
| ... | ... | @@ -71,7 +71,7 @@ public enum BpmProcessInstanceResultEnum { |
| 71 | 71 | public static boolean isEndResult(Integer result) { |
| 72 | 72 | return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(), |
| 73 | 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
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 | 74 | return success(true); |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | - @GetMapping("/get-return-list") | |
| 77 | + @GetMapping("/return-list") | |
| 78 | 78 | @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮") |
| 79 | 79 | @Parameter(name = "taskId", description = "当前任务ID", required = true) |
| 80 | 80 | @PreAuthorize("@ss.hasPermission('bpm:task:update')") |
| ... | ... | @@ -98,27 +98,28 @@ public class BpmTaskController { |
| 98 | 98 | return success(true); |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | - @PutMapping("/add-sign") | |
| 101 | + @PutMapping("/create-sign") | |
| 102 | 102 | @Operation(summary = "加签", description = "before 前加签,after 后加签") |
| 103 | 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 | 106 | return success(true); |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | - @PutMapping("/sub-sign") | |
| 109 | + @DeleteMapping("/delete-sign") | |
| 110 | 110 | @Operation(summary = "减签") |
| 111 | 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 | 114 | return success(true); |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | - @GetMapping("/get-children-task-list") | |
| 117 | + @GetMapping("children-list") | |
| 118 | 118 | @Operation(summary = "获取能被减签的任务") |
| 119 | + @Parameter(name = "parentId", description = "父级任务 ID", required = true) | |
| 119 | 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 | import javax.validation.constraints.NotEmpty; |
| 7 | 7 | import java.util.Set; |
| 8 | 8 | |
| 9 | +// TODO @海洋:类名,应该是 create 哈 | |
| 9 | 10 | @Schema(description = "管理后台 - 加签流程任务的 Request VO") |
| 10 | 11 | @Data |
| 11 | 12 | public class BpmTaskAddSignReqVO { |
| ... | ... | @@ -26,4 +27,4 @@ public class BpmTaskAddSignReqVO { |
| 26 | 27 | @NotEmpty(message = "加签原因不能为空") |
| 27 | 28 | private String reason; |
| 28 | 29 | |
| 29 | -} | |
| 30 | 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
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.convert.task; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 4 | +import cn.hutool.core.util.ObjectUtil; | |
| 5 | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 7 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | |
| 7 | 8 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; |
| 8 | 9 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 9 | 10 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; |
| ... | ... | @@ -25,6 +26,9 @@ import java.util.Date; |
| 25 | 26 | import java.util.List; |
| 26 | 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 | 33 | * Bpm 任务 Convert |
| 30 | 34 | * |
| ... | ... | @@ -167,32 +171,31 @@ public interface BpmTaskConvert { |
| 167 | 171 | default List<BpmTaskSubSignRespVO> convertList(List<BpmTaskExtDO> bpmTaskExtDOList, |
| 168 | 172 | Map<Long, AdminUserRespDTO> userMap, |
| 169 | 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 | 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 | 182 | return bpmTaskSubSignRespVO; |
| 182 | 183 | }); |
| 183 | 184 | } |
| 184 | 185 | |
| 185 | 186 | /** |
| 186 | 187 | * 转换任务为父子级 |
| 188 | + * | |
| 187 | 189 | * @param sourceList 原始数据 |
| 188 | 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 | 195 | for (BpmTaskRespVO bpmTaskRespVO : sourceList) { |
| 194 | 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<BpmTaskExtDO> { |
| 21 | 21 | return selectList(BpmTaskExtDO::getTaskId, taskIds); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | + // TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务 | |
| 24 | 25 | default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) { |
| 25 | 26 | return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>() |
| 26 | 27 | .in(BpmTaskExtDO::getTaskId, taskIds) |
| 27 | 28 | .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST)); |
| 28 | 29 | } |
| 29 | 30 | |
| 30 | - | |
| 31 | 31 | default BpmTaskExtDO selectByTaskId(String taskId) { |
| 32 | 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
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
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 | 163 | * @param userId 被加签的用户和任务 ID,加签类型 |
| 164 | 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 | 171 | * @param userId 当前用户ID |
| 172 | 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 | 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 | 53 | import javax.validation.Valid; |
| 54 | 54 | import java.time.LocalDateTime; |
| 55 | 55 | import java.util.*; |
| 56 | -import java.util.stream.Collectors; | |
| 57 | 56 | import java.util.stream.Stream; |
| 58 | 57 | |
| 59 | 58 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -240,10 +239,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 240 | 239 | handleParentTask(task); |
| 241 | 240 | } |
| 242 | 241 | |
| 242 | + | |
| 243 | 243 | /** |
| 244 | 244 | * 审批通过存在“后加签”的任务。 |
| 245 | 245 | * <p> |
| 246 | - * 注意:该任务不能马上完成,需要一个中间状态(ADD_SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理 | |
| 246 | + * 注意:该任务不能马上完成,需要一个中间状态(SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理 | |
| 247 | 247 | * |
| 248 | 248 | * @param task 当前任务 |
| 249 | 249 | * @param reqVO 前端请求参数 |
| ... | ... | @@ -251,7 +251,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 251 | 251 | private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) { |
| 252 | 252 | // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态 |
| 253 | 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 | 255 | .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now())); |
| 256 | 256 | |
| 257 | 257 | // 2. 激活子任务 |
| ... | ... | @@ -265,7 +265,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | /** |
| 268 | - * 处理当前任务的父任务 | |
| 268 | + * 处理当前任务的父任务,主要处理“加签”的情况 | |
| 269 | 269 | * |
| 270 | 270 | * @param task 当前任务 |
| 271 | 271 | */ |
| ... | ... | @@ -274,76 +274,79 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 274 | 274 | if (StrUtil.isBlank(parentTaskId)) { |
| 275 | 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 | 317 | * @param parentTask 当前审批任务的父任务 |
| 315 | 318 | */ |
| 316 | - private void handleAfterSign(Task parentTask) { | |
| 319 | + // TODO @海:这个逻辑,怎么感觉可以是 parentTask 的 parent,再去调用 handleParentTask 方法;可以微信聊下; | |
| 320 | + private void handleParentTaskForAfterSign(Task parentTask) { | |
| 317 | 321 | String parentTaskId = parentTask.getId(); |
| 318 | - //1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己 | |
| 322 | + // 1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己 | |
| 319 | 323 | BpmTaskExtDO currentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId()); |
| 320 | - BpmTaskExtDO currentTaskUpdateEntity = new BpmTaskExtDO().setTaskId(parentTask.getId()) | |
| 324 | + BpmTaskExtDO currentTaskExtUpdateObj = new BpmTaskExtDO().setTaskId(parentTask.getId()) | |
| 321 | 325 | .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); |
| 322 | 326 | if (currentTaskExt.getEndTime() == null) { |
| 323 | 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 | 332 | taskService.complete(parentTaskId); |
| 329 | 333 | |
| 330 | 334 | // 2. 如果有父级,递归查询上级任务是否都已经完成 |
| 331 | 335 | if (StrUtil.isEmpty(parentTask.getParentTaskId())) { |
| 332 | 336 | return; |
| 333 | 337 | } |
| 334 | - // TODO @海:这块待讨论,脑子略乱;感觉 handleAfterSign 的后半段,和 handleParentTask 有点重叠??? | |
| 335 | 338 | // 2.1 判断整条链路的任务是否完成 |
| 336 | 339 | // 例如从 A 任务加签了一个 B 任务,B 任务又加签了一个 C 任务,C 任务加签了 D 任务 |
| 337 | 340 | // 此时,D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务 |
| 338 | 341 | boolean allChildrenTaskFinish = true; |
| 339 | 342 | while (StrUtil.isNotBlank(parentTask.getParentTaskId())) { |
| 340 | 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 | 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 | 350 | if (allChildrenTaskFinish) { |
| 348 | 351 | allChildrenTaskFinish = currentTaskFinish; |
| 349 | 352 | } |
| ... | ... | @@ -354,19 +357,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 354 | 357 | |
| 355 | 358 | // 3 处理非完成状态的任务 |
| 356 | 359 | // 3.1 判断当前任务的父任务是否还有子任务 |
| 357 | - Long childrenTaskCount = getChildrenTaskCount(bpmTaskExtDO.getTaskId()); | |
| 360 | + Long childrenTaskCount = getChildrenTaskCount(parentTaskExt.getTaskId()); | |
| 358 | 361 | if (childrenTaskCount > 0) { |
| 359 | 362 | continue; |
| 360 | 363 | } |
| 361 | 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 | 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 | 371 | // 3.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签 |
| 369 | - parentTask = validateTaskExist(bpmTaskExtDO.getTaskId()); | |
| 372 | + parentTask = validateTaskExist(parentTaskExt.getTaskId()); | |
| 370 | 373 | clearTaskScopeTypeAndSave(parentTask); |
| 371 | 374 | } |
| 372 | 375 | |
| ... | ... | @@ -387,7 +390,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 387 | 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 | 711 | |
| 710 | 712 | @Override |
| 711 | 713 | @Transactional(rollbackFor = Exception.class) |
| 712 | - public void addSignTask(Long userId, BpmTaskAddSignReqVO reqVO) { | |
| 714 | + public void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO) { | |
| 713 | 715 | // 1. 获取和校验任务 |
| 714 | 716 | TaskEntityImpl taskEntity = validateAddSign(userId, reqVO); |
| 715 | 717 | List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList()); |
| ... | ... | @@ -728,7 +730,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 728 | 730 | // 2.3 更新扩展表状态 |
| 729 | 731 | taskExtMapper.updateByTaskId( |
| 730 | 732 | new BpmTaskExtDO().setTaskId(taskEntity.getId()) |
| 731 | - .setResult(BpmProcessInstanceResultEnum.ADD_SIGN_BEFORE.getResult()) | |
| 733 | + .setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()) | |
| 732 | 734 | .setReason(reqVO.getReason())); |
| 733 | 735 | } |
| 734 | 736 | // 2.4 记录加签方式,完成任务时需要用到判断 |
| ... | ... | @@ -737,12 +739,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 737 | 739 | taskService.saveTask(taskEntity); |
| 738 | 740 | |
| 739 | 741 | // 3. 创建加签任务 |
| 740 | - createAddSignChildrenTasks(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity); | |
| 742 | + createSignTask(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity); | |
| 741 | 743 | |
| 742 | 744 | // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason |
| 743 | 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 | 748 | taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), |
| 747 | 749 | BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment); |
| 748 | 750 | } |
| ... | ... | @@ -786,7 +788,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 786 | 788 | * @param addSingUserIdList 被加签的用户 ID |
| 787 | 789 | * @param taskEntity 被加签的任务 |
| 788 | 790 | */ |
| 789 | - private void createAddSignChildrenTasks(List<String> addSingUserIdList, TaskEntityImpl taskEntity) { | |
| 791 | + private void createSignTask(List<String> addSingUserIdList, TaskEntityImpl taskEntity) { | |
| 790 | 792 | if (CollUtil.isEmpty(addSingUserIdList)) { |
| 791 | 793 | return; |
| 792 | 794 | } |
| ... | ... | @@ -795,23 +797,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 795 | 797 | if (StrUtil.isBlank(addSignId)) { |
| 796 | 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 | 807 | * @param parentTask 父任务 |
| 806 | 808 | * @param assignee 子任务的执行人 |
| 807 | - * @return | |
| 808 | 809 | */ |
| 809 | - private void createChildrenTask(TaskEntityImpl parentTask, String assignee) { | |
| 810 | + private void createSignTask(TaskEntityImpl parentTask, String assignee) { | |
| 810 | 811 | // 1. 生成子任务 |
| 811 | 812 | TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID()); |
| 812 | 813 | task = BpmTaskConvert.INSTANCE.convert(task, parentTask); |
| 813 | 814 | if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { |
| 814 | - // 2.1 前加签,才设置审批人,否则设置 owner | |
| 815 | + // 2.1 前加签,设置审批人 | |
| 815 | 816 | task.setAssignee(assignee); |
| 816 | 817 | } else { |
| 817 | 818 | // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 |
| ... | ... | @@ -825,9 +826,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 825 | 826 | |
| 826 | 827 | @Override |
| 827 | 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 | 831 | Task task = validateSubSign(reqVO.getId()); |
| 830 | - AdminUserRespDTO user = adminUserApi.getUser(userId); | |
| 832 | + // 1.2 校验取消人存在 | |
| 831 | 833 | AdminUserRespDTO cancelUser = null; |
| 832 | 834 | if (StrUtil.isNotBlank(task.getAssignee())) { |
| 833 | 835 | cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getAssignee())); |
| ... | ... | @@ -836,20 +838,24 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 836 | 838 | cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner())); |
| 837 | 839 | } |
| 838 | 840 | Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误"); |
| 839 | - //1. 获取所有需要删除的任务 ID ,包含当前任务和所有子任务 | |
| 841 | + | |
| 842 | + // 2. 删除任务和对应子任务 | |
| 843 | + // 2.1 获取所有需要删除的任务 ID ,包含当前任务和所有子任务 | |
| 840 | 844 | List<String> allTaskIdList = getAllChildTaskIds(task.getId()); |
| 841 | - //2. 删除任务和所有子任务 | |
| 845 | + // 2.2 删除任务和所有子任务 | |
| 842 | 846 | taskService.deleteTasks(allTaskIdList); |
| 843 | - //3. 修改扩展表状态为取消 | |
| 847 | + // 2.3 修改扩展表状态为取消 | |
| 848 | + AdminUserRespDTO user = adminUserApi.getUser(userId); | |
| 844 | 849 | taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()) |
| 845 | 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 | 854 | taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), |
| 849 | 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 | 866 | */ |
| 861 | 867 | private Task validateSubSign(String id) { |
| 862 | 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 | 877 | throw exception(TASK_SUB_SIGN_NO_PARENT); |
| 866 | 878 | } |
| 867 | 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 | 892 | * 获取所有要被取消的删除的任务 ID 集合 |
| 872 | 893 | * |
| 873 | 894 | * @param parentTaskId 父级任务ID |
| ... | ... | @@ -875,25 +896,40 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 875 | 896 | */ |
| 876 | 897 | public List<String> getAllChildTaskIds(String parentTaskId) { |
| 877 | 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 | 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 | 938 | * @param parentTaskId 父任务 ID |
| 903 | 939 | * @return 所有子任务的 ID 集合 |
| 904 | 940 | */ |
| 905 | - private List<String> getChildrenTaskIdList(String parentTaskId) { | |
| 941 | + private List<Task> getChildrenTaskList0(String parentTaskId) { | |
| 906 | 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 | 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 | 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 | 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 | 147 | */ |
| 148 | 148 | private static ProcessConfig buildProcessConfig() { |
| 149 | 149 | return ProcessConfig.builder() |
| 150 | - .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_")) // 忽略表前缀 | |
| 150 | + .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_", "FLW_")) // 忽略表前缀 | |
| 151 | 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 | 29 | .antMatchers("/swagger-resources/**").anonymous() |
| 30 | 30 | .antMatchers("/webjars/**").anonymous() |
| 31 | 31 | .antMatchers("/*/api-docs").anonymous(); |
| 32 | - // 积木报表 | |
| 33 | - registry.antMatchers("/jmreport/**").permitAll(); | |
| 34 | 32 | // Spring Boot Actuator 的安全配置 |
| 35 | 33 | registry.antMatchers("/actuator").anonymous() |
| 36 | 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 | 3 | import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; |
| 4 | 4 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; |
| ... | ... | @@ -33,7 +33,7 @@ public class JobLogCleanJob implements JobHandler { |
| 33 | 33 | @TenantIgnore |
| 34 | 34 | public String execute(String param) { |
| 35 | 35 | Integer count = jobLogService.cleanJobLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); |
| 36 | - log.info("[count][定时执行清理定时任务日志数量 ({}) 个]", count); | |
| 36 | + log.info("[execute][定时执行清理定时任务日志数量 ({}) 个]", count); | |
| 37 | 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 | 3 | import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; |
| 4 | 4 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; |
| ... | ... | @@ -34,7 +34,7 @@ public class AccessLogCleanJob implements JobHandler { |
| 34 | 34 | @TenantIgnore |
| 35 | 35 | public String execute(String param) { |
| 36 | 36 | Integer count = apiAccessLogService.cleanAccessLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); |
| 37 | - log.info("[count][定时执行清理访问日志数量 ({}) 个]", count); | |
| 37 | + log.info("[execute][定时执行清理访问日志数量 ({}) 个]", count); | |
| 38 | 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 | 3 | import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; |
| 4 | 4 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; |
| ... | ... | @@ -34,7 +34,7 @@ public class ErrorLogCleanJob implements JobHandler { |
| 34 | 34 | @TenantIgnore |
| 35 | 35 | public String execute(String param) { |
| 36 | 36 | Integer count = apiErrorLogService.cleanErrorLog(JOB_CLEAN_RETAIN_DAY,DELETE_LIMIT); |
| 37 | - log.info("[count][定时执行清理错误日志数量 ({}) 个]", count); | |
| 37 | + log.info("[execute][定时执行清理错误日志数量 ({}) 个]", count); | |
| 38 | 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 | 58 | FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ? |
| 59 | 59 | fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id); |
| 60 | 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 | 28 | |
| 29 | 29 | // 导出${table.classComment} Excel |
| 30 | 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 | 5 | export const columns: BasicColumn[] = [ |
| 6 | 6 | #foreach($column in $columns) |
| ... | ... | @@ -50,7 +50,7 @@ export const searchFormSchema: FormSchema[] = [ |
| 50 | 50 | field: '${javaField}', |
| 51 | 51 | #if ($column.htmlType == "input") |
| 52 | 52 | component: 'Input', |
| 53 | - #elseif ($column.htmlType == "select" || $column.htmlType == "radio") | |
| 53 | + #elseif ($column.htmlType == "select") | |
| 54 | 54 | component: 'Select', |
| 55 | 55 | componentProps: { |
| 56 | 56 | #if ("" != $dictType)## 设置了 dictType 数据字典的情况 |
| ... | ... | @@ -59,6 +59,15 @@ export const searchFormSchema: FormSchema[] = [ |
| 59 | 59 | options: [], |
| 60 | 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 | 71 | #elseif($column.htmlType == "datetime") |
| 63 | 72 | component: 'RangePicker', |
| 64 | 73 | #end |
| ... | ... | @@ -181,7 +190,8 @@ export const updateFormSchema: FormSchema[] = [ |
| 181 | 190 | fileType: 'file', |
| 182 | 191 | maxCount: 1, |
| 183 | 192 | }, |
| 184 | - #elseif($column.htmlType == "editor")## 文本编辑器component: 'Editor', | |
| 193 | + #elseif($column.htmlType == "editor")## 文本编辑器 | |
| 194 | + component: 'Editor', | |
| 185 | 195 | #elseif($column.htmlType == "select")## 下拉框 |
| 186 | 196 | component: 'Select', |
| 187 | 197 | componentProps: { | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/index.vue.vm
| 1 | 1 | <script lang="ts" setup> |
| 2 | -import ${ simpleClassName }Modal from './${simpleClassName}Modal.vue' | |
| 2 | +import ${simpleClassName}Modal from './${simpleClassName}Modal.vue' | |
| 3 | 3 | import { columns, searchFormSchema } from './${classNameVar}.data' |
| 4 | 4 | import { useI18n } from '@/hooks/web/useI18n' |
| 5 | 5 | import { useMessage } from '@/hooks/web/useMessage' |
| 6 | 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 | 10 | defineOptions({ name: '${table.className}' }) |
| 12 | 11 | |
| ... | ... | @@ -16,7 +15,7 @@ const [registerModal, { openModal }] = useModal() |
| 16 | 15 | |
| 17 | 16 | const [registerTable, { getForm, reload }] = useTable({ |
| 18 | 17 | title: '${table.classComment}列表', |
| 19 | - api: get${ simpleClassName }Page, | |
| 18 | + api: get${simpleClassName}Page, | |
| 20 | 19 | columns, |
| 21 | 20 | formConfig: { labelWidth: 120, schemas: searchFormSchema }, |
| 22 | 21 | useSearchForm: true, |
| ... | ... | @@ -43,14 +42,14 @@ async function handleExport() { |
| 43 | 42 | iconType: 'warning', |
| 44 | 43 | content: t('common.exportMessage'), |
| 45 | 44 | async onOk() { |
| 46 | - await export${ simpleClassName } (getForm().getFieldsValue()) | |
| 45 | + await export${simpleClassName}(getForm().getFieldsValue()) | |
| 47 | 46 | createMessage.success(t('common.exportSuccessText')) |
| 48 | 47 | }, |
| 49 | 48 | }) |
| 50 | 49 | } |
| 51 | 50 | |
| 52 | 51 | async function handleDelete(record: Recordable) { |
| 53 | - await delete${ simpleClassName } (record.id) | |
| 52 | + await delete${simpleClassName}(record.id) | |
| 54 | 53 | createMessage.success(t('common.delSuccessText')) |
| 55 | 54 | reload() |
| 56 | 55 | } |
| ... | ... | @@ -62,7 +61,7 @@ async function handleDelete(record: Recordable) { |
| 62 | 61 | <a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate"> |
| 63 | 62 | {{ t('action.create') }} |
| 64 | 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 | 65 | {{ t('action.export') }} |
| 67 | 66 | </a-button> |
| 68 | 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 | 258 | Long id = fileConfig.getId(); |
| 259 | 259 | // mock 获得 Client |
| 260 | 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 | 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 | 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 | 2 | |
| 3 | 3 | import lombok.Data; |
| 4 | 4 | |
| 5 | +import javax.validation.constraints.NotNull; | |
| 5 | 6 | import java.util.List; |
| 6 | 7 | |
| 7 | 8 | /** |
| ... | ... | @@ -15,6 +16,7 @@ public class ProductCommentCreateReqDTO { |
| 15 | 16 | /** |
| 16 | 17 | * 商品 SKU 编号 |
| 17 | 18 | */ |
| 19 | + @NotNull(message = "商品 SKU 编号不能为空") | |
| 18 | 20 | private Long skuId; |
| 19 | 21 | /** |
| 20 | 22 | * 订单编号 |
| ... | ... | @@ -26,20 +28,19 @@ public class ProductCommentCreateReqDTO { |
| 26 | 28 | private Long orderItemId; |
| 27 | 29 | |
| 28 | 30 | /** |
| 29 | - * 评分星级 1-5 分 | |
| 30 | - */ | |
| 31 | - private Integer scores; | |
| 32 | - /** | |
| 33 | 31 | * 描述星级 1-5 分 |
| 34 | 32 | */ |
| 33 | + @NotNull(message = "描述星级不能为空") | |
| 35 | 34 | private Integer descriptionScores; |
| 36 | 35 | /** |
| 37 | 36 | * 服务星级 1-5 分 |
| 38 | 37 | */ |
| 38 | + @NotNull(message = "服务星级不能为空") | |
| 39 | 39 | private Integer benefitScores; |
| 40 | 40 | /** |
| 41 | 41 | * 评论内容 |
| 42 | 42 | */ |
| 43 | + @NotNull(message = "评论内容不能为空") | |
| 43 | 44 | private String content; |
| 44 | 45 | /** |
| 45 | 46 | * 评论图片地址数组,以逗号分隔最多上传 9 张 |
| ... | ... | @@ -49,11 +50,12 @@ public class ProductCommentCreateReqDTO { |
| 49 | 50 | /** |
| 50 | 51 | * 是否匿名 |
| 51 | 52 | */ |
| 53 | + @NotNull(message = "是否匿名不能为空") | |
| 52 | 54 | private Boolean anonymous; |
| 53 | 55 | /** |
| 54 | 56 | * 评价人 |
| 55 | 57 | */ |
| 58 | + @NotNull(message = "评价人不能为空") | |
| 56 | 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 | 3 | import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | -import java.util.List; | |
| 7 | - | |
| 8 | 6 | // TODO @LeeYan9: ProductSpuRespDTO |
| 9 | 7 | /** |
| 10 | 8 | * 商品 SPU 信息 Response DTO |
| ... | ... | @@ -27,55 +25,22 @@ public class ProductSpuRespDTO { |
| 27 | 25 | */ |
| 28 | 26 | private String name; |
| 29 | 27 | /** |
| 30 | - * 关键字 | |
| 31 | - */ | |
| 32 | - private String keyword; | |
| 33 | - /** | |
| 34 | 28 | * 单位 |
| 35 | 29 | * |
| 36 | 30 | * 对应 product_unit 数据字典 |
| 37 | 31 | */ |
| 38 | 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 | 37 | private Long categoryId; |
| 57 | 38 | /** |
| 58 | - * 商品品牌编号 | |
| 59 | - */ | |
| 60 | - private Long brandId; | |
| 61 | - /** | |
| 62 | 39 | * 商品封面图 |
| 63 | 40 | */ |
| 64 | 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 | 45 | * <p> |
| 81 | 46 | * 枚举 {@link ProductSpuStatusEnum} |
| ... | ... | @@ -124,22 +89,6 @@ public class ProductSpuRespDTO { |
| 124 | 89 | */ |
| 125 | 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 | 1 | package cn.iocoder.yudao.module.product.api.sku; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 5 | 4 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 6 | 5 | import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; |
| ... | ... | @@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated; |
| 11 | 10 | |
| 12 | 11 | import javax.annotation.Resource; |
| 13 | 12 | import java.util.Collection; |
| 14 | -import java.util.Collections; | |
| 15 | 13 | import java.util.List; |
| 16 | 14 | |
| 17 | 15 | /** |
| ... | ... | @@ -35,18 +33,12 @@ public class ProductSkuApiImpl implements ProductSkuApi { |
| 35 | 33 | |
| 36 | 34 | @Override |
| 37 | 35 | public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) { |
| 38 | - if (CollUtil.isEmpty(ids)) { | |
| 39 | - return Collections.emptyList(); | |
| 40 | - } | |
| 41 | 36 | List<ProductSkuDO> skus = productSkuService.getSkuList(ids); |
| 42 | 37 | return ProductSkuConvert.INSTANCE.convertList04(skus); |
| 43 | 38 | } |
| 44 | 39 | |
| 45 | 40 | @Override |
| 46 | 41 | public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) { |
| 47 | - if (CollUtil.isEmpty(spuIds)) { | |
| 48 | - return Collections.emptyList(); | |
| 49 | - } | |
| 50 | 42 | List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds); |
| 51 | 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 | 27 | |
| 28 | 28 | @Override |
| 29 | 29 | public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) { |
| 30 | - if (CollectionUtil.isEmpty(ids)) { | |
| 31 | - return Collections.emptyList(); | |
| 32 | - } | |
| 33 | 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 | 1 | package cn.iocoder.yudao.module.product.convert.property; |
| 2 | 2 | |
| 3 | 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 | 4 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; |
| 8 | 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; |
| 9 | 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 | 7 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; |
| 12 | -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; | |
| 13 | 8 | import org.mapstruct.Mapper; |
| 14 | 9 | import org.mapstruct.factory.Mappers; |
| 15 | 10 | |
| 16 | 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 | 14 | * 属性值 Convert |
| ... | ... | @@ -38,18 +30,4 @@ public interface ProductPropertyValueConvert { |
| 38 | 30 | |
| 39 | 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 | 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; |
| 7 | 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 | 9 | import java.util.Collection; |
| 11 | 10 | import java.util.List; |
| ... | ... | @@ -57,14 +56,6 @@ public interface ProductPropertyValueService { |
| 57 | 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 | 61 | * @param propertyId 属性项编号数 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.product.service.property; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 4 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; |
| 6 | 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; |
| 7 | 6 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; |
| 8 | 7 | import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert; |
| 9 | -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | |
| 10 | 8 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; |
| 11 | 9 | import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; |
| 12 | -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; | |
| 13 | 10 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; |
| 14 | 11 | import org.springframework.context.annotation.Lazy; |
| 15 | 12 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -17,11 +14,9 @@ import org.springframework.validation.annotation.Validated; |
| 17 | 14 | |
| 18 | 15 | import javax.annotation.Resource; |
| 19 | 16 | import java.util.Collection; |
| 20 | -import java.util.Collections; | |
| 21 | 17 | import java.util.List; |
| 22 | 18 | |
| 23 | 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 | 20 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS; |
| 26 | 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 | 95 | } |
| 101 | 96 | |
| 102 | 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 | 98 | public Integer getPropertyValueCountByPropertyId(Long propertyId) { |
| 121 | 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 | 153 | |
| 154 | 154 | @Override |
| 155 | 155 | public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) { |
| 156 | + if (CollUtil.isEmpty(spuIds)) { | |
| 157 | + return Collections.emptyList(); | |
| 158 | + } | |
| 156 | 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 | 188 | |
| 189 | 189 | @Override |
| 190 | 190 | public List<ProductSpuDO> getSpuList(Collection<Long> ids) { |
| 191 | + if (CollUtil.isEmpty(ids)) { | |
| 192 | + return Collections.emptyList(); | |
| 193 | + } | |
| 191 | 194 | return productSpuMapper.selectBatchIds(ids); |
| 192 | 195 | } |
| 193 | 196 | ... | ... |
yudao-module-mall/yudao-module-promotion-api/pom.xml
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java deleted
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 | 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 | 118 | |
| 119 | 119 | // ========== 装修模板 1-013-017-000 ========== |
| 120 | 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 | 124 | // ========== 装修页面 1-013-018-000 ========== |
| 124 | 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 | 14 | <name>${project.artifactId}</name> |
| 15 | 15 | |
| 16 | 16 | <description> |
| 17 | - market模块,主要实现营销相关功能 | |
| 18 | - 例如:营销活动、banner广告、优惠券、优惠码等功能。 | |
| 17 | + promotion 模块,主要实现营销相关功能 | |
| 18 | + 例如:营销活动、banner 广告、优惠券、优惠码等功能。 | |
| 19 | 19 | </description> |
| 20 | 20 | |
| 21 | 21 | <dependencies> |
| ... | ... | @@ -49,10 +49,6 @@ |
| 49 | 49 | <groupId>cn.iocoder.boot</groupId> |
| 50 | 50 | <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> |
| 51 | 51 | </dependency> |
| 52 | - <dependency> | |
| 53 | - <groupId>cn.iocoder.boot</groupId> | |
| 54 | - <artifactId>yudao-spring-boot-starter-biz-weixin</artifactId> | |
| 55 | - </dependency> | |
| 56 | 52 | |
| 57 | 53 | <!-- Web 相关 --> |
| 58 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; |
| 4 | 4 | import org.springframework.stereotype.Service; |
| 5 | +import org.springframework.validation.annotation.Validated; | |
| 5 | 6 | |
| 6 | 7 | import javax.annotation.Resource; |
| 7 | 8 | |
| ... | ... | @@ -11,6 +12,7 @@ import javax.annotation.Resource; |
| 11 | 12 | * @author HUIHUI |
| 12 | 13 | */ |
| 13 | 14 | @Service |
| 15 | +@Validated | |
| 14 | 16 | public class BargainActivityApiImpl implements BargainActivityApi { |
| 15 | 17 | |
| 16 | 18 | @Resource | ... | ... |