Commit ffb0358ce23ecf5d0f53ebb977a0d6fe81df5af7
Merge remote-tracking branch 'origin/master' into feature/springdoc
Showing
182 changed files
with
6620 additions
and
809 deletions
README.md
| @@ -91,6 +91,7 @@ | @@ -91,6 +91,7 @@ | ||
| 91 | | 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | | 91 | | 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | |
| 92 | | | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | | 92 | | | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | |
| 93 | | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | | 93 | | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | |
| 94 | +| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 | | ||
| 94 | | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | | 95 | | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | |
| 95 | | ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | | 96 | | ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | |
| 96 | | 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | | 97 | | 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | |
sql/mysql/ruoyi-vue-pro.sql
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | Target Server Version : 80026 | 11 | Target Server Version : 80026 |
| 12 | File Encoding : 65001 | 12 | File Encoding : 65001 |
| 13 | 13 | ||
| 14 | - Date: 17/01/2023 23:47:35 | 14 | + Date: 27/01/2023 20:57:31 |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | SET NAMES utf8mb4; | 17 | SET NAMES utf8mb4; |
| @@ -300,7 +300,7 @@ CREATE TABLE `bpm_form` ( | @@ -300,7 +300,7 @@ CREATE TABLE `bpm_form` ( | ||
| 300 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 300 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 301 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 301 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 302 | PRIMARY KEY (`id`) USING BTREE | 302 | PRIMARY KEY (`id`) USING BTREE |
| 303 | -) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义'; | 303 | +) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义'; |
| 304 | 304 | ||
| 305 | -- ---------------------------- | 305 | -- ---------------------------- |
| 306 | -- Records of bpm_form | 306 | -- Records of bpm_form |
| @@ -329,7 +329,7 @@ CREATE TABLE `bpm_oa_leave` ( | @@ -329,7 +329,7 @@ CREATE TABLE `bpm_oa_leave` ( | ||
| 329 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 329 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 330 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 330 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 331 | PRIMARY KEY (`id`) USING BTREE | 331 | PRIMARY KEY (`id`) USING BTREE |
| 332 | -) ENGINE = InnoDB AUTO_INCREMENT = 33 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表'; | 332 | +) ENGINE = InnoDB AUTO_INCREMENT = 35 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表'; |
| 333 | 333 | ||
| 334 | -- ---------------------------- | 334 | -- ---------------------------- |
| 335 | -- Records of bpm_oa_leave | 335 | -- Records of bpm_oa_leave |
| @@ -359,7 +359,7 @@ CREATE TABLE `bpm_process_definition_ext` ( | @@ -359,7 +359,7 @@ CREATE TABLE `bpm_process_definition_ext` ( | ||
| 359 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 359 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 360 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 360 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 361 | PRIMARY KEY (`id`) USING BTREE | 361 | PRIMARY KEY (`id`) USING BTREE |
| 362 | -) ENGINE = InnoDB AUTO_INCREMENT = 135 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n'; | 362 | +) ENGINE = InnoDB AUTO_INCREMENT = 140 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n'; |
| 363 | 363 | ||
| 364 | -- ---------------------------- | 364 | -- ---------------------------- |
| 365 | -- Records of bpm_process_definition_ext | 365 | -- Records of bpm_process_definition_ext |
| @@ -389,7 +389,7 @@ CREATE TABLE `bpm_process_instance_ext` ( | @@ -389,7 +389,7 @@ CREATE TABLE `bpm_process_instance_ext` ( | ||
| 389 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 389 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 390 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 390 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 391 | PRIMARY KEY (`id`) USING BTREE | 391 | PRIMARY KEY (`id`) USING BTREE |
| 392 | -) ENGINE = InnoDB AUTO_INCREMENT = 290 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展'; | 392 | +) ENGINE = InnoDB AUTO_INCREMENT = 295 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展'; |
| 393 | 393 | ||
| 394 | -- ---------------------------- | 394 | -- ---------------------------- |
| 395 | -- Records of bpm_process_instance_ext | 395 | -- Records of bpm_process_instance_ext |
| @@ -415,7 +415,7 @@ CREATE TABLE `bpm_task_assign_rule` ( | @@ -415,7 +415,7 @@ CREATE TABLE `bpm_task_assign_rule` ( | ||
| 415 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 415 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 416 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 416 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 417 | PRIMARY KEY (`id`) USING BTREE | 417 | PRIMARY KEY (`id`) USING BTREE |
| 418 | -) ENGINE = InnoDB AUTO_INCREMENT = 265 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表'; | 418 | +) ENGINE = InnoDB AUTO_INCREMENT = 274 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表'; |
| 419 | 419 | ||
| 420 | -- ---------------------------- | 420 | -- ---------------------------- |
| 421 | -- Records of bpm_task_assign_rule | 421 | -- Records of bpm_task_assign_rule |
| @@ -444,7 +444,7 @@ CREATE TABLE `bpm_task_ext` ( | @@ -444,7 +444,7 @@ CREATE TABLE `bpm_task_ext` ( | ||
| 444 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 444 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 445 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 445 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 446 | PRIMARY KEY (`id`) USING BTREE | 446 | PRIMARY KEY (`id`) USING BTREE |
| 447 | -) ENGINE = InnoDB AUTO_INCREMENT = 341 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表'; | 447 | +) ENGINE = InnoDB AUTO_INCREMENT = 350 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表'; |
| 448 | 448 | ||
| 449 | -- ---------------------------- | 449 | -- ---------------------------- |
| 450 | -- Records of bpm_task_ext | 450 | -- Records of bpm_task_ext |
| @@ -469,7 +469,7 @@ CREATE TABLE `bpm_user_group` ( | @@ -469,7 +469,7 @@ CREATE TABLE `bpm_user_group` ( | ||
| 469 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 469 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 470 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 470 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 471 | PRIMARY KEY (`id`) USING BTREE | 471 | PRIMARY KEY (`id`) USING BTREE |
| 472 | -) ENGINE = InnoDB AUTO_INCREMENT = 111 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组'; | 472 | +) ENGINE = InnoDB AUTO_INCREMENT = 113 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组'; |
| 473 | 473 | ||
| 474 | -- ---------------------------- | 474 | -- ---------------------------- |
| 475 | -- Records of bpm_user_group | 475 | -- Records of bpm_user_group |
| @@ -546,7 +546,7 @@ CREATE TABLE `infra_api_error_log` ( | @@ -546,7 +546,7 @@ CREATE TABLE `infra_api_error_log` ( | ||
| 546 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 546 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 547 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 547 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 548 | PRIMARY KEY (`id`) USING BTREE | 548 | PRIMARY KEY (`id`) USING BTREE |
| 549 | -) ENGINE = InnoDB AUTO_INCREMENT = 931 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; | 549 | +) ENGINE = InnoDB AUTO_INCREMENT = 949 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; |
| 550 | 550 | ||
| 551 | -- ---------------------------- | 551 | -- ---------------------------- |
| 552 | -- Records of infra_api_error_log | 552 | -- Records of infra_api_error_log |
| @@ -584,7 +584,7 @@ CREATE TABLE `infra_codegen_column` ( | @@ -584,7 +584,7 @@ CREATE TABLE `infra_codegen_column` ( | ||
| 584 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 584 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 585 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 585 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 586 | PRIMARY KEY (`id`) USING BTREE | 586 | PRIMARY KEY (`id`) USING BTREE |
| 587 | -) ENGINE = InnoDB AUTO_INCREMENT = 1533 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; | 587 | +) ENGINE = InnoDB AUTO_INCREMENT = 1582 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; |
| 588 | 588 | ||
| 589 | -- ---------------------------- | 589 | -- ---------------------------- |
| 590 | -- Records of infra_codegen_column | 590 | -- Records of infra_codegen_column |
| @@ -616,7 +616,7 @@ CREATE TABLE `infra_codegen_table` ( | @@ -616,7 +616,7 @@ CREATE TABLE `infra_codegen_table` ( | ||
| 616 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 616 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 617 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 617 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 618 | PRIMARY KEY (`id`) USING BTREE | 618 | PRIMARY KEY (`id`) USING BTREE |
| 619 | -) ENGINE = InnoDB AUTO_INCREMENT = 119 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; | 619 | +) ENGINE = InnoDB AUTO_INCREMENT = 122 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; |
| 620 | 620 | ||
| 621 | -- ---------------------------- | 621 | -- ---------------------------- |
| 622 | -- Records of infra_codegen_table | 622 | -- Records of infra_codegen_table |
| @@ -699,7 +699,7 @@ CREATE TABLE `infra_file` ( | @@ -699,7 +699,7 @@ CREATE TABLE `infra_file` ( | ||
| 699 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 699 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 700 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 700 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 701 | PRIMARY KEY (`id`) USING BTREE | 701 | PRIMARY KEY (`id`) USING BTREE |
| 702 | -) ENGINE = InnoDB AUTO_INCREMENT = 355 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; | 702 | +) ENGINE = InnoDB AUTO_INCREMENT = 356 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; |
| 703 | 703 | ||
| 704 | -- ---------------------------- | 704 | -- ---------------------------- |
| 705 | -- Records of infra_file | 705 | -- Records of infra_file |
| @@ -1191,7 +1191,7 @@ CREATE TABLE `system_dict_data` ( | @@ -1191,7 +1191,7 @@ CREATE TABLE `system_dict_data` ( | ||
| 1191 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 1191 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 1192 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 1192 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1193 | PRIMARY KEY (`id`) USING BTREE | 1193 | PRIMARY KEY (`id`) USING BTREE |
| 1194 | -) ENGINE = InnoDB AUTO_INCREMENT = 1213 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; | 1194 | +) ENGINE = InnoDB AUTO_INCREMENT = 1227 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; |
| 1195 | 1195 | ||
| 1196 | -- ---------------------------- | 1196 | -- ---------------------------- |
| 1197 | -- Records of system_dict_data | 1197 | -- Records of system_dict_data |
| @@ -1391,6 +1391,10 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st | @@ -1391,6 +1391,10 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st | ||
| 1391 | 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 (1220, 8, '地理位置', 'location', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 地理位置', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:23:51', b'0'); | 1391 | 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 (1220, 8, '地理位置', 'location', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 地理位置', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:23:51', b'0'); |
| 1392 | 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 (1221, 9, '链接', 'link', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 链接', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:24:49', b'0'); | 1392 | 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 (1221, 9, '链接', 'link', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 链接', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:24:49', b'0'); |
| 1393 | 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 (1222, 10, '事件', 'event', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 事件', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:24:49', b'0'); | 1393 | 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 (1222, 10, '事件', 'event', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 事件', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:24:49', b'0'); |
| 1394 | +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 (1223, 0, '初始化', '0', 'system_mail_send_status', 0, 'primary', '', '邮件发送状态 - 初始化\n', '1', '2023-01-26 09:53:49', '1', '2023-01-26 16:36:14', b'0'); | ||
| 1395 | +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 (1224, 10, '发送成功', '10', 'system_mail_send_status', 0, 'success', '', '邮件发送状态 - 发送成功', '1', '2023-01-26 09:54:28', '1', '2023-01-26 16:36:22', b'0'); | ||
| 1396 | +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 (1225, 20, '发送失败', '20', 'system_mail_send_status', 0, 'danger', '', '邮件发送状态 - 发送失败', '1', '2023-01-26 09:54:50', '1', '2023-01-26 16:36:26', b'0'); | ||
| 1397 | +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 (1226, 30, '不发送', '30', 'system_mail_send_status', 0, 'info', '', '邮件发送状态 - 不发送', '1', '2023-01-26 09:55:06', '1', '2023-01-26 16:36:36', b'0'); | ||
| 1394 | COMMIT; | 1398 | COMMIT; |
| 1395 | 1399 | ||
| 1396 | -- ---------------------------- | 1400 | -- ---------------------------- |
| @@ -1411,7 +1415,7 @@ CREATE TABLE `system_dict_type` ( | @@ -1411,7 +1415,7 @@ CREATE TABLE `system_dict_type` ( | ||
| 1411 | `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', | 1415 | `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', |
| 1412 | PRIMARY KEY (`id`) USING BTREE, | 1416 | PRIMARY KEY (`id`) USING BTREE, |
| 1413 | UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE | 1417 | UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE |
| 1414 | -) ENGINE = InnoDB AUTO_INCREMENT = 165 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; | 1418 | +) ENGINE = InnoDB AUTO_INCREMENT = 167 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; |
| 1415 | 1419 | ||
| 1416 | -- ---------------------------- | 1420 | -- ---------------------------- |
| 1417 | -- Records of system_dict_type | 1421 | -- Records of system_dict_type |
| @@ -1474,6 +1478,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat | @@ -1474,6 +1478,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat | ||
| 1474 | INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (163, '交易订单项的售后状态', 'trade_order_item_after_sale_status', 0, '交易订单项的售后状态', '1', '2022-12-10 20:58:08', '1', '2022-12-10 20:58:08', b'0', NULL); | 1478 | INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (163, '交易订单项的售后状态', 'trade_order_item_after_sale_status', 0, '交易订单项的售后状态', '1', '2022-12-10 20:58:08', '1', '2022-12-10 20:58:08', b'0', NULL); |
| 1475 | INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (164, '公众号自动回复的请求关键字匹配模式', 'mp_auto_reply_request_match', 0, '公众号自动回复的请求关键字匹配模式', '1', '2023-01-16 23:29:56', '1', '2023-01-16 23:29:56', b'0', '1970-01-01 00:00:00'); | 1479 | INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (164, '公众号自动回复的请求关键字匹配模式', 'mp_auto_reply_request_match', 0, '公众号自动回复的请求关键字匹配模式', '1', '2023-01-16 23:29:56', '1', '2023-01-16 23:29:56', b'0', '1970-01-01 00:00:00'); |
| 1476 | INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (165, '公众号的消息类型', 'mp_message_type', 0, '公众号的消息类型', '1', '2023-01-17 22:17:09', '1', '2023-01-17 22:17:09', b'0', '1970-01-01 00:00:00'); | 1480 | INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (165, '公众号的消息类型', 'mp_message_type', 0, '公众号的消息类型', '1', '2023-01-17 22:17:09', '1', '2023-01-17 22:17:09', b'0', '1970-01-01 00:00:00'); |
| 1481 | +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (166, '邮件发送状态', 'system_mail_send_status', 0, '邮件发送状态', '1', '2023-01-26 09:53:13', '1', '2023-01-26 09:53:13', b'0', '1970-01-01 00:00:00'); | ||
| 1477 | COMMIT; | 1482 | COMMIT; |
| 1478 | 1483 | ||
| 1479 | -- ---------------------------- | 1484 | -- ---------------------------- |
| @@ -1522,7 +1527,7 @@ CREATE TABLE `system_login_log` ( | @@ -1522,7 +1527,7 @@ CREATE TABLE `system_login_log` ( | ||
| 1522 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 1527 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1523 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 1528 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 1524 | PRIMARY KEY (`id`) USING BTREE | 1529 | PRIMARY KEY (`id`) USING BTREE |
| 1525 | -) ENGINE = InnoDB AUTO_INCREMENT = 1963 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; | 1530 | +) ENGINE = InnoDB AUTO_INCREMENT = 1980 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; |
| 1526 | 1531 | ||
| 1527 | -- ---------------------------- | 1532 | -- ---------------------------- |
| 1528 | -- Records of system_login_log | 1533 | -- Records of system_login_log |
| @@ -1531,6 +1536,102 @@ BEGIN; | @@ -1531,6 +1536,102 @@ BEGIN; | ||
| 1531 | COMMIT; | 1536 | COMMIT; |
| 1532 | 1537 | ||
| 1533 | -- ---------------------------- | 1538 | -- ---------------------------- |
| 1539 | +-- Table structure for system_mail_account | ||
| 1540 | +-- ---------------------------- | ||
| 1541 | +DROP TABLE IF EXISTS `system_mail_account`; | ||
| 1542 | +CREATE TABLE `system_mail_account` ( | ||
| 1543 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', | ||
| 1544 | + `mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮箱', | ||
| 1545 | + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名', | ||
| 1546 | + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码', | ||
| 1547 | + `host` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'SMTP 服务器域名', | ||
| 1548 | + `port` int NOT NULL COMMENT 'SMTP 服务器端口', | ||
| 1549 | + `ssl_enable` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否开启 SSL', | ||
| 1550 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | ||
| 1551 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 1552 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | ||
| 1553 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 1554 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||
| 1555 | + PRIMARY KEY (`id`) USING BTREE | ||
| 1556 | +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮箱账号表'; | ||
| 1557 | + | ||
| 1558 | +-- ---------------------------- | ||
| 1559 | +-- Records of system_mail_account | ||
| 1560 | +-- ---------------------------- | ||
| 1561 | +BEGIN; | ||
| 1562 | +INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '7684413@qq.com', '7684413@qq.com', '123457', '127.0.0.1', 8080, b'0', '1', '2023-01-25 17:39:52', '1', '2023-01-26 22:59:04', b'0'); | ||
| 1563 | +INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'ydym_test@163.com', 'ydym_test@163.com', 'WBZTEINMIFVRYSOE', 'smtp.163.com', 465, b'1', '1', '2023-01-26 01:26:03', '1', '2023-01-26 01:26:03', b'0'); | ||
| 1564 | +INSERT INTO `system_mail_account` (`id`, `mail`, `username`, `password`, `host`, `port`, `ssl_enable`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, '76854114@qq.com', '3335', '11234', 'yunai1.cn', 466, b'0', '1', '2023-01-27 15:06:38', '1', '2023-01-27 07:08:36', b'1'); | ||
| 1565 | +COMMIT; | ||
| 1566 | + | ||
| 1567 | +-- ---------------------------- | ||
| 1568 | +-- Table structure for system_mail_log | ||
| 1569 | +-- ---------------------------- | ||
| 1570 | +DROP TABLE IF EXISTS `system_mail_log`; | ||
| 1571 | +CREATE TABLE `system_mail_log` ( | ||
| 1572 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | ||
| 1573 | + `user_id` bigint NULL DEFAULT NULL COMMENT '用户编号', | ||
| 1574 | + `user_type` tinyint NULL DEFAULT NULL COMMENT '用户类型', | ||
| 1575 | + `to_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收邮箱地址', | ||
| 1576 | + `account_id` bigint NOT NULL COMMENT '邮箱账号编号', | ||
| 1577 | + `from_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '发送邮箱地址', | ||
| 1578 | + `template_id` bigint NOT NULL COMMENT '模板编号', | ||
| 1579 | + `template_code` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板编码', | ||
| 1580 | + `template_nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '模版发送人名称', | ||
| 1581 | + `template_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件标题', | ||
| 1582 | + `template_content` varchar(10240) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件内容', | ||
| 1583 | + `template_params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '邮件参数', | ||
| 1584 | + `send_status` tinyint NOT NULL DEFAULT 0 COMMENT '发送状态', | ||
| 1585 | + `send_time` datetime NULL DEFAULT NULL COMMENT '发送时间', | ||
| 1586 | + `send_message_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发送返回的消息 ID', | ||
| 1587 | + `send_exception` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发送异常', | ||
| 1588 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | ||
| 1589 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 1590 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | ||
| 1591 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 1592 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||
| 1593 | + PRIMARY KEY (`id`) USING BTREE | ||
| 1594 | +) ENGINE = InnoDB AUTO_INCREMENT = 354 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表'; | ||
| 1595 | + | ||
| 1596 | +-- ---------------------------- | ||
| 1597 | +-- Records of system_mail_log | ||
| 1598 | +-- ---------------------------- | ||
| 1599 | +BEGIN; | ||
| 1600 | +COMMIT; | ||
| 1601 | + | ||
| 1602 | +-- ---------------------------- | ||
| 1603 | +-- Table structure for system_mail_template | ||
| 1604 | +-- ---------------------------- | ||
| 1605 | +DROP TABLE IF EXISTS `system_mail_template`; | ||
| 1606 | +CREATE TABLE `system_mail_template` ( | ||
| 1607 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | ||
| 1608 | + `name` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板名称', | ||
| 1609 | + `code` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板编码', | ||
| 1610 | + `account_id` bigint NOT NULL COMMENT '发送的邮箱账号编号', | ||
| 1611 | + `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发送人名称', | ||
| 1612 | + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板标题', | ||
| 1613 | + `content` varchar(10240) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板内容', | ||
| 1614 | + `params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '参数数组', | ||
| 1615 | + `status` tinyint NOT NULL COMMENT '开启状态', | ||
| 1616 | + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', | ||
| 1617 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | ||
| 1618 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 1619 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | ||
| 1620 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 1621 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||
| 1622 | + PRIMARY KEY (`id`) USING BTREE | ||
| 1623 | +) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件模版表'; | ||
| 1624 | + | ||
| 1625 | +-- ---------------------------- | ||
| 1626 | +-- Records of system_mail_template | ||
| 1627 | +-- ---------------------------- | ||
| 1628 | +BEGIN; | ||
| 1629 | +INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (13, '后台用户短信登录', 'admin-sms-login', 1, '奥特曼', '你猜我猜', '<p>您的验证码是{code},名字是{name}</p>', '[\"code\",\"name\"]', 0, '3', '1', '2021-10-11 08:10:00', '1', '2023-01-26 23:22:05', b'0'); | ||
| 1630 | +INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (14, '测试模版', 'test_01', 2, '芋艿', '一个标题', '<p>你是 {key01} 吗?</p><p><br></p><p>是的话,赶紧 {key02} 一下!</p>', '[\"key01\",\"key02\"]', 0, NULL, '1', '2023-01-26 01:27:40', '1', '2023-01-27 10:32:16', b'0'); | ||
| 1631 | +INSERT INTO `system_mail_template` (`id`, `name`, `code`, `account_id`, `nickname`, `title`, `content`, `params`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (15, '3', '2', 2, '7', '4', '<p>45</p>', '[]', 1, '80', '1', '2023-01-27 15:50:35', '1', '2023-01-27 16:34:49', b'0'); | ||
| 1632 | +COMMIT; | ||
| 1633 | + | ||
| 1634 | +-- ---------------------------- | ||
| 1534 | -- Table structure for system_menu | 1635 | -- Table structure for system_menu |
| 1535 | -- ---------------------------- | 1636 | -- ---------------------------- |
| 1536 | DROP TABLE IF EXISTS `system_menu`; | 1637 | DROP TABLE IF EXISTS `system_menu`; |
| @@ -1553,7 +1654,7 @@ CREATE TABLE `system_menu` ( | @@ -1553,7 +1654,7 @@ CREATE TABLE `system_menu` ( | ||
| 1553 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 1654 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 1554 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 1655 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1555 | PRIMARY KEY (`id`) USING BTREE | 1656 | PRIMARY KEY (`id`) USING BTREE |
| 1556 | -) ENGINE = InnoDB AUTO_INCREMENT = 2125 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; | 1657 | +) ENGINE = InnoDB AUTO_INCREMENT = 2144 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; |
| 1557 | 1658 | ||
| 1558 | -- ---------------------------- | 1659 | -- ---------------------------- |
| 1559 | -- Records of system_menu | 1660 | -- Records of system_menu |
| @@ -1776,7 +1877,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i | @@ -1776,7 +1877,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i | ||
| 1776 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1250, '敏感词更新', 'system:sensitive-word:update', 3, 3, 1247, '', '', '', 0, b'1', b'1', '', '2022-04-07 16:55:03', '', '2022-04-20 17:03:10', b'0'); | 1877 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1250, '敏感词更新', 'system:sensitive-word:update', 3, 3, 1247, '', '', '', 0, b'1', b'1', '', '2022-04-07 16:55:03', '', '2022-04-20 17:03:10', b'0'); |
| 1777 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1251, '敏感词删除', 'system:sensitive-word:delete', 3, 4, 1247, '', '', '', 0, b'1', b'1', '', '2022-04-07 16:55:03', '', '2022-04-20 17:03:10', b'0'); | 1878 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1251, '敏感词删除', 'system:sensitive-word:delete', 3, 4, 1247, '', '', '', 0, b'1', b'1', '', '2022-04-07 16:55:03', '', '2022-04-20 17:03:10', b'0'); |
| 1778 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1252, '敏感词导出', 'system:sensitive-word:export', 3, 5, 1247, '', '', '', 0, b'1', b'1', '', '2022-04-07 16:55:03', '', '2022-04-20 17:03:10', b'0'); | 1879 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1252, '敏感词导出', 'system:sensitive-word:export', 3, 5, 1247, '', '', '', 0, b'1', b'1', '', '2022-04-07 16:55:03', '', '2022-04-20 17:03:10', b'0'); |
| 1779 | -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1254, '作者动态', '', 1, 0, 0, 'https://www.iocoder.cn', 'people', NULL, 0, b'1', b'1', '1', '2022-04-23 01:03:15', '1', '2022-06-22 13:35:05', b'0'); | 1880 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1254, '作者动态', '', 1, 0, 0, 'https://www.iocoder.cn', 'people', NULL, 0, b'1', b'1', '1', '2022-04-23 01:03:15', '1', '2023-01-25 20:05:55', b'0'); |
| 1780 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1255, '数据源配置', '', 2, 1, 2, 'data-source-config', 'rate', 'infra/dataSourceConfig/index', 0, b'1', b'1', '', '2022-04-27 14:37:32', '1', '2022-04-27 22:42:06', b'0'); | 1881 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1255, '数据源配置', '', 2, 1, 2, 'data-source-config', 'rate', 'infra/dataSourceConfig/index', 0, b'1', b'1', '', '2022-04-27 14:37:32', '1', '2022-04-27 22:42:06', b'0'); |
| 1781 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1256, '数据源配置查询', 'infra:data-source-config:query', 3, 1, 1255, '', '', '', 0, b'1', b'1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', b'0'); | 1882 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1256, '数据源配置查询', 'infra:data-source-config:query', 3, 1, 1255, '', '', '', 0, b'1', b'1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', b'0'); |
| 1782 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1257, '数据源配置创建', 'infra:data-source-config:create', 3, 2, 1255, '', '', '', 0, b'1', b'1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', b'0'); | 1883 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1257, '数据源配置创建', 'infra:data-source-config:create', 3, 2, 1255, '', '', '', 0, b'1', b'1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', b'0'); |
| @@ -1908,6 +2009,20 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i | @@ -1908,6 +2009,20 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i | ||
| 1908 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2127, '删除菜单', 'mp:menu:delete', 3, 2, 2119, '', '', '', 0, b'1', b'1', '1', '2023-01-17 23:06:16', '1', '2023-01-17 23:06:16', b'0'); | 2009 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2127, '删除菜单', 'mp:menu:delete', 3, 2, 2119, '', '', '', 0, b'1', b'1', '1', '2023-01-17 23:06:16', '1', '2023-01-17 23:06:16', b'0'); |
| 1909 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2128, '查询消息', 'mp:message:query', 3, 0, 2103, '', '', '', 0, b'1', b'1', '1', '2023-01-17 23:07:14', '1', '2023-01-17 23:07:14', b'0'); | 2010 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2128, '查询消息', 'mp:message:query', 3, 0, 2103, '', '', '', 0, b'1', b'1', '1', '2023-01-17 23:07:14', '1', '2023-01-17 23:07:14', b'0'); |
| 1910 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2129, '发送消息', 'mp:message:send', 3, 1, 2103, '', '', '', 0, b'1', b'1', '1', '2023-01-17 23:07:26', '1', '2023-01-17 23:07:26', b'0'); | 2011 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2129, '发送消息', 'mp:message:send', 3, 1, 2103, '', '', '', 0, b'1', b'1', '1', '2023-01-17 23:07:26', '1', '2023-01-17 23:07:26', b'0'); |
| 2012 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2130, '邮箱管理', '', 2, 11, 1, 'mail', 'email', NULL, 0, b'1', b'1', '1', '2023-01-25 17:27:44', '1', '2023-01-25 17:27:44', b'0'); | ||
| 2013 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2131, '邮箱账号', '', 2, 0, 2130, 'mail-account', 'user', 'system/mail/account/index', 0, b'1', b'1', '', '2023-01-25 09:33:48', '1', '2023-01-26 16:37:37', b'0'); | ||
| 2014 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2132, '账号查询', 'system:mail-account:query', 3, 1, 2131, '', '', '', 0, b'1', b'1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', b'0'); | ||
| 2015 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2133, '账号创建', 'system:mail-account:create', 3, 2, 2131, '', '', '', 0, b'1', b'1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', b'0'); | ||
| 2016 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2134, '账号更新', 'system:mail-account:update', 3, 3, 2131, '', '', '', 0, b'1', b'1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', b'0'); | ||
| 2017 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2135, '账号删除', 'system:mail-account:delete', 3, 4, 2131, '', '', '', 0, b'1', b'1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', b'0'); | ||
| 2018 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2136, '邮件模版', '', 2, 0, 2130, 'mail-template', 'education', 'system/mail/template/index', 0, b'1', b'1', '', '2023-01-25 12:05:31', '1', '2023-01-26 16:38:35', b'0'); | ||
| 2019 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2137, '模版查询', 'system:mail-template:query', 3, 1, 2136, '', '', '', 0, b'1', b'1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', b'0'); | ||
| 2020 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2138, '模版创建', 'system:mail-template:create', 3, 2, 2136, '', '', '', 0, b'1', b'1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', b'0'); | ||
| 2021 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2139, '模版更新', 'system:mail-template:update', 3, 3, 2136, '', '', '', 0, b'1', b'1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', b'0'); | ||
| 2022 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2140, '模版删除', 'system:mail-template:delete', 3, 4, 2136, '', '', '', 0, b'1', b'1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', b'0'); | ||
| 2023 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2141, '邮件记录', '', 2, 0, 2130, 'mail-log', 'log', 'system/mail/log/index', 0, b'1', b'1', '', '2023-01-26 02:16:50', '1', '2023-01-26 16:38:27', b'0'); | ||
| 2024 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2142, '日志查询', 'system:mail-log:query', 3, 1, 2141, '', '', '', 0, b'1', b'1', '', '2023-01-26 02:16:50', '', '2023-01-26 02:16:50', b'0'); | ||
| 2025 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2143, '发送测试邮件', 'system:mail-template:send-mail', 3, 5, 2136, '', '', '', 0, b'1', b'1', '1', '2023-01-26 23:29:15', '1', '2023-01-26 23:29:15', b'0'); | ||
| 1911 | COMMIT; | 2026 | COMMIT; |
| 1912 | 2027 | ||
| 1913 | -- ---------------------------- | 2028 | -- ---------------------------- |
| @@ -1958,7 +2073,7 @@ CREATE TABLE `system_oauth2_access_token` ( | @@ -1958,7 +2073,7 @@ CREATE TABLE `system_oauth2_access_token` ( | ||
| 1958 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 2073 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1959 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 2074 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 1960 | PRIMARY KEY (`id`) USING BTREE | 2075 | PRIMARY KEY (`id`) USING BTREE |
| 1961 | -) ENGINE = InnoDB AUTO_INCREMENT = 1083 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; | 2076 | +) ENGINE = InnoDB AUTO_INCREMENT = 1214 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; |
| 1962 | 2077 | ||
| 1963 | -- ---------------------------- | 2078 | -- ---------------------------- |
| 1964 | -- Records of system_oauth2_access_token | 2079 | -- Records of system_oauth2_access_token |
| @@ -2080,7 +2195,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( | @@ -2080,7 +2195,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( | ||
| 2080 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 2195 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2081 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 2196 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2082 | PRIMARY KEY (`id`) USING BTREE | 2197 | PRIMARY KEY (`id`) USING BTREE |
| 2083 | -) ENGINE = InnoDB AUTO_INCREMENT = 571 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; | 2198 | +) ENGINE = InnoDB AUTO_INCREMENT = 588 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; |
| 2084 | 2199 | ||
| 2085 | -- ---------------------------- | 2200 | -- ---------------------------- |
| 2086 | -- Records of system_oauth2_refresh_token | 2201 | -- Records of system_oauth2_refresh_token |
| @@ -2120,7 +2235,7 @@ CREATE TABLE `system_operate_log` ( | @@ -2120,7 +2235,7 @@ CREATE TABLE `system_operate_log` ( | ||
| 2120 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 2235 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2121 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 2236 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2122 | PRIMARY KEY (`id`) USING BTREE | 2237 | PRIMARY KEY (`id`) USING BTREE |
| 2123 | -) ENGINE = InnoDB AUTO_INCREMENT = 4018 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; | 2238 | +) ENGINE = InnoDB AUTO_INCREMENT = 4177 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; |
| 2124 | 2239 | ||
| 2125 | -- ---------------------------- | 2240 | -- ---------------------------- |
| 2126 | -- Records of system_operate_log | 2241 | -- Records of system_operate_log |
| @@ -2212,7 +2327,7 @@ CREATE TABLE `system_role_menu` ( | @@ -2212,7 +2327,7 @@ CREATE TABLE `system_role_menu` ( | ||
| 2212 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 2327 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2213 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 2328 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2214 | PRIMARY KEY (`id`) USING BTREE | 2329 | PRIMARY KEY (`id`) USING BTREE |
| 2215 | -) ENGINE = InnoDB AUTO_INCREMENT = 1991 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表'; | 2330 | +) ENGINE = InnoDB AUTO_INCREMENT = 2185 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表'; |
| 2216 | 2331 | ||
| 2217 | -- ---------------------------- | 2332 | -- ---------------------------- |
| 2218 | -- Records of system_role_menu | 2333 | -- Records of system_role_menu |
| @@ -2628,6 +2743,194 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t | @@ -2628,6 +2743,194 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t | ||
| 2628 | INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1988, 118, 1018, '1', '2022-12-30 11:47:52', '1', '2022-12-30 11:47:52', b'0', 129); | 2743 | INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1988, 118, 1018, '1', '2022-12-30 11:47:52', '1', '2022-12-30 11:47:52', b'0', 129); |
| 2629 | INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1989, 118, 1019, '1', '2022-12-30 11:47:52', '1', '2022-12-30 11:47:52', b'0', 129); | 2744 | INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1989, 118, 1019, '1', '2022-12-30 11:47:52', '1', '2022-12-30 11:47:52', b'0', 129); |
| 2630 | INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1990, 118, 1020, '1', '2022-12-30 11:47:52', '1', '2022-12-30 11:47:52', b'0', 129); | 2745 | INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1990, 118, 1020, '1', '2022-12-30 11:47:52', '1', '2022-12-30 11:47:52', b'0', 129); |
| 2746 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1991, 2, 1024, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2747 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1992, 2, 1025, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2748 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1993, 2, 1026, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2749 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1994, 2, 1027, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2750 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1995, 2, 1028, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2751 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1996, 2, 1029, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2752 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1997, 2, 1030, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2753 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1998, 2, 1031, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2754 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1999, 2, 1032, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2755 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2000, 2, 1033, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2756 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2001, 2, 1034, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2757 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2002, 2, 1035, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2758 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2003, 2, 1036, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2759 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2004, 2, 1037, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2760 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2005, 2, 1038, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2761 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2006, 2, 1039, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2762 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2007, 2, 1040, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2763 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2008, 2, 1042, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2764 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2009, 2, 1043, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2765 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2010, 2, 1045, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2766 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2011, 2, 1046, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2767 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2012, 2, 1048, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2768 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2013, 2, 1050, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2769 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2014, 2, 1051, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2770 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2015, 2, 1052, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2771 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2016, 2, 1053, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2772 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2017, 2, 1054, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2773 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2018, 2, 1056, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2774 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2019, 2, 1057, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2775 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2020, 2, 1058, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2776 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2021, 2, 2083, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2777 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2022, 2, 1059, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2778 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2023, 2, 1060, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2779 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2024, 2, 1063, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2780 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2025, 2, 1064, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2781 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2026, 2, 1065, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2782 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2027, 2, 1066, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2783 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2028, 2, 1067, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2784 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2029, 2, 1070, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2785 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2030, 2, 1071, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2786 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2031, 2, 1072, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2787 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2032, 2, 1073, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2788 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2033, 2, 1074, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2789 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2034, 2, 1075, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2790 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2035, 2, 1076, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2791 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2036, 2, 1082, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2792 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2037, 2, 1085, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2793 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2038, 2, 1086, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2794 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2039, 2, 1087, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2795 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2040, 2, 1088, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2796 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2041, 2, 1089, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2797 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2042, 2, 1091, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2798 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2043, 2, 1092, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2799 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2044, 2, 1095, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2800 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2045, 2, 1096, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2801 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2046, 2, 1097, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2802 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2047, 2, 1098, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2803 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2048, 2, 1101, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2804 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2049, 2, 1102, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2805 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2050, 2, 1103, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2806 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2051, 2, 1104, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2807 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2052, 2, 1105, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2808 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2053, 2, 1106, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2809 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2054, 2, 1108, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2810 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2055, 2, 1109, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2811 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2056, 2, 1111, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2812 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2057, 2, 1112, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2813 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2058, 2, 1113, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2814 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2059, 2, 1114, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2815 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2060, 2, 1115, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2816 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2061, 2, 1127, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2817 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2062, 2, 1128, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2818 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2063, 2, 1129, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2819 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2064, 2, 1130, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2820 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2065, 2, 1131, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2821 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2066, 2, 1132, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2822 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2067, 2, 1133, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2823 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2068, 2, 1134, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2824 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2069, 2, 1135, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2825 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2070, 2, 1136, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2826 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2071, 2, 1137, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2827 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2072, 2, 114, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2828 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2073, 2, 1139, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2829 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2074, 2, 115, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2830 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2075, 2, 1140, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2831 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2076, 2, 116, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2832 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2077, 2, 1141, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2833 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2078, 2, 1142, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2834 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2079, 2, 1143, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2835 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2080, 2, 1150, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2836 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2081, 2, 1161, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2837 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2082, 2, 1162, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2838 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2083, 2, 1163, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2839 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2084, 2, 1164, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2840 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2085, 2, 1165, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2841 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2086, 2, 1166, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2842 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2087, 2, 1173, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2843 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2088, 2, 1174, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2844 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2089, 2, 1175, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2845 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2090, 2, 1176, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2846 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2091, 2, 1177, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2847 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2092, 2, 1178, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2848 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2093, 2, 1179, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2849 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2094, 2, 1180, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2850 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2095, 2, 1181, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2851 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2096, 2, 1182, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2852 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2097, 2, 1183, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2853 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2098, 2, 1184, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2854 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2099, 2, 1226, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2855 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2100, 2, 1227, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2856 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2101, 2, 1228, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2857 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2102, 2, 1229, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2858 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2103, 2, 1237, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2859 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2104, 2, 1238, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2860 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2105, 2, 1239, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2861 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2106, 2, 1240, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2862 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2107, 2, 1241, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2863 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2108, 2, 1242, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2864 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2109, 2, 1243, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2865 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2110, 2, 1247, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2866 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2111, 2, 1248, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2867 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2112, 2, 1249, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2868 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2113, 2, 1250, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2869 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2114, 2, 1251, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2870 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2115, 2, 1252, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2871 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2116, 2, 1254, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2872 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2117, 2, 1255, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2873 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2118, 2, 1256, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2874 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2119, 2, 1257, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2875 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2120, 2, 1258, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2876 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2121, 2, 1259, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2877 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2122, 2, 1260, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2878 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2123, 2, 1261, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2879 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2124, 2, 1263, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2880 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2125, 2, 1264, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2881 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2126, 2, 1265, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2882 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2127, 2, 1266, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2883 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2128, 2, 1267, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2884 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2129, 2, 1001, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2885 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2130, 2, 1002, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2886 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2131, 2, 1003, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2887 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2132, 2, 1004, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2888 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2133, 2, 1005, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2889 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2134, 2, 1006, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2890 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2135, 2, 1007, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2891 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2136, 2, 1008, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2892 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2137, 2, 1009, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2893 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2138, 2, 1010, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2894 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2139, 2, 1011, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2895 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2140, 2, 1012, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2896 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2141, 2, 1013, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2897 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2142, 2, 1014, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2898 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2143, 2, 1015, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2899 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2144, 2, 1016, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2900 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2145, 2, 1017, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2901 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2146, 2, 1018, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2902 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2147, 2, 1019, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2903 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2148, 2, 1020, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2904 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2149, 2, 1021, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2905 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2150, 2, 1022, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2906 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2151, 2, 1023, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); | ||
| 2907 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2152, 2, 1281, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2908 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2153, 2, 1282, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2909 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2154, 2, 2000, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2910 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2155, 2, 2002, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2911 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2156, 2, 2003, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2912 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2157, 2, 2004, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2913 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2158, 2, 2005, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2914 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2159, 2, 2006, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2915 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2160, 2, 2008, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2916 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2161, 2, 2009, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2917 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2162, 2, 2010, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2918 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2163, 2, 2011, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2919 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2164, 2, 2012, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2920 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2170, 2, 2019, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2921 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2171, 2, 2020, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2922 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2172, 2, 2021, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2923 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2173, 2, 2022, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2924 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2174, 2, 2023, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2925 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2175, 2, 2025, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2926 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2177, 2, 2027, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2927 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2178, 2, 2028, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2928 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2179, 2, 2029, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', b'0', 1); | ||
| 2929 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2180, 2, 2014, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1); | ||
| 2930 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2181, 2, 2015, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1); | ||
| 2931 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2182, 2, 2016, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1); | ||
| 2932 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2183, 2, 2017, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1); | ||
| 2933 | +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2184, 2, 2018, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', b'0', 1); | ||
| 2631 | COMMIT; | 2934 | COMMIT; |
| 2632 | 2935 | ||
| 2633 | -- ---------------------------- | 2936 | -- ---------------------------- |
| @@ -2752,7 +3055,7 @@ CREATE TABLE `system_sms_log` ( | @@ -2752,7 +3055,7 @@ CREATE TABLE `system_sms_log` ( | ||
| 2752 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 3055 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 2753 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 3056 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2754 | PRIMARY KEY (`id`) USING BTREE | 3057 | PRIMARY KEY (`id`) USING BTREE |
| 2755 | -) ENGINE = InnoDB AUTO_INCREMENT = 339 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; | 3058 | +) ENGINE = InnoDB AUTO_INCREMENT = 347 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; |
| 2756 | 3059 | ||
| 2757 | -- ---------------------------- | 3060 | -- ---------------------------- |
| 2758 | -- Records of system_sms_log | 3061 | -- Records of system_sms_log |
| @@ -3050,7 +3353,7 @@ CREATE TABLE `system_users` ( | @@ -3050,7 +3353,7 @@ CREATE TABLE `system_users` ( | ||
| 3050 | -- Records of system_users | 3353 | -- Records of system_users |
| 3051 | -- ---------------------------- | 3354 | -- ---------------------------- |
| 3052 | BEGIN; | 3355 | BEGIN; |
| 3053 | -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, '127.0.0.1', '2023-01-17 12:33:07', 'admin', '2021-01-05 17:03:47', NULL, '2023-01-17 12:33:07', b'0', 1); | 3356 | +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-01-27 14:31:00', 'admin', '2021-01-05 17:03:47', NULL, '2023-01-27 14:31:00', b'0', 1); |
| 3054 | 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); | 3357 | 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); |
| 3055 | 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); | 3358 | 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); |
| 3056 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '127.0.0.1', '2022-05-28 15:43:17', '', '2021-01-21 02:13:53', NULL, '2022-07-09 09:00:33', b'0', 1); | 3359 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '127.0.0.1', '2022-05-28 15:43:17', '', '2021-01-21 02:13:53', NULL, '2022-07-09 09:00:33', b'0', 1); |
yudao-dependencies/pom.xml
| @@ -143,6 +143,11 @@ | @@ -143,6 +143,11 @@ | ||
| 143 | <artifactId>yudao-spring-boot-starter-captcha</artifactId> | 143 | <artifactId>yudao-spring-boot-starter-captcha</artifactId> |
| 144 | <version>${revision}</version> | 144 | <version>${revision}</version> |
| 145 | </dependency> | 145 | </dependency> |
| 146 | + <dependency> | ||
| 147 | + <groupId>cn.iocoder.boot</groupId> | ||
| 148 | + <artifactId>yudao-spring-boot-starter-desensitize</artifactId> | ||
| 149 | + <version>${revision}</version> | ||
| 150 | + </dependency> | ||
| 146 | 151 | ||
| 147 | <!-- Spring 核心 --> | 152 | <!-- Spring 核心 --> |
| 148 | <dependency> | 153 | <dependency> |
yudao-framework/pom.xml
| @@ -41,6 +41,7 @@ | @@ -41,6 +41,7 @@ | ||
| 41 | <module>yudao-spring-boot-starter-flowable</module> | 41 | <module>yudao-spring-boot-starter-flowable</module> |
| 42 | <module>yudao-spring-boot-starter-captcha</module> | 42 | <module>yudao-spring-boot-starter-captcha</module> |
| 43 | <module>yudao-spring-boot-starter-websocket</module> | 43 | <module>yudao-spring-boot-starter-websocket</module> |
| 44 | + <module>yudao-spring-boot-starter-desensitize</module> | ||
| 44 | </modules> | 45 | </modules> |
| 45 | 46 | ||
| 46 | <artifactId>yudao-framework</artifactId> | 47 | <artifactId>yudao-framework</artifactId> |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
| @@ -41,6 +41,11 @@ public class LocalDateTimeUtils { | @@ -41,6 +41,11 @@ public class LocalDateTimeUtils { | ||
| 41 | return LocalDateTime.of(year, mouth, day, 0, 0, 0); | 41 | return LocalDateTime.of(year, mouth, day, 0, 0, 0); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | + public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1, | ||
| 45 | + int year2, int mouth2, int day2) { | ||
| 46 | + return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)}; | ||
| 47 | + } | ||
| 48 | + | ||
| 44 | /** | 49 | /** |
| 45 | * 判断当前时间是否在该时间范围内 | 50 | * 判断当前时间是否在该时间范围内 |
| 46 | * | 51 | * |
yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <artifactId>yudao-framework</artifactId> | ||
| 8 | + <groupId>cn.iocoder.boot</groupId> | ||
| 9 | + <version>${revision}</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>yudao-spring-boot-starter-desensitize</artifactId> | ||
| 13 | + <description>脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏</description> | ||
| 14 | + | ||
| 15 | + <dependencies> | ||
| 16 | + <dependency> | ||
| 17 | + <groupId>cn.iocoder.boot</groupId> | ||
| 18 | + <artifactId>yudao-common</artifactId> | ||
| 19 | + </dependency> | ||
| 20 | + | ||
| 21 | + <!-- jackson --> | ||
| 22 | + <dependency> | ||
| 23 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
| 24 | + <artifactId>jackson-annotations</artifactId> | ||
| 25 | + </dependency> | ||
| 26 | + <dependency> | ||
| 27 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
| 28 | + <artifactId>jackson-databind</artifactId> | ||
| 29 | + </dependency> | ||
| 30 | + | ||
| 31 | + <!-- Test 测试相关 --> | ||
| 32 | + <dependency> | ||
| 33 | + <groupId>cn.iocoder.boot</groupId> | ||
| 34 | + <artifactId>yudao-spring-boot-starter-test</artifactId> | ||
| 35 | + <scope>test</scope> | ||
| 36 | + </dependency> | ||
| 37 | + </dependencies> | ||
| 38 | +</project> |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.base.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.base.serializer.StringDesensitizeSerializer; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | +import com.fasterxml.jackson.databind.annotation.JsonSerialize; | ||
| 7 | + | ||
| 8 | +import java.lang.annotation.Documented; | ||
| 9 | +import java.lang.annotation.ElementType; | ||
| 10 | +import java.lang.annotation.Retention; | ||
| 11 | +import java.lang.annotation.RetentionPolicy; | ||
| 12 | +import java.lang.annotation.Target; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 顶级脱敏注解,自定义注解需要使用此注解 | ||
| 16 | + * | ||
| 17 | + * @author gaibu | ||
| 18 | + */ | ||
| 19 | +@Documented | ||
| 20 | +@Target(ElementType.ANNOTATION_TYPE) | ||
| 21 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 22 | +@JacksonAnnotationsInside // 此注解是其他所有 jackson 注解的元注解,打上了此注解的注解表明是 jackson 注解的一部分 | ||
| 23 | +@JsonSerialize(using = StringDesensitizeSerializer.class) // 指定序列化器 | ||
| 24 | +public @interface DesensitizeBy { | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 脱敏处理器 | ||
| 28 | + */ | ||
| 29 | + @SuppressWarnings("rawtypes") | ||
| 30 | + Class<? extends DesensitizationHandler> handler(); | ||
| 31 | + | ||
| 32 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.base.handler; | ||
| 2 | + | ||
| 3 | +import java.lang.annotation.Annotation; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 脱敏处理器接口 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public interface DesensitizationHandler<T extends Annotation> { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 脱敏 | ||
| 14 | + * | ||
| 15 | + * @param origin 原始字符串 | ||
| 16 | + * @param annotation 注解信息 | ||
| 17 | + * @return 脱敏后的字符串 | ||
| 18 | + */ | ||
| 19 | + String desensitize(String origin, T annotation); | ||
| 20 | + | ||
| 21 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.base.serializer; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.annotation.AnnotationUtil; | ||
| 4 | +import cn.hutool.core.lang.Singleton; | ||
| 5 | +import cn.hutool.core.util.ArrayUtil; | ||
| 6 | +import cn.hutool.core.util.ReflectUtil; | ||
| 7 | +import cn.hutool.core.util.StrUtil; | ||
| 8 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 9 | +import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||
| 10 | +import com.fasterxml.jackson.core.JsonGenerator; | ||
| 11 | +import com.fasterxml.jackson.databind.BeanProperty; | ||
| 12 | +import com.fasterxml.jackson.databind.JsonSerializer; | ||
| 13 | +import com.fasterxml.jackson.databind.SerializerProvider; | ||
| 14 | +import com.fasterxml.jackson.databind.ser.ContextualSerializer; | ||
| 15 | +import com.fasterxml.jackson.databind.ser.std.StdSerializer; | ||
| 16 | +import lombok.Getter; | ||
| 17 | +import lombok.Setter; | ||
| 18 | + | ||
| 19 | +import java.io.IOException; | ||
| 20 | +import java.lang.annotation.Annotation; | ||
| 21 | +import java.lang.reflect.Field; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * 脱敏序列化器 | ||
| 25 | + * | ||
| 26 | + * 实现 JSON 返回数据时,使用 {@link DesensitizationHandler} 对声明脱敏注解的字段,进行脱敏处理。 | ||
| 27 | + * | ||
| 28 | + * @author gaibu | ||
| 29 | + */ | ||
| 30 | +@SuppressWarnings("rawtypes") | ||
| 31 | +public class StringDesensitizeSerializer extends StdSerializer<String> implements ContextualSerializer { | ||
| 32 | + | ||
| 33 | + @Getter | ||
| 34 | + @Setter | ||
| 35 | + private DesensitizationHandler desensitizationHandler; | ||
| 36 | + | ||
| 37 | + protected StringDesensitizeSerializer() { | ||
| 38 | + super(String.class); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) { | ||
| 43 | + DesensitizeBy annotation = beanProperty.getAnnotation(DesensitizeBy.class); | ||
| 44 | + if (annotation == null) { | ||
| 45 | + return this; | ||
| 46 | + } | ||
| 47 | + // 创建一个 StringDesensitizeSerializer 对象,使用 DesensitizeBy 对应的处理器 | ||
| 48 | + StringDesensitizeSerializer serializer = new StringDesensitizeSerializer(); | ||
| 49 | + serializer.setDesensitizationHandler(Singleton.get(annotation.handler())); | ||
| 50 | + return serializer; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Override | ||
| 54 | + @SuppressWarnings("unchecked") | ||
| 55 | + public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException { | ||
| 56 | + if (StrUtil.isBlank(value)) { | ||
| 57 | + gen.writeNull(); | ||
| 58 | + return; | ||
| 59 | + } | ||
| 60 | + // 获取序列化字段 | ||
| 61 | + Field field = getField(gen); | ||
| 62 | + | ||
| 63 | + // 自定义处理器 | ||
| 64 | + DesensitizeBy[] annotations = AnnotationUtil.getCombinationAnnotations(field, DesensitizeBy.class); | ||
| 65 | + if (ArrayUtil.isEmpty(annotations)) { | ||
| 66 | + gen.writeString(value); | ||
| 67 | + return; | ||
| 68 | + } | ||
| 69 | + for (Annotation annotation : field.getAnnotations()) { | ||
| 70 | + if (AnnotationUtil.hasAnnotation(annotation.annotationType(), DesensitizeBy.class)) { | ||
| 71 | + value = this.desensitizationHandler.desensitize(value, annotation); | ||
| 72 | + gen.writeString(value); | ||
| 73 | + return; | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + gen.writeString(value); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 获取字段 | ||
| 81 | + * | ||
| 82 | + * @param generator JsonGenerator | ||
| 83 | + * @return 字段 | ||
| 84 | + */ | ||
| 85 | + private Field getField(JsonGenerator generator) { | ||
| 86 | + String currentName = generator.getOutputContext().getCurrentName(); | ||
| 87 | + Object currentValue = generator.getCurrentValue(); | ||
| 88 | + Class<?> currentValueClass = currentValue.getClass(); | ||
| 89 | + return ReflectUtil.getField(currentValueClass, currentName); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.regex.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.regex.handler.EmailDesensitizationHandler; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 邮箱脱敏注解 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = EmailDesensitizationHandler.class) | ||
| 23 | +public @interface EmailDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 匹配的正则表达式 | ||
| 27 | + */ | ||
| 28 | + String regex() default "(^.)[^@]*(@.*$)"; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 替换规则,邮箱; | ||
| 32 | + * | ||
| 33 | + * 比如:example@gmail.com 脱敏之后为 e****@gmail.com | ||
| 34 | + */ | ||
| 35 | + String replacer() default "$1****$2"; | ||
| 36 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.regex.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.regex.handler.DefaultRegexDesensitizationHandler; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 正则脱敏注解 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = DefaultRegexDesensitizationHandler.class) | ||
| 23 | +public @interface RegexDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 匹配的正则表达式(默认匹配所有) | ||
| 27 | + */ | ||
| 28 | + String regex() default "^[\\s\\S]*$"; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 替换规则,会将匹配到的字符串全部替换成 replacer | ||
| 32 | + * | ||
| 33 | + * 例如:regex=123; replacer=****** | ||
| 34 | + * 原始字符串 123456789 | ||
| 35 | + * 脱敏后字符串 ******456789 | ||
| 36 | + */ | ||
| 37 | + String replacer() default "******"; | ||
| 38 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.regex.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||
| 4 | + | ||
| 5 | +import java.lang.annotation.Annotation; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 正则表达式脱敏处理器抽象类,已实现通用的方法 | ||
| 9 | + * | ||
| 10 | + * @author gaibu | ||
| 11 | + */ | ||
| 12 | +public abstract class AbstractRegexDesensitizationHandler<T extends Annotation> | ||
| 13 | + implements DesensitizationHandler<T> { | ||
| 14 | + | ||
| 15 | + @Override | ||
| 16 | + public String desensitize(String origin, T annotation) { | ||
| 17 | + String regex = getRegex(annotation); | ||
| 18 | + String replacer = getReplacer(annotation); | ||
| 19 | + return origin.replaceAll(regex, replacer); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 获取注解上的 regex 参数 | ||
| 24 | + * | ||
| 25 | + * @param annotation 注解信息 | ||
| 26 | + * @return 正则表达式 | ||
| 27 | + */ | ||
| 28 | + abstract String getRegex(T annotation); | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 获取注解上的 replacer 参数 | ||
| 32 | + * | ||
| 33 | + * @param annotation 注解信息 | ||
| 34 | + * @return 待替换的字符串 | ||
| 35 | + */ | ||
| 36 | + abstract String getReplacer(T annotation); | ||
| 37 | + | ||
| 38 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.regex.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.RegexDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link RegexDesensitize} 的正则脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitizationHandler<RegexDesensitize> { | ||
| 11 | + | ||
| 12 | + @Override | ||
| 13 | + String getRegex(RegexDesensitize annotation) { | ||
| 14 | + return annotation.regex(); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + String getReplacer(RegexDesensitize annotation) { | ||
| 19 | + return annotation.replacer(); | ||
| 20 | + } | ||
| 21 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.regex.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.EmailDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link EmailDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class EmailDesensitizationHandler extends AbstractRegexDesensitizationHandler<EmailDesensitize> { | ||
| 11 | + | ||
| 12 | + @Override | ||
| 13 | + String getRegex(EmailDesensitize annotation) { | ||
| 14 | + return annotation.regex(); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + String getReplacer(EmailDesensitize annotation) { | ||
| 19 | + return annotation.replacer(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.BankCardDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 银行卡号 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = BankCardDesensitization.class) | ||
| 23 | +public @interface BankCardDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 6; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 2; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,银行卡号; 比如:9988002866797031 脱敏之后为 998800********31 | ||
| 37 | + */ | ||
| 38 | + String replacer() default "*"; | ||
| 39 | + | ||
| 40 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.CarLicenseDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 车牌号 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = CarLicenseDesensitization.class) | ||
| 23 | +public @interface CarLicenseDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 3; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 1; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,车牌号;比如:粤A66666 脱敏之后为粤A6***6 | ||
| 37 | + */ | ||
| 38 | + String replacer() default "*"; | ||
| 39 | + | ||
| 40 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.ChineseNameDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 中文名 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = ChineseNameDesensitization.class) | ||
| 23 | +public @interface ChineseNameDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 1; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 0; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,中文名;比如:刘子豪脱敏之后为刘** | ||
| 37 | + */ | ||
| 38 | + String replacer() default "*"; | ||
| 39 | + | ||
| 40 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.FixedPhoneDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 固定电话 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = FixedPhoneDesensitization.class) | ||
| 23 | +public @interface FixedPhoneDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 4; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 2; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,固定电话;比如:01086551122 脱敏之后为 0108*****22 | ||
| 37 | + */ | ||
| 38 | + String replacer() default "*"; | ||
| 39 | + | ||
| 40 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.IdCardDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 身份证 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = IdCardDesensitization.class) | ||
| 23 | +public @interface IdCardDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 6; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 2; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,身份证号码;比如:530321199204074611 脱敏之后为 530321**********11 | ||
| 37 | + */ | ||
| 38 | + String replacer() default "*"; | ||
| 39 | + | ||
| 40 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.MobileDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 手机号 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = MobileDesensitization.class) | ||
| 23 | +public @interface MobileDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 3; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 4; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,手机号;比如:13248765917 脱敏之后为 132****5917 | ||
| 37 | + */ | ||
| 38 | + String replacer() default "*"; | ||
| 39 | + | ||
| 40 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.PasswordDesensitization; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 密码 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = PasswordDesensitization.class) | ||
| 23 | +public @interface PasswordDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 前缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int prefixKeep() default 0; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 后缀保留长度 | ||
| 32 | + */ | ||
| 33 | + int suffixKeep() default 0; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 替换规则,密码; | ||
| 37 | + * | ||
| 38 | + * 比如:123456 脱敏之后为 ****** | ||
| 39 | + */ | ||
| 40 | + String replacer() default "*"; | ||
| 41 | + | ||
| 42 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.slider.handler.DefaultDesensitizationHandler; | ||
| 5 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Documented; | ||
| 8 | +import java.lang.annotation.ElementType; | ||
| 9 | +import java.lang.annotation.Retention; | ||
| 10 | +import java.lang.annotation.RetentionPolicy; | ||
| 11 | +import java.lang.annotation.Target; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 滑动脱敏注解 | ||
| 15 | + * | ||
| 16 | + * @author gaibu | ||
| 17 | + */ | ||
| 18 | +@Documented | ||
| 19 | +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) | ||
| 20 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | +@JacksonAnnotationsInside | ||
| 22 | +@DesensitizeBy(handler = DefaultDesensitizationHandler.class) | ||
| 23 | +public @interface SliderDesensitize { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 后缀保留长度 | ||
| 27 | + */ | ||
| 28 | + int suffixKeep() default 0; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 替换规则,会将前缀后缀保留后,全部替换成 replacer | ||
| 32 | + * | ||
| 33 | + * 例如:prefixKeep = 1; suffixKeep = 2; replacer = "*"; | ||
| 34 | + * 原始字符串 123456 | ||
| 35 | + * 脱敏后 1***56 | ||
| 36 | + */ | ||
| 37 | + String replacer() default "*"; | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 前缀保留长度 | ||
| 41 | + */ | ||
| 42 | + int prefixKeep() default 0; | ||
| 43 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||
| 4 | + | ||
| 5 | +import java.lang.annotation.Annotation; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 滑动脱敏处理器抽象类,已实现通用的方法 | ||
| 9 | + * | ||
| 10 | + * @author gaibu | ||
| 11 | + */ | ||
| 12 | +public abstract class AbstractSliderDesensitizationHandler<T extends Annotation> | ||
| 13 | + implements DesensitizationHandler<T> { | ||
| 14 | + | ||
| 15 | + @Override | ||
| 16 | + public String desensitize(String origin, T annotation) { | ||
| 17 | + int prefixKeep = getPrefixKeep(annotation); | ||
| 18 | + int suffixKeep = getSuffixKeep(annotation); | ||
| 19 | + String replacer = getReplacer(annotation); | ||
| 20 | + int length = origin.length(); | ||
| 21 | + | ||
| 22 | + // 情况一:原始字符串长度小于等于保留长度,则原始字符串全部替换 | ||
| 23 | + if (prefixKeep >= length || suffixKeep >= length) { | ||
| 24 | + return buildReplacerByLength(replacer, length); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + // 情况二:原始字符串长度小于等于前后缀保留字符串长度,则原始字符串全部替换 | ||
| 28 | + if ((prefixKeep + suffixKeep) >= length) { | ||
| 29 | + return buildReplacerByLength(replacer, length); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + // 情况三:原始字符串长度大于前后缀保留字符串长度,则替换中间字符串 | ||
| 33 | + int interval = length - prefixKeep - suffixKeep; | ||
| 34 | + return origin.substring(0, prefixKeep) + | ||
| 35 | + buildReplacerByLength(replacer, interval) + | ||
| 36 | + origin.substring(prefixKeep + interval); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 根据长度循环构建替换符 | ||
| 41 | + * | ||
| 42 | + * @param replacer 替换符 | ||
| 43 | + * @param length 长度 | ||
| 44 | + * @return 构建后的替换符 | ||
| 45 | + */ | ||
| 46 | + private String buildReplacerByLength(String replacer, int length) { | ||
| 47 | + StringBuilder builder = new StringBuilder(); | ||
| 48 | + for (int i = 0; i < length; i++) { | ||
| 49 | + builder.append(replacer); | ||
| 50 | + } | ||
| 51 | + return builder.toString(); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 前缀保留长度 | ||
| 56 | + * | ||
| 57 | + * @param annotation 注解信息 | ||
| 58 | + * @return 前缀保留长度 | ||
| 59 | + */ | ||
| 60 | + abstract Integer getPrefixKeep(T annotation); | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 后缀保留长度 | ||
| 64 | + * | ||
| 65 | + * @param annotation 注解信息 | ||
| 66 | + * @return 后缀保留长度 | ||
| 67 | + */ | ||
| 68 | + abstract Integer getSuffixKeep(T annotation); | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 替换符 | ||
| 72 | + * | ||
| 73 | + * @param annotation 注解信息 | ||
| 74 | + * @return 替换符 | ||
| 75 | + */ | ||
| 76 | + abstract String getReplacer(T annotation); | ||
| 77 | + | ||
| 78 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.BankCardDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link BankCardDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class BankCardDesensitization extends AbstractSliderDesensitizationHandler<BankCardDesensitize> { | ||
| 11 | + | ||
| 12 | + @Override | ||
| 13 | + Integer getPrefixKeep(BankCardDesensitize annotation) { | ||
| 14 | + return annotation.prefixKeep(); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + Integer getSuffixKeep(BankCardDesensitize annotation) { | ||
| 19 | + return annotation.suffixKeep(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + String getReplacer(BankCardDesensitize annotation) { | ||
| 24 | + return annotation.replacer(); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link CarLicenseDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class CarLicenseDesensitization extends AbstractSliderDesensitizationHandler<CarLicenseDesensitize> { | ||
| 11 | + @Override | ||
| 12 | + Integer getPrefixKeep(CarLicenseDesensitize annotation) { | ||
| 13 | + return annotation.prefixKeep(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + Integer getSuffixKeep(CarLicenseDesensitize annotation) { | ||
| 18 | + return annotation.suffixKeep(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + String getReplacer(CarLicenseDesensitize annotation) { | ||
| 23 | + return annotation.replacer(); | ||
| 24 | + } | ||
| 25 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.ChineseNameDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link ChineseNameDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class ChineseNameDesensitization extends AbstractSliderDesensitizationHandler<ChineseNameDesensitize> { | ||
| 11 | + | ||
| 12 | + @Override | ||
| 13 | + Integer getPrefixKeep(ChineseNameDesensitize annotation) { | ||
| 14 | + return annotation.prefixKeep(); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + Integer getSuffixKeep(ChineseNameDesensitize annotation) { | ||
| 19 | + return annotation.suffixKeep(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + String getReplacer(ChineseNameDesensitize annotation) { | ||
| 24 | + return annotation.replacer(); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link SliderDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class DefaultDesensitizationHandler extends AbstractSliderDesensitizationHandler<SliderDesensitize> { | ||
| 11 | + @Override | ||
| 12 | + Integer getPrefixKeep(SliderDesensitize annotation) { | ||
| 13 | + return annotation.prefixKeep(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + Integer getSuffixKeep(SliderDesensitize annotation) { | ||
| 18 | + return annotation.suffixKeep(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + String getReplacer(SliderDesensitize annotation) { | ||
| 23 | + return annotation.replacer(); | ||
| 24 | + } | ||
| 25 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link FixedPhoneDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHandler<FixedPhoneDesensitize> { | ||
| 11 | + @Override | ||
| 12 | + Integer getPrefixKeep(FixedPhoneDesensitize annotation) { | ||
| 13 | + return annotation.prefixKeep(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + Integer getSuffixKeep(FixedPhoneDesensitize annotation) { | ||
| 18 | + return annotation.suffixKeep(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + String getReplacer(FixedPhoneDesensitize annotation) { | ||
| 23 | + return annotation.replacer(); | ||
| 24 | + } | ||
| 25 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.IdCardDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link IdCardDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class IdCardDesensitization extends AbstractSliderDesensitizationHandler<IdCardDesensitize> { | ||
| 11 | + @Override | ||
| 12 | + Integer getPrefixKeep(IdCardDesensitize annotation) { | ||
| 13 | + return annotation.prefixKeep(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + Integer getSuffixKeep(IdCardDesensitize annotation) { | ||
| 18 | + return annotation.suffixKeep(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + String getReplacer(IdCardDesensitize annotation) { | ||
| 23 | + return annotation.replacer(); | ||
| 24 | + } | ||
| 25 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.MobileDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link MobileDesensitize} 的脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class MobileDesensitization extends AbstractSliderDesensitizationHandler<MobileDesensitize> { | ||
| 11 | + | ||
| 12 | + @Override | ||
| 13 | + Integer getPrefixKeep(MobileDesensitize annotation) { | ||
| 14 | + return annotation.prefixKeep(); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + Integer getSuffixKeep(MobileDesensitize annotation) { | ||
| 19 | + return annotation.suffixKeep(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + String getReplacer(MobileDesensitize annotation) { | ||
| 24 | + return annotation.replacer(); | ||
| 25 | + } | ||
| 26 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.PasswordDesensitize; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * {@link PasswordDesensitize} 的码脱敏处理器 | ||
| 7 | + * | ||
| 8 | + * @author gaibu | ||
| 9 | + */ | ||
| 10 | +public class PasswordDesensitization extends AbstractSliderDesensitizationHandler<PasswordDesensitize> { | ||
| 11 | + @Override | ||
| 12 | + Integer getPrefixKeep(PasswordDesensitize annotation) { | ||
| 13 | + return annotation.prefixKeep(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + Integer getSuffixKeep(PasswordDesensitize annotation) { | ||
| 18 | + return annotation.suffixKeep(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + String getReplacer(PasswordDesensitize annotation) { | ||
| 23 | + return annotation.replacer(); | ||
| 24 | + } | ||
| 25 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.EmailDesensitize; | ||
| 5 | +import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.RegexDesensitize; | ||
| 6 | +import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; | ||
| 7 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.BankCardDesensitize; | ||
| 8 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseDesensitize; | ||
| 9 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.ChineseNameDesensitize; | ||
| 10 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize; | ||
| 11 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.IdCardDesensitize; | ||
| 12 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.PasswordDesensitize; | ||
| 13 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.MobileDesensitize; | ||
| 14 | +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesensitize; | ||
| 15 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 16 | +import lombok.Data; | ||
| 17 | +import org.junit.jupiter.api.Test; | ||
| 18 | + | ||
| 19 | +import static org.junit.jupiter.api.Assertions.*; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * {@link DesensitizeTest} 的单元测试 | ||
| 23 | + */ | ||
| 24 | +public class DesensitizeTest extends BaseMockitoUnitTest { | ||
| 25 | + | ||
| 26 | + @Test | ||
| 27 | + public void test() { | ||
| 28 | + // 准备参数 | ||
| 29 | + DesensitizeDemo desensitizeDemo = new DesensitizeDemo(); | ||
| 30 | + desensitizeDemo.setNickname("芋道源码"); | ||
| 31 | + desensitizeDemo.setBankCard("9988002866797031"); | ||
| 32 | + desensitizeDemo.setCarLicense("粤A66666"); | ||
| 33 | + desensitizeDemo.setFixedPhone("01086551122"); | ||
| 34 | + desensitizeDemo.setIdCard("530321199204074611"); | ||
| 35 | + desensitizeDemo.setPassword("123456"); | ||
| 36 | + desensitizeDemo.setPhoneNumber("13248765917"); | ||
| 37 | + desensitizeDemo.setSlider1("ABCDEFG"); | ||
| 38 | + desensitizeDemo.setSlider2("ABCDEFG"); | ||
| 39 | + desensitizeDemo.setSlider3("ABCDEFG"); | ||
| 40 | + desensitizeDemo.setEmail("1@email.com"); | ||
| 41 | + desensitizeDemo.setRegex("你好,我是芋道源码"); | ||
| 42 | + desensitizeDemo.setAddress("北京市海淀区上地十街10号"); | ||
| 43 | + desensitizeDemo.setOrigin("芋道源码"); | ||
| 44 | + | ||
| 45 | + // 调用 | ||
| 46 | + DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class); | ||
| 47 | + // 断言 | ||
| 48 | + assertNotNull(d); | ||
| 49 | + assertEquals("芋***", d.getNickname()); | ||
| 50 | + assertEquals("998800********31", d.getBankCard()); | ||
| 51 | + assertEquals("粤A6***6", d.getCarLicense()); | ||
| 52 | + assertEquals("0108*****22", d.getFixedPhone()); | ||
| 53 | + assertEquals("530321**********11", d.getIdCard()); | ||
| 54 | + assertEquals("******", d.getPassword()); | ||
| 55 | + assertEquals("132****5917", d.getPhoneNumber()); | ||
| 56 | + assertEquals("#######", d.getSlider1()); | ||
| 57 | + assertEquals("ABC*EFG", d.getSlider2()); | ||
| 58 | + assertEquals("*******", d.getSlider3()); | ||
| 59 | + assertEquals("1****@email.com", d.getEmail()); | ||
| 60 | + assertEquals("你好,我是*", d.getRegex()); | ||
| 61 | + assertEquals("北京市海淀区上地十街10号*", d.getAddress()); | ||
| 62 | + assertEquals("芋道源码", d.getOrigin()); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Data | ||
| 66 | + public static class DesensitizeDemo { | ||
| 67 | + | ||
| 68 | + @ChineseNameDesensitize | ||
| 69 | + private String nickname; | ||
| 70 | + @BankCardDesensitize | ||
| 71 | + private String bankCard; | ||
| 72 | + @CarLicenseDesensitize | ||
| 73 | + private String carLicense; | ||
| 74 | + @FixedPhoneDesensitize | ||
| 75 | + private String fixedPhone; | ||
| 76 | + @IdCardDesensitize | ||
| 77 | + private String idCard; | ||
| 78 | + @PasswordDesensitize | ||
| 79 | + private String password; | ||
| 80 | + @MobileDesensitize | ||
| 81 | + private String phoneNumber; | ||
| 82 | + @SliderDesensitize(prefixKeep = 6, suffixKeep = 1, replacer = "#") | ||
| 83 | + private String slider1; | ||
| 84 | + @SliderDesensitize(prefixKeep = 3, suffixKeep = 3) | ||
| 85 | + private String slider2; | ||
| 86 | + @SliderDesensitize(prefixKeep = 10) | ||
| 87 | + private String slider3; | ||
| 88 | + @EmailDesensitize | ||
| 89 | + private String email; | ||
| 90 | + @RegexDesensitize(regex = "芋道源码", replacer = "*") | ||
| 91 | + private String regex; | ||
| 92 | + @Address | ||
| 93 | + private String address; | ||
| 94 | + private String origin; | ||
| 95 | + | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.annotation; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||
| 5 | +import cn.iocoder.yudao.framework.desensitize.core.handler.AddressHandler; | ||
| 6 | +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | ||
| 7 | + | ||
| 8 | +import java.lang.annotation.Documented; | ||
| 9 | +import java.lang.annotation.ElementType; | ||
| 10 | +import java.lang.annotation.Retention; | ||
| 11 | +import java.lang.annotation.RetentionPolicy; | ||
| 12 | +import java.lang.annotation.Target; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 地址 | ||
| 16 | + * | ||
| 17 | + * 用于 {@link DesensitizeTest} 测试使用 | ||
| 18 | + * | ||
| 19 | + * @author gaibu | ||
| 20 | + */ | ||
| 21 | +@Documented | ||
| 22 | +@Target({ElementType.FIELD}) | ||
| 23 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 24 | +@JacksonAnnotationsInside | ||
| 25 | +@DesensitizeBy(handler = AddressHandler.class) | ||
| 26 | +public @interface Address { | ||
| 27 | + | ||
| 28 | + String replacer() default "*"; | ||
| 29 | + | ||
| 30 | +} |
yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.desensitize.core.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; | ||
| 4 | +import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||
| 5 | +import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * {@link Address} 的脱敏处理器 | ||
| 9 | + * | ||
| 10 | + * 用于 {@link DesensitizeTest} 测试使用 | ||
| 11 | + */ | ||
| 12 | +public class AddressHandler implements DesensitizationHandler<Address> { | ||
| 13 | + | ||
| 14 | + @Override | ||
| 15 | + public String desensitize(String origin, Address annotation) { | ||
| 16 | + return origin + annotation.replacer(); | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | +} |
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
| @@ -81,22 +81,19 @@ public interface BaseMapperX<T> extends BaseMapper<T> { | @@ -81,22 +81,19 @@ public interface BaseMapperX<T> extends BaseMapper<T> { | ||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /** | 83 | /** |
| 84 | - * 逐条插入,适合少量数据插入,或者对性能要求不高的场景 | ||
| 85 | - * <p> | ||
| 86 | - * 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法 | ||
| 87 | - * 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类 | 84 | + * 批量插入,适合大量数据插入 |
| 88 | * | 85 | * |
| 89 | * @param entities 实体们 | 86 | * @param entities 实体们 |
| 90 | */ | 87 | */ |
| 91 | default void insertBatch(Collection<T> entities) { | 88 | default void insertBatch(Collection<T> entities) { |
| 92 | - entities.forEach(this::insert); | 89 | + Db.saveBatch(entities); |
| 93 | } | 90 | } |
| 94 | 91 | ||
| 95 | /** | 92 | /** |
| 96 | * 批量插入,适合大量数据插入 | 93 | * 批量插入,适合大量数据插入 |
| 97 | * | 94 | * |
| 98 | * @param entities 实体们 | 95 | * @param entities 实体们 |
| 99 | - * @param size 插入数量 Db.saveBatch 默认为1000 | 96 | + * @param size 插入数量 Db.saveBatch 默认为 1000 |
| 100 | */ | 97 | */ |
| 101 | default void insertBatch(Collection<T> entities, int size) { | 98 | default void insertBatch(Collection<T> entities, int size) { |
| 102 | Db.saveBatch(entities, size); | 99 | Db.saveBatch(entities, size); |
yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java
| @@ -7,7 +7,10 @@ import cn.hutool.core.util.StrUtil; | @@ -7,7 +7,10 @@ import cn.hutool.core.util.StrUtil; | ||
| 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 8 | import uk.co.jemos.podam.api.PodamFactory; | 8 | import uk.co.jemos.podam.api.PodamFactory; |
| 9 | import uk.co.jemos.podam.api.PodamFactoryImpl; | 9 | import uk.co.jemos.podam.api.PodamFactoryImpl; |
| 10 | +import uk.co.jemos.podam.common.AttributeStrategy; | ||
| 10 | 11 | ||
| 12 | +import javax.validation.constraints.Email; | ||
| 13 | +import java.lang.annotation.Annotation; | ||
| 11 | import java.lang.reflect.Type; | 14 | import java.lang.reflect.Type; |
| 12 | import java.time.LocalDateTime; | 15 | import java.time.LocalDateTime; |
| 13 | import java.util.Arrays; | 16 | import java.util.Arrays; |
| @@ -95,6 +98,10 @@ public class RandomUtils { | @@ -95,6 +98,10 @@ public class RandomUtils { | ||
| 95 | return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); | 98 | return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); |
| 96 | } | 99 | } |
| 97 | 100 | ||
| 101 | + public static String randomEmail() { | ||
| 102 | + return randomString() + "@qq.com"; | ||
| 103 | + } | ||
| 104 | + | ||
| 98 | @SafeVarargs | 105 | @SafeVarargs |
| 99 | public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) { | 106 | public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) { |
| 100 | T pojo = PODAM_FACTORY.manufacturePojo(clazz); | 107 | T pojo = PODAM_FACTORY.manufacturePojo(clazz); |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
| @@ -2,27 +2,18 @@ package cn.iocoder.yudao.framework.web.config; | @@ -2,27 +2,18 @@ package cn.iocoder.yudao.framework.web.config; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; | 3 | import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; |
| 4 | import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; |
| 5 | -import cn.iocoder.yudao.framework.web.core.clean.JsoupXssCleaner; | ||
| 6 | -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; | ||
| 7 | import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; | 5 | import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; |
| 8 | import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; | 6 | import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; |
| 9 | -import cn.iocoder.yudao.framework.web.core.filter.XssFilter; | ||
| 10 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | 7 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; |
| 11 | import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; | 8 | import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; |
| 12 | -import cn.iocoder.yudao.framework.web.core.json.XssStringJsonDeserializer; | ||
| 13 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 9 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 14 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 15 | import org.springframework.beans.factory.annotation.Value; | 10 | import org.springframework.beans.factory.annotation.Value; |
| 16 | import org.springframework.boot.autoconfigure.AutoConfiguration; | 11 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 17 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
| 18 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 20 | -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | ||
| 21 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 13 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 22 | import org.springframework.boot.web.servlet.FilterRegistrationBean; | 14 | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| 23 | import org.springframework.context.annotation.Bean; | 15 | import org.springframework.context.annotation.Bean; |
| 24 | import org.springframework.util.AntPathMatcher; | 16 | import org.springframework.util.AntPathMatcher; |
| 25 | -import org.springframework.util.PathMatcher; | ||
| 26 | import org.springframework.web.bind.annotation.RestController; | 17 | import org.springframework.web.bind.annotation.RestController; |
| 27 | import org.springframework.web.cors.CorsConfiguration; | 18 | import org.springframework.web.cors.CorsConfiguration; |
| 28 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | 19 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
| @@ -34,7 +25,7 @@ import javax.annotation.Resource; | @@ -34,7 +25,7 @@ import javax.annotation.Resource; | ||
| 34 | import javax.servlet.Filter; | 25 | import javax.servlet.Filter; |
| 35 | 26 | ||
| 36 | @AutoConfiguration | 27 | @AutoConfiguration |
| 37 | -@EnableConfigurationProperties({WebProperties.class, XssProperties.class}) | 28 | +@EnableConfigurationProperties(WebProperties.class) |
| 38 | public class YudaoWebAutoConfiguration implements WebMvcConfigurer { | 29 | public class YudaoWebAutoConfiguration implements WebMvcConfigurer { |
| 39 | 30 | ||
| 40 | @Resource | 31 | @Resource |
| @@ -108,15 +99,6 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { | @@ -108,15 +99,6 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { | ||
| 108 | } | 99 | } |
| 109 | 100 | ||
| 110 | /** | 101 | /** |
| 111 | - * 创建 XssFilter Bean,解决 Xss 安全问题 | ||
| 112 | - */ | ||
| 113 | - @Bean | ||
| 114 | - @ConditionalOnBean(XssCleaner.class) | ||
| 115 | - public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) { | ||
| 116 | - return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER); | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - /** | ||
| 120 | * 创建 DemoFilter Bean,演示模式 | 102 | * 创建 DemoFilter Bean,演示模式 |
| 121 | */ | 103 | */ |
| 122 | @Bean | 104 | @Bean |
| @@ -125,33 +107,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { | @@ -125,33 +107,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { | ||
| 125 | return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER); | 107 | return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER); |
| 126 | } | 108 | } |
| 127 | 109 | ||
| 128 | - | ||
| 129 | - /** | ||
| 130 | - * Xss 清理者 | ||
| 131 | - * | ||
| 132 | - * @return XssCleaner | ||
| 133 | - */ | ||
| 134 | - @Bean | ||
| 135 | - @ConditionalOnMissingBean(XssCleaner.class) | ||
| 136 | - public XssCleaner xssCleaner() { | ||
| 137 | - return new JsoupXssCleaner(); | ||
| 138 | - } | ||
| 139 | - | ||
| 140 | - /** | ||
| 141 | - * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤 | ||
| 142 | - * | ||
| 143 | - * @return Jackson2ObjectMapperBuilderCustomizer | ||
| 144 | - */ | ||
| 145 | - @Bean | ||
| 146 | - @ConditionalOnMissingBean(name = "xssJacksonCustomizer") | ||
| 147 | - @ConditionalOnBean(ObjectMapper.class) | ||
| 148 | - @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") | ||
| 149 | - public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) { | ||
| 150 | - // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 | ||
| 151 | - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner)); | ||
| 152 | - } | ||
| 153 | - | ||
| 154 | - private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { | 110 | + public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { |
| 155 | FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); | 111 | FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); |
| 156 | bean.setOrder(order); | 112 | bean.setOrder(order); |
| 157 | return bean; | 113 | return bean; |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java
| 1 | -package cn.iocoder.yudao.framework.web.config; | 1 | +package cn.iocoder.yudao.framework.xss.config; |
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | import org.springframework.boot.context.properties.ConfigurationProperties; | 4 | import org.springframework.boot.context.properties.ConfigurationProperties; |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.xss.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.xss.core.clean.JsoupXssCleaner; | ||
| 5 | +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; | ||
| 6 | +import cn.iocoder.yudao.framework.xss.core.filter.XssFilter; | ||
| 7 | +import cn.iocoder.yudao.framework.xss.core.json.XssStringJsonDeserializer; | ||
| 8 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 9 | +import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
| 10 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
| 11 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| 12 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 13 | +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | ||
| 14 | +import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| 15 | +import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
| 16 | +import org.springframework.context.annotation.Bean; | ||
| 17 | +import org.springframework.util.PathMatcher; | ||
| 18 | +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
| 19 | + | ||
| 20 | +import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.createFilterBean; | ||
| 21 | + | ||
| 22 | +@AutoConfiguration | ||
| 23 | +@EnableConfigurationProperties(XssProperties.class) | ||
| 24 | +public class YudaoXssAutoConfiguration implements WebMvcConfigurer { | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * Xss 清理者 | ||
| 28 | + * | ||
| 29 | + * @return XssCleaner | ||
| 30 | + */ | ||
| 31 | + @Bean | ||
| 32 | + @ConditionalOnMissingBean(XssCleaner.class) | ||
| 33 | + public XssCleaner xssCleaner() { | ||
| 34 | + return new JsoupXssCleaner(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤 | ||
| 39 | + * | ||
| 40 | + * @return Jackson2ObjectMapperBuilderCustomizer | ||
| 41 | + */ | ||
| 42 | + @Bean | ||
| 43 | + @ConditionalOnMissingBean(name = "xssJacksonCustomizer") | ||
| 44 | + @ConditionalOnBean(ObjectMapper.class) | ||
| 45 | + @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") | ||
| 46 | + public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) { | ||
| 47 | + // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 | ||
| 48 | + return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner)); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 创建 XssFilter Bean,解决 Xss 安全问题 | ||
| 53 | + */ | ||
| 54 | + @Bean | ||
| 55 | + @ConditionalOnBean(XssCleaner.class) | ||
| 56 | + public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) { | ||
| 57 | + return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java
| 1 | -package cn.iocoder.yudao.framework.web.core.clean; | 1 | +package cn.iocoder.yudao.framework.xss.core.clean; |
| 2 | 2 | ||
| 3 | import org.jsoup.Jsoup; | 3 | import org.jsoup.Jsoup; |
| 4 | import org.jsoup.nodes.Document; | 4 | import org.jsoup.nodes.Document; |
| 5 | import org.jsoup.safety.Safelist; | 5 | import org.jsoup.safety.Safelist; |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | - * jsonp 过滤字符串 | 8 | + * 基于 JSONP 实现 XSS 过滤字符串 |
| 9 | */ | 9 | */ |
| 10 | public class JsoupXssCleaner implements XssCleaner { | 10 | public class JsoupXssCleaner implements XssCleaner { |
| 11 | 11 | ||
| @@ -24,21 +24,6 @@ public class JsoupXssCleaner implements XssCleaner { | @@ -24,21 +24,6 @@ public class JsoupXssCleaner implements XssCleaner { | ||
| 24 | this.baseUri = ""; | 24 | this.baseUri = ""; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | - public JsoupXssCleaner(Safelist safelist) { | ||
| 28 | - this.safelist = safelist; | ||
| 29 | - this.baseUri = ""; | ||
| 30 | - } | ||
| 31 | - | ||
| 32 | - public JsoupXssCleaner(String baseUri) { | ||
| 33 | - this.safelist = buildSafelist(); | ||
| 34 | - this.baseUri = baseUri; | ||
| 35 | - } | ||
| 36 | - | ||
| 37 | - public JsoupXssCleaner(Safelist safelist, String baseUri) { | ||
| 38 | - this.safelist = safelist; | ||
| 39 | - this.baseUri = baseUri; | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | /** | 27 | /** |
| 43 | * 构建一个 Xss 清理的 Safelist 规则。 | 28 | * 构建一个 Xss 清理的 Safelist 规则。 |
| 44 | * 基于 Safelist#relaxed() 的基础上: | 29 | * 基于 Safelist#relaxed() 的基础上: |
| @@ -67,7 +52,6 @@ public class JsoupXssCleaner implements XssCleaner { | @@ -67,7 +52,6 @@ public class JsoupXssCleaner implements XssCleaner { | ||
| 67 | // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径 | 52 | // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径 |
| 68 | // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto"); | 53 | // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto"); |
| 69 | // WHITELIST.removeProtocols("img", "src", "http", "https"); | 54 | // WHITELIST.removeProtocols("img", "src", "http", "https"); |
| 70 | - | ||
| 71 | return relaxedSafelist; | 55 | return relaxedSafelist; |
| 72 | } | 56 | } |
| 73 | 57 |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java
| 1 | -package cn.iocoder.yudao.framework.web.core.clean; | 1 | +package cn.iocoder.yudao.framework.xss.core.clean; |
| 2 | 2 | ||
| 3 | /** | 3 | /** |
| 4 | * 对 html 文本中的有 Xss 风险的数据进行清理 | 4 | * 对 html 文本中的有 Xss 风险的数据进行清理 |
| @@ -12,4 +12,5 @@ public interface XssCleaner { | @@ -12,4 +12,5 @@ public interface XssCleaner { | ||
| 12 | * @return 清理后的 html | 12 | * @return 清理后的 html |
| 13 | */ | 13 | */ |
| 14 | String clean(String html); | 14 | String clean(String html); |
| 15 | + | ||
| 15 | } | 16 | } |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java
| 1 | -package cn.iocoder.yudao.framework.web.core.filter; | 1 | +package cn.iocoder.yudao.framework.xss.core.filter; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.web.config.XssProperties; | ||
| 4 | -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; | 3 | +import cn.iocoder.yudao.framework.xss.config.XssProperties; |
| 4 | +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; | ||
| 5 | import lombok.AllArgsConstructor; | 5 | import lombok.AllArgsConstructor; |
| 6 | import org.springframework.util.PathMatcher; | 6 | import org.springframework.util.PathMatcher; |
| 7 | import org.springframework.web.filter.OncePerRequestFilter; | 7 | import org.springframework.web.filter.OncePerRequestFilter; |
| @@ -14,8 +14,6 @@ import java.io.IOException; | @@ -14,8 +14,6 @@ import java.io.IOException; | ||
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * Xss 过滤器 | 16 | * Xss 过滤器 |
| 17 | - * <p> | ||
| 18 | - * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/ | ||
| 19 | * | 17 | * |
| 20 | * @author 芋道源码 | 18 | * @author 芋道源码 |
| 21 | */ | 19 | */ |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java
| 1 | -package cn.iocoder.yudao.framework.web.core.filter; | 1 | +package cn.iocoder.yudao.framework.xss.core.filter; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; | 3 | +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; |
| 4 | 4 | ||
| 5 | import javax.servlet.http.HttpServletRequest; | 5 | import javax.servlet.http.HttpServletRequest; |
| 6 | import javax.servlet.http.HttpServletRequestWrapper; | 6 | import javax.servlet.http.HttpServletRequestWrapper; |
| @@ -13,6 +13,7 @@ import java.util.Map; | @@ -13,6 +13,7 @@ import java.util.Map; | ||
| 13 | * @author 芋道源码 | 13 | * @author 芋道源码 |
| 14 | */ | 14 | */ |
| 15 | public class XssRequestWrapper extends HttpServletRequestWrapper { | 15 | public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 16 | + | ||
| 16 | private final XssCleaner xssCleaner; | 17 | private final XssCleaner xssCleaner; |
| 17 | 18 | ||
| 18 | public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) { | 19 | public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) { |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java
| 1 | -package cn.iocoder.yudao.framework.web.core.json; | 1 | +package cn.iocoder.yudao.framework.xss.core.json; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; | 3 | +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; |
| 4 | import com.fasterxml.jackson.core.JsonParser; | 4 | import com.fasterxml.jackson.core.JsonParser; |
| 5 | import com.fasterxml.jackson.core.JsonToken; | 5 | import com.fasterxml.jackson.core.JsonToken; |
| 6 | import com.fasterxml.jackson.databind.DeserializationContext; | 6 | import com.fasterxml.jackson.databind.DeserializationContext; |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
| @@ -2,4 +2,5 @@ cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration | @@ -2,4 +2,5 @@ cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration | ||
| 2 | cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration | 2 | cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration |
| 3 | com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration | 3 | com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration |
| 4 | cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration | 4 | cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration |
| 5 | -cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration | ||
| 6 | \ No newline at end of file | 5 | \ No newline at end of file |
| 6 | +cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration | ||
| 7 | +cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileConfigMapper.java
| @@ -6,15 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -6,15 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; | 6 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; |
| 7 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; | 7 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | -import org.apache.ibatis.annotations.Select; | ||
| 10 | 9 | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | - | ||
| 13 | -/** | ||
| 14 | - * 文件配置 Mapper | ||
| 15 | - * | ||
| 16 | - * @author 芋道源码 | ||
| 17 | - */ | ||
| 18 | @Mapper | 10 | @Mapper |
| 19 | public interface FileConfigMapper extends BaseMapperX<FileConfigDO> { | 11 | public interface FileConfigMapper extends BaseMapperX<FileConfigDO> { |
| 20 | 12 | ||
| @@ -26,7 +18,4 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> { | @@ -26,7 +18,4 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> { | ||
| 26 | .orderByDesc(FileConfigDO::getId)); | 18 | .orderByDesc(FileConfigDO::getId)); |
| 27 | } | 19 | } |
| 28 | 20 | ||
| 29 | - @Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}") | ||
| 30 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 31 | - | ||
| 32 | } | 21 | } |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/file/FileConfigRefreshConsumer.java
| @@ -23,7 +23,7 @@ public class FileConfigRefreshConsumer extends AbstractChannelMessageListener<Fi | @@ -23,7 +23,7 @@ public class FileConfigRefreshConsumer extends AbstractChannelMessageListener<Fi | ||
| 23 | @Override | 23 | @Override |
| 24 | public void onMessage(FileConfigRefreshMessage message) { | 24 | public void onMessage(FileConfigRefreshMessage message) { |
| 25 | log.info("[onMessage][收到 FileConfig 刷新消息]"); | 25 | log.info("[onMessage][收到 FileConfig 刷新消息]"); |
| 26 | - fileConfigService.initFileClients(); | 26 | + fileConfigService.initLocalCache(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | } | 29 | } |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java
| @@ -237,10 +237,6 @@ public class CodegenServiceImpl implements CodegenService { | @@ -237,10 +237,6 @@ public class CodegenServiceImpl implements CodegenService { | ||
| 237 | @Override | 237 | @Override |
| 238 | public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { | 238 | public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { |
| 239 | List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); | 239 | List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); |
| 240 | - // 移除置顶前缀的表名 // TODO 未来做成可配置 | ||
| 241 | - tables.removeIf(table -> table.getName().toUpperCase().startsWith("QRTZ_")); | ||
| 242 | - tables.removeIf(table -> table.getName().toUpperCase().startsWith("ACT_")); | ||
| 243 | - tables.removeIf(table -> table.getName().toUpperCase().startsWith("FLW_")); | ||
| 244 | // 移除已经生成的表 | 240 | // 移除已经生成的表 |
| 245 | // 移除在 Codegen 中,已经存在的 | 241 | // 移除在 Codegen 中,已经存在的 |
| 246 | Set<String> existsTables = CollectionUtils.convertSet( | 242 | Set<String> existsTables = CollectionUtils.convertSet( |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
| @@ -52,7 +52,11 @@ public class DatabaseTableServiceImpl implements DatabaseTableService { | @@ -52,7 +52,11 @@ public class DatabaseTableServiceImpl implements DatabaseTableService { | ||
| 52 | StrategyConfig.Builder strategyConfig = new StrategyConfig.Builder(); | 52 | StrategyConfig.Builder strategyConfig = new StrategyConfig.Builder(); |
| 53 | if (StrUtil.isNotEmpty(name)) { | 53 | if (StrUtil.isNotEmpty(name)) { |
| 54 | strategyConfig.addInclude(name); | 54 | strategyConfig.addInclude(name); |
| 55 | + } else { | ||
| 56 | + // 移除工作流和定时任务前缀的表名 // TODO 未来做成可配置 | ||
| 57 | + strategyConfig.addExclude("ACT_[\\S\\s]+|QRTZ_[\\S\\s]+|FLW_[\\S\\s]+"); | ||
| 55 | } | 58 | } |
| 59 | + | ||
| 56 | GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build(); // 只使用 Date 类型,不使用 LocalDate | 60 | GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build(); // 只使用 Date 类型,不使用 LocalDate |
| 57 | ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(), | 61 | ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(), |
| 58 | null, globalConfig, null); | 62 | null, globalConfig, null); |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.service.file; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.service.file; | ||
| 3 | import cn.hutool.core.io.resource.ResourceUtil; | 3 | import cn.hutool.core.io.resource.ResourceUtil; |
| 4 | import cn.hutool.core.util.IdUtil; | 4 | import cn.hutool.core.util.IdUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 6 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 8 | import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; | 7 | import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; |
| 9 | import cn.iocoder.yudao.framework.file.core.client.FileClient; | 8 | import cn.iocoder.yudao.framework.file.core.client.FileClient; |
| @@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; | @@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; | ||
| 19 | import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer; | 18 | import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer; |
| 20 | import lombok.Getter; | 19 | import lombok.Getter; |
| 21 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
| 22 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 23 | import org.springframework.stereotype.Service; | 21 | import org.springframework.stereotype.Service; |
| 24 | import org.springframework.transaction.annotation.Transactional; | 22 | import org.springframework.transaction.annotation.Transactional; |
| 25 | import org.springframework.transaction.support.TransactionSynchronization; | 23 | import org.springframework.transaction.support.TransactionSynchronization; |
| @@ -29,7 +27,6 @@ import org.springframework.validation.annotation.Validated; | @@ -29,7 +27,6 @@ import org.springframework.validation.annotation.Validated; | ||
| 29 | import javax.annotation.PostConstruct; | 27 | import javax.annotation.PostConstruct; |
| 30 | import javax.annotation.Resource; | 28 | import javax.annotation.Resource; |
| 31 | import javax.validation.Validator; | 29 | import javax.validation.Validator; |
| 32 | -import java.time.LocalDateTime; | ||
| 33 | import java.util.Collection; | 30 | import java.util.Collection; |
| 34 | import java.util.List; | 31 | import java.util.List; |
| 35 | import java.util.Map; | 32 | import java.util.Map; |
| @@ -48,18 +45,6 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG | @@ -48,18 +45,6 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG | ||
| 48 | @Slf4j | 45 | @Slf4j |
| 49 | public class FileConfigServiceImpl implements FileConfigService { | 46 | public class FileConfigServiceImpl implements FileConfigService { |
| 50 | 47 | ||
| 51 | - /** | ||
| 52 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 53 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 54 | - */ | ||
| 55 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 56 | - | ||
| 57 | - /** | ||
| 58 | - * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 59 | - */ | ||
| 60 | - @Getter | ||
| 61 | - private volatile LocalDateTime maxUpdateTime; | ||
| 62 | - | ||
| 63 | @Resource | 48 | @Resource |
| 64 | private FileClientFactory fileClientFactory; | 49 | private FileClientFactory fileClientFactory; |
| 65 | /** | 50 | /** |
| @@ -79,34 +64,12 @@ public class FileConfigServiceImpl implements FileConfigService { | @@ -79,34 +64,12 @@ public class FileConfigServiceImpl implements FileConfigService { | ||
| 79 | 64 | ||
| 80 | @Override | 65 | @Override |
| 81 | @PostConstruct | 66 | @PostConstruct |
| 82 | - public void initFileClients() { | ||
| 83 | - initLocalCacheIfUpdate(null); | ||
| 84 | - } | ||
| 85 | - | ||
| 86 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 87 | - public void schedulePeriodicRefresh() { | ||
| 88 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - /** | ||
| 92 | - * 刷新本地缓存 | ||
| 93 | - * | ||
| 94 | - * @param maxUpdateTime 最大更新时间 | ||
| 95 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 96 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 97 | - */ | ||
| 98 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 99 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 100 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 101 | - if (maxUpdateTime != null | ||
| 102 | - && fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 103 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 104 | - return; | ||
| 105 | - } | 67 | + public void initLocalCache() { |
| 68 | + // 第一步:查询数据 | ||
| 106 | List<FileConfigDO> configs = fileConfigMapper.selectList(); | 69 | List<FileConfigDO> configs = fileConfigMapper.selectList(); |
| 107 | - log.info("[initLocalCacheIfUpdate][缓存文件配置,数量为:{}]", configs.size()); | 70 | + log.info("[initLocalCache][缓存文件配置,数量为:{}]", configs.size()); |
| 108 | 71 | ||
| 109 | - // 第二步:构建缓存。创建或更新文件 Client | 72 | + // 第二步:构建缓存:创建或更新文件 Client |
| 110 | configs.forEach(config -> { | 73 | configs.forEach(config -> { |
| 111 | fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig()); | 74 | fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig()); |
| 112 | // 如果是 master,进行设置 | 75 | // 如果是 master,进行设置 |
| @@ -114,9 +77,6 @@ public class FileConfigServiceImpl implements FileConfigService { | @@ -114,9 +77,6 @@ public class FileConfigServiceImpl implements FileConfigService { | ||
| 114 | masterFileClient = fileClientFactory.getFileClient(config.getId()); | 77 | masterFileClient = fileClientFactory.getFileClient(config.getId()); |
| 115 | } | 78 | } |
| 116 | }); | 79 | }); |
| 117 | - | ||
| 118 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 119 | - this.maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime); | ||
| 120 | } | 80 | } |
| 121 | 81 | ||
| 122 | @Override | 82 | @Override |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
| @@ -79,7 +79,7 @@ public class TestDemoServiceImpl implements TestDemoService { | @@ -79,7 +79,7 @@ public class TestDemoServiceImpl implements TestDemoService { | ||
| 79 | 79 | ||
| 80 | @Override | 80 | @Override |
| 81 | public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) { | 81 | public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) { |
| 82 | -// testDemoMapper.selectList2(); | 82 | + testDemoMapper.selectList2(); |
| 83 | return testDemoMapper.selectPage(pageReqVO); | 83 | return testDemoMapper.selectPage(pageReqVO); |
| 84 | } | 84 | } |
| 85 | 85 |
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
| @@ -30,7 +30,6 @@ import java.util.Map; | @@ -30,7 +30,6 @@ import java.util.Map; | ||
| 30 | import static cn.hutool.core.util.RandomUtil.randomEle; | 30 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| 31 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | 31 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; |
| 32 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 32 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 33 | -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; | ||
| 34 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 33 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 35 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 34 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 36 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | 35 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; |
| @@ -74,16 +73,13 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { | @@ -74,16 +73,13 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { | ||
| 74 | when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient); | 73 | when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient); |
| 75 | 74 | ||
| 76 | // 调用 | 75 | // 调用 |
| 77 | - fileConfigService.initFileClients(); | 76 | + fileConfigService.initLocalCache(); |
| 78 | // 断言 fileClientFactory 调用 | 77 | // 断言 fileClientFactory 调用 |
| 79 | verify(fileClientFactory).createOrUpdateFileClient(eq(1L), | 78 | verify(fileClientFactory).createOrUpdateFileClient(eq(1L), |
| 80 | eq(configDO1.getStorage()), eq(configDO1.getConfig())); | 79 | eq(configDO1.getStorage()), eq(configDO1.getConfig())); |
| 81 | verify(fileClientFactory).createOrUpdateFileClient(eq(2L), | 80 | verify(fileClientFactory).createOrUpdateFileClient(eq(2L), |
| 82 | eq(configDO2.getStorage()), eq(configDO2.getConfig())); | 81 | eq(configDO2.getStorage()), eq(configDO2.getConfig())); |
| 83 | assertSame(masterFileClient, fileConfigService.getMasterFileClient()); | 82 | assertSame(masterFileClient, fileConfigService.getMasterFileClient()); |
| 84 | - // 断言 maxUpdateTime 缓存 | ||
| 85 | - assertEquals(max(configDO1.getUpdateTime(), configDO2.getUpdateTime()), | ||
| 86 | - fileConfigService.getMaxUpdateTime()); | ||
| 87 | } | 83 | } |
| 88 | 84 | ||
| 89 | @Test | 85 | @Test |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapper.java
| @@ -8,9 +8,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChann | @@ -8,9 +8,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChann | ||
| 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; |
| 9 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 10 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 11 | -import org.apache.ibatis.annotations.Select; | ||
| 12 | 11 | ||
| 13 | -import java.time.LocalDateTime; | ||
| 14 | import java.util.Collection; | 12 | import java.util.Collection; |
| 15 | import java.util.List; | 13 | import java.util.List; |
| 16 | 14 | ||
| @@ -21,9 +19,6 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> { | @@ -21,9 +19,6 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> { | ||
| 21 | return selectOne(PayChannelDO::getAppId, appId, PayChannelDO::getCode, code); | 19 | return selectOne(PayChannelDO::getAppId, appId, PayChannelDO::getCode, code); |
| 22 | } | 20 | } |
| 23 | 21 | ||
| 24 | - @Select("SELECT COUNT(*) FROM pay_channel WHERE update_time > #{maxUpdateTime}") | ||
| 25 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 26 | - | ||
| 27 | default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) { | 22 | default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) { |
| 28 | return selectPage(reqVO, new QueryWrapperX<PayChannelDO>() | 23 | return selectPage(reqVO, new QueryWrapperX<PayChannelDO>() |
| 29 | .eqIfPresent("code", reqVO.getCode()) | 24 | .eqIfPresent("code", reqVO.getCode()) |
| @@ -67,14 +62,14 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> { | @@ -67,14 +62,14 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> { | ||
| 67 | * 根据条件获取渠道 | 62 | * 根据条件获取渠道 |
| 68 | * | 63 | * |
| 69 | * @param merchantId 商户编号 | 64 | * @param merchantId 商户编号 |
| 70 | - * @param appid 应用编号 // TODO @aquan:appid =》appId | 65 | + * @param appI 应用编号 |
| 71 | * @param code 渠道编码 | 66 | * @param code 渠道编码 |
| 72 | * @return 数量 | 67 | * @return 数量 |
| 73 | */ | 68 | */ |
| 74 | - default PayChannelDO selectOne(Long merchantId, Long appid, String code) { | 69 | + default PayChannelDO selectOne(Long merchantId, Long appI, String code) { |
| 75 | return this.selectOne((new QueryWrapper<PayChannelDO>().lambda() | 70 | return this.selectOne((new QueryWrapper<PayChannelDO>().lambda() |
| 76 | .eq(PayChannelDO::getMerchantId, merchantId) | 71 | .eq(PayChannelDO::getMerchantId, merchantId) |
| 77 | - .eq(PayChannelDO::getAppId, appid) | 72 | + .eq(PayChannelDO::getAppId, appI) |
| 78 | .eq(PayChannelDO::getCode, code) | 73 | .eq(PayChannelDO::getCode, code) |
| 79 | )); | 74 | )); |
| 80 | } | 75 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java
| @@ -5,7 +5,6 @@ import cn.hutool.json.JSONUtil; | @@ -5,7 +5,6 @@ import cn.hutool.json.JSONUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | 6 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 9 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; | 8 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 10 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | 9 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 11 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | 10 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| @@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; | @@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; | ||
| 19 | import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper; | 18 | import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper; |
| 20 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; | 19 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; |
| 21 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
| 22 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 23 | import org.springframework.stereotype.Service; | 21 | import org.springframework.stereotype.Service; |
| 24 | import org.springframework.validation.annotation.Validated; | 22 | import org.springframework.validation.annotation.Validated; |
| 25 | 23 | ||
| @@ -45,12 +43,6 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_E | @@ -45,12 +43,6 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_E | ||
| 45 | public class PayChannelServiceImpl implements PayChannelService { | 43 | public class PayChannelServiceImpl implements PayChannelService { |
| 46 | 44 | ||
| 47 | /** | 45 | /** |
| 48 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 49 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 50 | - */ | ||
| 51 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 52 | - | ||
| 53 | - /** | ||
| 54 | * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 | 46 | * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 |
| 55 | */ | 47 | */ |
| 56 | private volatile LocalDateTime maxUpdateTime; | 48 | private volatile LocalDateTime maxUpdateTime; |
| @@ -70,40 +62,15 @@ public class PayChannelServiceImpl implements PayChannelService { | @@ -70,40 +62,15 @@ public class PayChannelServiceImpl implements PayChannelService { | ||
| 70 | @Override | 62 | @Override |
| 71 | @PostConstruct | 63 | @PostConstruct |
| 72 | public void initLocalCache() { | 64 | public void initLocalCache() { |
| 73 | - initLocalCacheIfUpdate(null); | ||
| 74 | - } | ||
| 75 | - | ||
| 76 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 77 | - public void schedulePeriodicRefresh() { | ||
| 78 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - /** | ||
| 82 | - * 刷新本地缓存 | ||
| 83 | - * | ||
| 84 | - * @param maxUpdateTime 最大更新时间 | ||
| 85 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 86 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 87 | - */ | ||
| 88 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 89 | // 注意:忽略自动多租户,因为要全局初始化缓存 | 65 | // 注意:忽略自动多租户,因为要全局初始化缓存 |
| 90 | TenantUtils.executeIgnore(() -> { | 66 | TenantUtils.executeIgnore(() -> { |
| 91 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 92 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 93 | - if (maxUpdateTime != null | ||
| 94 | - && channelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 95 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 96 | - return; | ||
| 97 | - } | 67 | + // 第一步:查询数据 |
| 98 | List<PayChannelDO> channels = channelMapper.selectList(); | 68 | List<PayChannelDO> channels = channelMapper.selectList(); |
| 99 | - log.info("[initLocalCacheIfUpdate][缓存支付渠道,数量为:{}]", channels.size()); | 69 | + log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size()); |
| 100 | 70 | ||
| 101 | - // 第二步:构建缓存。创建或更新支付 Client | 71 | + // 第二步:构建缓存:创建或更新支付 Client |
| 102 | channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), | 72 | channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), |
| 103 | payChannel.getCode(), payChannel.getConfig())); | 73 | payChannel.getCode(), payChannel.getConfig())); |
| 104 | - | ||
| 105 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 106 | - this.maxUpdateTime = CollectionUtils.getMaxValue(channels, PayChannelDO::getUpdateTime); | ||
| 107 | }); | 74 | }); |
| 108 | } | 75 | } |
| 109 | 76 |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/mail/MailSendApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.system.api.mail.dto.MailSendSingleToUserReqDTO; | ||
| 4 | + | ||
| 5 | +import javax.validation.Valid; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 邮箱发送 API 接口 | ||
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 11 | + */ | ||
| 12 | +public interface MailSendApi { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 发送单条邮箱给 Admin 用户 | ||
| 16 | + * | ||
| 17 | + * 在 mail 为空时,使用 userId 加载对应 Admin 的邮箱 | ||
| 18 | + * | ||
| 19 | + * @param reqDTO 发送请求 | ||
| 20 | + * @return 发送日志编号 | ||
| 21 | + */ | ||
| 22 | + Long sendSingleMailToAdmin(@Valid MailSendSingleToUserReqDTO reqDTO); | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 发送单条邮箱给 Member 用户 | ||
| 26 | + * | ||
| 27 | + * 在 mail 为空时,使用 userId 加载对应 Member 的邮箱 | ||
| 28 | + * | ||
| 29 | + * @param reqDTO 发送请求 | ||
| 30 | + * @return 发送日志编号 | ||
| 31 | + */ | ||
| 32 | + Long sendSingleMailToMember(@Valid MailSendSingleToUserReqDTO reqDTO); | ||
| 33 | + | ||
| 34 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.mail.dto; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import javax.validation.constraints.Email; | ||
| 6 | +import javax.validation.constraints.NotNull; | ||
| 7 | +import java.util.Map; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 邮件发送 Request DTO | ||
| 11 | + * | ||
| 12 | + * @author wangjingqi | ||
| 13 | + */ | ||
| 14 | +@Data | ||
| 15 | +public class MailSendSingleToUserReqDTO { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 用户编号 | ||
| 19 | + */ | ||
| 20 | + private Long userId; | ||
| 21 | + /** | ||
| 22 | + * 邮箱 | ||
| 23 | + */ | ||
| 24 | |||
| 25 | + private String mail; | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 邮件模板编号 | ||
| 29 | + */ | ||
| 30 | + @NotNull(message = "邮件模板编号不能为空") | ||
| 31 | + private String templateCode; | ||
| 32 | + /** | ||
| 33 | + * 邮件模板参数 | ||
| 34 | + */ | ||
| 35 | + private Map<String, Object> templateParams; | ||
| 36 | + | ||
| 37 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| @@ -141,4 +141,16 @@ public interface ErrorCodeConstants { | @@ -141,4 +141,16 @@ public interface ErrorCodeConstants { | ||
| 141 | ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在"); | 141 | ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在"); |
| 142 | ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022001, "code 已过期"); | 142 | ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022001, "code 已过期"); |
| 143 | 143 | ||
| 144 | + // ========== 邮箱账号 1002023000 ========== | ||
| 145 | + ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1002023000, "邮箱账号不存在"); | ||
| 146 | + ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1002023001, "无法删除,该邮箱账号还有邮件模板"); | ||
| 147 | + | ||
| 148 | + // ========== 邮件模版 1002024000 ========== | ||
| 149 | + ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1002024000, "邮件模版不存在"); | ||
| 150 | + ErrorCode MAIL_TEMPLATE_CODE_EXISTS = new ErrorCode(1002024001, "邮件模版 code({}) 已存在"); | ||
| 151 | + | ||
| 152 | + // ========== 邮件发送 1002025000 ========== | ||
| 153 | + ErrorCode MAIL_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1002025000, "模板参数({})缺失"); | ||
| 154 | + ErrorCode MAIL_SEND_MAIL_NOT_EXISTS = new ErrorCode(1002025000, "邮箱不存在"); | ||
| 155 | + | ||
| 144 | } | 156 | } |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/mail/MailSendStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.enums.mail; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 邮件的发送状态枚举 | ||
| 8 | + * | ||
| 9 | + * @author wangjingyi | ||
| 10 | + * @since 2022/4/10 13:39 | ||
| 11 | + */ | ||
| 12 | +@Getter | ||
| 13 | +@AllArgsConstructor | ||
| 14 | +public enum MailSendStatusEnum { | ||
| 15 | + | ||
| 16 | + INIT(0), // 初始化 | ||
| 17 | + SUCCESS(10), // 发送成功 | ||
| 18 | + FAILURE(20), // 发送失败 | ||
| 19 | + IGNORE(30), // 忽略,即不发送 | ||
| 20 | + ; | ||
| 21 | + | ||
| 22 | + private final int status; | ||
| 23 | + | ||
| 24 | +} |
yudao-module-system/yudao-module-system-biz/pom.xml
| @@ -111,6 +111,10 @@ | @@ -111,6 +111,10 @@ | ||
| 111 | <artifactId>yudao-spring-boot-starter-captcha</artifactId> | 111 | <artifactId>yudao-spring-boot-starter-captcha</artifactId> |
| 112 | </dependency> | 112 | </dependency> |
| 113 | 113 | ||
| 114 | + <dependency> | ||
| 115 | + <groupId>org.springframework.boot</groupId> | ||
| 116 | + <artifactId>spring-boot-starter-mail</artifactId> | ||
| 117 | + </dependency> | ||
| 114 | </dependencies> | 118 | </dependencies> |
| 115 | 119 | ||
| 116 | </project> | 120 | </project> |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/mail/MailSendApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.system.api.mail.dto.MailSendSingleToUserReqDTO; | ||
| 4 | +import cn.iocoder.yudao.module.system.service.mail.MailSendService; | ||
| 5 | +import org.springframework.stereotype.Service; | ||
| 6 | +import org.springframework.validation.annotation.Validated; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 邮件发送 API 实现类 | ||
| 12 | + * | ||
| 13 | + * @author wangjingyi | ||
| 14 | + */ | ||
| 15 | +@Service | ||
| 16 | +@Validated | ||
| 17 | +public class MailSendApiImpl implements MailSendApi { | ||
| 18 | + | ||
| 19 | + @Resource | ||
| 20 | + private MailSendService mailSendService; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public Long sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) { | ||
| 24 | + return mailSendService.sendSingleMailToAdmin(reqDTO.getMail(), reqDTO.getUserId(), | ||
| 25 | + reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public Long sendSingleMailToMember(MailSendSingleToUserReqDTO reqDTO) { | ||
| 30 | + return mailSendService.sendSingleMailToMember(reqDTO.getMail(), reqDTO.getUserId(), | ||
| 31 | + reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailAccountController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.*; | ||
| 7 | +import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.service.mail.MailAccountService; | ||
| 10 | +import io.swagger.annotations.Api; | ||
| 11 | +import io.swagger.annotations.ApiImplicitParam; | ||
| 12 | +import io.swagger.annotations.ApiOperation; | ||
| 13 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 14 | +import org.springframework.web.bind.annotation.*; | ||
| 15 | + | ||
| 16 | +import javax.annotation.Resource; | ||
| 17 | +import javax.validation.Valid; | ||
| 18 | +import java.util.Comparator; | ||
| 19 | +import java.util.List; | ||
| 20 | + | ||
| 21 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 22 | + | ||
| 23 | +@Api(tags = "管理后台 - 邮箱账号") | ||
| 24 | +@RestController | ||
| 25 | +@RequestMapping("/system/mail-account") | ||
| 26 | +public class MailAccountController { | ||
| 27 | + | ||
| 28 | + @Resource | ||
| 29 | + private MailAccountService mailAccountService; | ||
| 30 | + | ||
| 31 | + @PostMapping("/create") | ||
| 32 | + @ApiOperation("创建邮箱账号") | ||
| 33 | + @PreAuthorize("@ss.hasPermission('system:mail-account:create')") | ||
| 34 | + public CommonResult<Long> createMailAccount(@Valid @RequestBody MailAccountCreateReqVO createReqVO) { | ||
| 35 | + return success(mailAccountService.createMailAccount(createReqVO)); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @PutMapping("/update") | ||
| 39 | + @ApiOperation("修改邮箱账号") | ||
| 40 | + @PreAuthorize("@ss.hasPermission('system:mail-account:update')") | ||
| 41 | + public CommonResult<Boolean> updateMailAccount(@Valid @RequestBody MailAccountUpdateReqVO updateReqVO) { | ||
| 42 | + mailAccountService.updateMailAccount(updateReqVO); | ||
| 43 | + return success(true); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + @DeleteMapping("/delete") | ||
| 47 | + @ApiOperation("删除邮箱账号") | ||
| 48 | + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | ||
| 49 | + @PreAuthorize("@ss.hasPermission('system:mail-account:delete')") | ||
| 50 | + public CommonResult<Boolean> deleteMailAccount(@RequestParam Long id) { | ||
| 51 | + mailAccountService.deleteMailAccount(id); | ||
| 52 | + return success(true); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @GetMapping("/get") | ||
| 56 | + @ApiOperation("获得邮箱账号") | ||
| 57 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||
| 58 | + @PreAuthorize("@ss.hasPermission('system:mail-account:get')") | ||
| 59 | + public CommonResult<MailAccountRespVO> getMailAccount(@RequestParam("id") Long id) { | ||
| 60 | + MailAccountDO mailAccountDO = mailAccountService.getMailAccount(id); | ||
| 61 | + return success(MailAccountConvert.INSTANCE.convert(mailAccountDO)); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + @GetMapping("/page") | ||
| 65 | + @ApiOperation("获得邮箱账号分页") | ||
| 66 | + @PreAuthorize("@ss.hasPermission('system:mail-account:query')") | ||
| 67 | + public CommonResult<PageResult<MailAccountBaseVO>> getMailAccountPage(@Valid MailAccountPageReqVO pageReqVO) { | ||
| 68 | + PageResult<MailAccountDO> pageResult = mailAccountService.getMailAccountPage(pageReqVO); | ||
| 69 | + return success(MailAccountConvert.INSTANCE.convertPage(pageResult)); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @GetMapping("/list-all-simple") | ||
| 73 | + @ApiOperation(value = "获得邮箱账号精简列表") | ||
| 74 | + public CommonResult<List<MailAccountSimpleRespVO>> getSimpleMailAccountList() { | ||
| 75 | + List<MailAccountDO> list = mailAccountService.getMailAccountList(); | ||
| 76 | + return success(MailAccountConvert.INSTANCE.convertList02(list)); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailLogController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.system.convert.mail.MailLogConvert; | ||
| 10 | +import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; | ||
| 11 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 12 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 13 | +import cn.iocoder.yudao.module.system.service.mail.MailLogService; | ||
| 14 | +import io.swagger.annotations.Api; | ||
| 15 | +import io.swagger.annotations.ApiImplicitParam; | ||
| 16 | +import io.swagger.annotations.ApiOperation; | ||
| 17 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 18 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 21 | +import org.springframework.web.bind.annotation.RestController; | ||
| 22 | + | ||
| 23 | +import javax.annotation.Resource; | ||
| 24 | +import javax.validation.Valid; | ||
| 25 | + | ||
| 26 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +@Api(tags = "管理后台 - 邮件日志") | ||
| 30 | +@RestController | ||
| 31 | +@RequestMapping("/system/mail-log") | ||
| 32 | +public class MailLogController { | ||
| 33 | + | ||
| 34 | + @Resource | ||
| 35 | + private MailLogService mailLogService; | ||
| 36 | + | ||
| 37 | + @GetMapping("/page") | ||
| 38 | + @ApiOperation("获得邮箱日志分页") | ||
| 39 | + @PreAuthorize("@ss.hasPermission('system:mail-log:query')") | ||
| 40 | + public CommonResult<PageResult<MailLogRespVO>> getMailLogPage(@Valid MailLogPageReqVO pageVO) { | ||
| 41 | + PageResult<MailLogDO> pageResult = mailLogService.getMailLogPage(pageVO); | ||
| 42 | + return success(MailLogConvert.INSTANCE.convertPage(pageResult)); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @GetMapping("/get") | ||
| 46 | + @ApiOperation("获得邮箱日志") | ||
| 47 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||
| 48 | + @PreAuthorize("@ss.hasPermission('system:mail-log:query')") | ||
| 49 | + public CommonResult<MailLogRespVO> getMailTemplate(@RequestParam("id") Long id) { | ||
| 50 | + MailLogDO mailLogDO = mailLogService.getMailLog(id); | ||
| 51 | + return success(MailLogConvert.INSTANCE.convert(mailLogDO)); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.http
0 → 100644
| 1 | +### 请求 /system/mail-template/send-mail 接口 => 成功 | ||
| 2 | +POST {{baseUrl}}/system/mail-template/send-mail | ||
| 3 | +Authorization: Bearer {{token}} | ||
| 4 | +Content-Type: application/json | ||
| 5 | +tenant-id: {{adminTenentId}} | ||
| 6 | + | ||
| 7 | +{ | ||
| 8 | + "templateCode": "test_01", | ||
| 9 | + "mail": "7685413@qq.com", | ||
| 10 | + "templateParams": { | ||
| 11 | + "key01": "value01", | ||
| 12 | + "key02": "value02" | ||
| 13 | + } | ||
| 14 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.*; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.service.mail.MailSendService; | ||
| 10 | +import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; | ||
| 11 | +import io.swagger.annotations.Api; | ||
| 12 | +import io.swagger.annotations.ApiImplicitParam; | ||
| 13 | +import io.swagger.annotations.ApiOperation; | ||
| 14 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 15 | +import org.springframework.web.bind.annotation.*; | ||
| 16 | + | ||
| 17 | +import javax.annotation.Resource; | ||
| 18 | +import javax.validation.Valid; | ||
| 19 | +import java.util.List; | ||
| 20 | + | ||
| 21 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 22 | + | ||
| 23 | +@Api(tags = "管理后台 - 邮件模版") | ||
| 24 | +@RestController | ||
| 25 | +@RequestMapping("/system/mail-template") | ||
| 26 | +public class MailTemplateController { | ||
| 27 | + | ||
| 28 | + @Resource | ||
| 29 | + private MailTemplateService mailTempleService; | ||
| 30 | + @Resource | ||
| 31 | + private MailSendService mailSendService; | ||
| 32 | + | ||
| 33 | + @PostMapping("/create") | ||
| 34 | + @ApiOperation("创建邮件模版") | ||
| 35 | + @PreAuthorize("@ss.hasPermission('system:mail-template:create')") | ||
| 36 | + public CommonResult<Long> createMailTemplate(@Valid @RequestBody MailTemplateCreateReqVO createReqVO){ | ||
| 37 | + return success(mailTempleService.createMailTemplate(createReqVO)); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @PutMapping("/update") | ||
| 41 | + @ApiOperation("修改邮件模版") | ||
| 42 | + @PreAuthorize("@ss.hasPermission('system:mail-template:update')") | ||
| 43 | + public CommonResult<Boolean> updateMailTemplate(@Valid @RequestBody MailTemplateUpdateReqVO updateReqVO){ | ||
| 44 | + mailTempleService.updateMailTemplate(updateReqVO); | ||
| 45 | + return success(true); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @DeleteMapping("/delete") | ||
| 49 | + @ApiOperation("删除邮件模版") | ||
| 50 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||
| 51 | + @PreAuthorize("@ss.hasPermission('system:mail-template:delete')") | ||
| 52 | + public CommonResult<Boolean> deleteMailTemplate(@RequestParam("id") Long id) { | ||
| 53 | + mailTempleService.deleteMailTemplate(id); | ||
| 54 | + return success(true); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @GetMapping("/get") | ||
| 58 | + @ApiOperation("获得邮件模版") | ||
| 59 | + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||
| 60 | + @PreAuthorize("@ss.hasPermission('system:mail-template:get')") | ||
| 61 | + public CommonResult<MailTemplateRespVO> getMailTemplate(@RequestParam("id") Long id) { | ||
| 62 | + MailTemplateDO mailTemplateDO = mailTempleService.getMailTemplate(id); | ||
| 63 | + return success(MailTemplateConvert.INSTANCE.convert(mailTemplateDO)); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @GetMapping("/page") | ||
| 67 | + @ApiOperation("获得邮件模版分页") | ||
| 68 | + @PreAuthorize("@ss.hasPermission('system:mail-template:query')") | ||
| 69 | + public CommonResult<PageResult<MailTemplateRespVO>> getMailTemplatePage(@Valid MailTemplatePageReqVO pageReqVO) { | ||
| 70 | + PageResult<MailTemplateDO> pageResult = mailTempleService.getMailTemplatePage(pageReqVO); | ||
| 71 | + return success(MailTemplateConvert.INSTANCE.convertPage(pageResult)); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @GetMapping("/list-all-simple") | ||
| 75 | + @ApiOperation(value = "获得邮件模版精简列表") | ||
| 76 | + public CommonResult<List<MailTemplateSimpleRespVO>> getSimpleTemplateList() { | ||
| 77 | + List<MailTemplateDO> list = mailTempleService.getMailTemplateList(); | ||
| 78 | + return success(MailTemplateConvert.INSTANCE.convertList02(list)); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @PostMapping("/send-mail") | ||
| 82 | + @ApiOperation("发送短信") | ||
| 83 | + @PreAuthorize("@ss.hasPermission('system:mail-template:send-mail')") | ||
| 84 | + public CommonResult<Long> sendMail(@Valid @RequestBody MailTemplateSendReqVO sendReqVO) { | ||
| 85 | + return success(mailSendService.sendSingleMailToAdmin(sendReqVO.getMail(), null, | ||
| 86 | + sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams())); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModelProperty; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import javax.validation.constraints.Email; | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 邮箱账号 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 11 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 12 | + */ | ||
| 13 | +@Data | ||
| 14 | +public class MailAccountBaseVO { | ||
| 15 | + | ||
| 16 | + @ApiModelProperty(value = "邮箱", required = true, example = "yudaoyuanma@123.com") | ||
| 17 | + @NotNull(message = "邮箱不能为空") | ||
| 18 | + @Email(message = "必须是 Email 格式") | ||
| 19 | + private String mail; | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "用户名", required = true, example = "yudao") | ||
| 22 | + @NotNull(message = "用户名不能为空") | ||
| 23 | + private String username; | ||
| 24 | + | ||
| 25 | + @ApiModelProperty(value = "密码", required = true, example = "123456") | ||
| 26 | + @NotNull(message = "密码必填") | ||
| 27 | + private String password; | ||
| 28 | + | ||
| 29 | + @ApiModelProperty(value = "SMTP 服务器域名", required = true, example = "www.iocoder.cn") | ||
| 30 | + @NotNull(message = "SMTP 服务器域名不能为空") | ||
| 31 | + private String host; | ||
| 32 | + | ||
| 33 | + @ApiModelProperty(value = "SMTP 服务器端口", required = true, example = "80") | ||
| 34 | + @NotNull(message = "SMTP 服务器端口不能为空") | ||
| 35 | + private Integer port; | ||
| 36 | + | ||
| 37 | + @ApiModelProperty(value = "是否开启 ssl", required = true, example = "true") | ||
| 38 | + @NotNull(message = "是否开启 ssl 必填") | ||
| 39 | + private Boolean sslEnable; | ||
| 40 | + | ||
| 41 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import javax.validation.constraints.NotNull; | ||
| 10 | + | ||
| 11 | +@ApiModel("管理后台 - 邮箱账号创建 Request VO") | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +@ToString(callSuper = true) | ||
| 15 | +public class MailAccountCreateReqVO extends MailAccountBaseVO { | ||
| 16 | + | ||
| 17 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.annotations.ApiModel; | ||
| 5 | +import io.swagger.annotations.ApiModelProperty; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.ToString; | ||
| 9 | + | ||
| 10 | +@ApiModel("管理后台 - 邮箱账号分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +@ToString(callSuper = true) | ||
| 14 | +public class MailAccountPageReqVO extends PageParam { | ||
| 15 | + | ||
| 16 | + @ApiModelProperty(value = "邮箱", required = true, example = "yudaoyuanma@123.com") | ||
| 17 | + private String mail; | ||
| 18 | + | ||
| 19 | + @ApiModelProperty(value = "用户名" , required = true , example = "yudao") | ||
| 20 | + private String username; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import javax.validation.constraints.NotNull; | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | + | ||
| 12 | +@ApiModel("管理后台 - 邮箱账号 Response VO") | ||
| 13 | +@Data | ||
| 14 | +@EqualsAndHashCode(callSuper = true) | ||
| 15 | +@ToString(callSuper = true) | ||
| 16 | +public class MailAccountRespVO extends MailAccountBaseVO { | ||
| 17 | + | ||
| 18 | + @ApiModelProperty(value = "编号", required = true, example = "1024") | ||
| 19 | + @NotNull(message = "编号不能为空") | ||
| 20 | + private Long id; | ||
| 21 | + | ||
| 22 | + @ApiModelProperty(value = "创建时间", required = true) | ||
| 23 | + private LocalDateTime createTime; | ||
| 24 | + | ||
| 25 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountSimpleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@ApiModel("管理后台 - 邮箱账号的精简 Response VO") | ||
| 8 | +@Data | ||
| 9 | +public class MailAccountSimpleRespVO { | ||
| 10 | + | ||
| 11 | + @ApiModelProperty(value = "邮箱编号", required = true, example = "1024") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "邮箱", required = true, example = "768541388@qq.com") | ||
| 15 | + private String mail; | ||
| 16 | + | ||
| 17 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import javax.validation.constraints.NotNull; | ||
| 10 | + | ||
| 11 | +@ApiModel("管理后台 - 邮箱账号修改 Request VO") | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +@ToString(callSuper = true) | ||
| 15 | +public class MailAccountUpdateReqVO extends MailAccountBaseVO { | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "编号", required = true, example = "1024") | ||
| 18 | + @NotNull(message = "编号不能为空") | ||
| 19 | + private Long id; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; | ||
| 2 | + | ||
| 3 | +import lombok.*; | ||
| 4 | +import java.util.*; | ||
| 5 | +import java.time.LocalDateTime; | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.time.LocalDateTime; | ||
| 8 | +import io.swagger.annotations.*; | ||
| 9 | +import javax.validation.constraints.*; | ||
| 10 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 11 | + | ||
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | +* 邮件日志 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 16 | +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 17 | +*/ | ||
| 18 | +@Data | ||
| 19 | +public class MailLogBaseVO { | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "用户编号", example = "30883") | ||
| 22 | + private Long userId; | ||
| 23 | + | ||
| 24 | + @ApiModelProperty(value = "用户类型", example = "2", notes = "参见 UserTypeEnum 枚举") | ||
| 25 | + private Byte userType; | ||
| 26 | + | ||
| 27 | + @ApiModelProperty(value = "接收邮箱地址", required = true, example = "76854@qq.com") | ||
| 28 | + @NotNull(message = "接收邮箱地址不能为空") | ||
| 29 | + private String toMail; | ||
| 30 | + | ||
| 31 | + @ApiModelProperty(value = "邮箱账号编号", required = true, example = "18107") | ||
| 32 | + @NotNull(message = "邮箱账号编号不能为空") | ||
| 33 | + private Long accountId; | ||
| 34 | + | ||
| 35 | + @ApiModelProperty(value = "发送邮箱地址", required = true, example = "85757@qq.com") | ||
| 36 | + @NotNull(message = "发送邮箱地址不能为空") | ||
| 37 | + private String fromMail; | ||
| 38 | + | ||
| 39 | + @ApiModelProperty(value = "模板编号", required = true, example = "5678") | ||
| 40 | + @NotNull(message = "模板编号不能为空") | ||
| 41 | + private Long templateId; | ||
| 42 | + | ||
| 43 | + @ApiModelProperty(value = "模板编码", required = true, example = "test_01") | ||
| 44 | + @NotNull(message = "模板编码不能为空") | ||
| 45 | + private String templateCode; | ||
| 46 | + | ||
| 47 | + @ApiModelProperty(value = "模版发送人名称", example = "李四") | ||
| 48 | + private String templateNickname; | ||
| 49 | + | ||
| 50 | + @ApiModelProperty(value = "邮件标题", required = true, example = "测试标题") | ||
| 51 | + @NotNull(message = "邮件标题不能为空") | ||
| 52 | + private String templateTitle; | ||
| 53 | + | ||
| 54 | + @ApiModelProperty(value = "邮件内容", required = true, example = "测试内容") | ||
| 55 | + @NotNull(message = "邮件内容不能为空") | ||
| 56 | + private String templateContent; | ||
| 57 | + | ||
| 58 | + @ApiModelProperty(value = "邮件参数", required = true) | ||
| 59 | + @NotNull(message = "邮件参数不能为空") | ||
| 60 | + private Map<String, Object> templateParams; | ||
| 61 | + | ||
| 62 | + @ApiModelProperty(value = "发送状态", required = true, example = "1", notes = "参见 MailSendStatusEnum 枚举") | ||
| 63 | + @NotNull(message = "发送状态不能为空") | ||
| 64 | + private Byte sendStatus; | ||
| 65 | + | ||
| 66 | + @ApiModelProperty(value = "发送时间") | ||
| 67 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 68 | + private LocalDateTime sendTime; | ||
| 69 | + | ||
| 70 | + @ApiModelProperty(value = "发送返回的消息 ID", example = "28568") | ||
| 71 | + private String sendMessageId; | ||
| 72 | + | ||
| 73 | + @ApiModelProperty(value = "发送异常") | ||
| 74 | + private String sendException; | ||
| 75 | + | ||
| 76 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.annotations.ApiModel; | ||
| 5 | +import io.swagger.annotations.ApiModelProperty; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.ToString; | ||
| 9 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 10 | + | ||
| 11 | +import java.sql.Timestamp; | ||
| 12 | +import java.time.LocalDateTime; | ||
| 13 | + | ||
| 14 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 15 | + | ||
| 16 | +@ApiModel("管理后台 - 邮箱日志分页 Request VO") | ||
| 17 | +@Data | ||
| 18 | +@EqualsAndHashCode(callSuper = true) | ||
| 19 | +@ToString(callSuper = true) | ||
| 20 | +public class MailLogPageReqVO extends PageParam { | ||
| 21 | + | ||
| 22 | + @ApiModelProperty(value = "用户编号", example = "30883") | ||
| 23 | + private Long userId; | ||
| 24 | + | ||
| 25 | + @ApiModelProperty(value = "用户类型", example = "2", notes = "参见 UserTypeEnum 枚举") | ||
| 26 | + private Integer userType; | ||
| 27 | + | ||
| 28 | + @ApiModelProperty(value = "接收邮箱地址", example = "76854@qq.com", notes = "模糊匹配") | ||
| 29 | + private String toMail; | ||
| 30 | + | ||
| 31 | + @ApiModelProperty(value = "邮箱账号编号", example = "18107") | ||
| 32 | + private Long accountId; | ||
| 33 | + | ||
| 34 | + @ApiModelProperty(value = "模板编号", example = "5678") | ||
| 35 | + private Long templateId; | ||
| 36 | + | ||
| 37 | + @ApiModelProperty(value = "发送状态", example = "1", notes = "参见 MailSendStatusEnum 枚举") | ||
| 38 | + private Integer sendStatus; | ||
| 39 | + | ||
| 40 | + @ApiModelProperty(value = "发送时间") | ||
| 41 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 42 | + private LocalDateTime[] sendTime; | ||
| 43 | + | ||
| 44 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; | ||
| 2 | + | ||
| 3 | +import lombok.*; | ||
| 4 | +import java.time.LocalDateTime; | ||
| 5 | +import io.swagger.annotations.*; | ||
| 6 | + | ||
| 7 | +@ApiModel("管理后台 - 邮件日志 Response VO") | ||
| 8 | +@Data | ||
| 9 | +@EqualsAndHashCode(callSuper = true) | ||
| 10 | +@ToString(callSuper = true) | ||
| 11 | +public class MailLogRespVO extends MailLogBaseVO { | ||
| 12 | + | ||
| 13 | + @ApiModelProperty(value = "编号", required = true, example = "31020") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @ApiModelProperty(value = "创建时间", required = true) | ||
| 17 | + private LocalDateTime createTime; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotEmpty; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 邮件模版 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 12 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 13 | + */ | ||
| 14 | +@Data | ||
| 15 | +public class MailTemplateBaseVO { | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "模版名称", required = true, example = "测试名字") | ||
| 18 | + @NotNull(message = "名称不能为空") | ||
| 19 | + private String name; | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "模版编号", required = true, example = "test") | ||
| 22 | + @NotNull(message = "模版编号不能为空") | ||
| 23 | + private String code; | ||
| 24 | + | ||
| 25 | + @ApiModelProperty(value = "发送的邮箱账号编号", required = true, example = "1") | ||
| 26 | + @NotNull(message = "发送的邮箱账号编号不能为空") | ||
| 27 | + private Long accountId; | ||
| 28 | + | ||
| 29 | + @ApiModelProperty(value = "发送人名称", example = "芋头") | ||
| 30 | + private String nickname; | ||
| 31 | + | ||
| 32 | + @ApiModelProperty(value = "标题", required = true, example = "注册成功") | ||
| 33 | + @NotEmpty(message = "标题不能为空") | ||
| 34 | + private String title; | ||
| 35 | + | ||
| 36 | + @ApiModelProperty(value = "内容", required = true, example = "你好,注册成功啦") | ||
| 37 | + @NotEmpty(message = "内容不能为空") | ||
| 38 | + private String content; | ||
| 39 | + | ||
| 40 | + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") | ||
| 41 | + @NotNull(message = "状态不能为空") | ||
| 42 | + private Integer status; | ||
| 43 | + | ||
| 44 | + @ApiModelProperty(value = "备注", example = "奥特曼") | ||
| 45 | + private String remark; | ||
| 46 | + | ||
| 47 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | +import lombok.ToString; | ||
| 7 | + | ||
| 8 | +@ApiModel("管理后台 - 邮件模版创建 Request VO") | ||
| 9 | +@Data | ||
| 10 | +@EqualsAndHashCode(callSuper = true) | ||
| 11 | +@ToString(callSuper = true) | ||
| 12 | +public class MailTemplateCreateReqVO extends MailTemplateBaseVO { | ||
| 13 | + | ||
| 14 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplatePageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.annotations.ApiModel; | ||
| 5 | +import io.swagger.annotations.ApiModelProperty; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.ToString; | ||
| 9 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 10 | + | ||
| 11 | +import java.time.LocalDateTime; | ||
| 12 | + | ||
| 13 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 14 | + | ||
| 15 | +@ApiModel("管理后台 - 邮件模版分页 Request VO") | ||
| 16 | +@Data | ||
| 17 | +@EqualsAndHashCode(callSuper = true) | ||
| 18 | +@ToString(callSuper = true) | ||
| 19 | +public class MailTemplatePageReqVO extends PageParam { | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "状态", example = "1", notes = "参见 CommonStatusEnum 枚举") | ||
| 22 | + private Integer status; | ||
| 23 | + | ||
| 24 | + @ApiModelProperty(value = "标识", example = "code_1024", notes = "模糊匹配") | ||
| 25 | + private String code; | ||
| 26 | + | ||
| 27 | + @ApiModelProperty(value = "名称", example = "芋头", notes = "模糊匹配") | ||
| 28 | + private String name; | ||
| 29 | + | ||
| 30 | + @ApiModelProperty(value = "账号编号", example = "2048") | ||
| 31 | + private Long accountId; | ||
| 32 | + | ||
| 33 | + @ApiModelProperty(value = "创建时间") | ||
| 34 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 35 | + private LocalDateTime[] createTime; | ||
| 36 | + | ||
| 37 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +@ApiModel("管理后台 - 邮件末班 Response VO") | ||
| 13 | +@Data | ||
| 14 | +@EqualsAndHashCode(callSuper = true) | ||
| 15 | +@ToString(callSuper = true) | ||
| 16 | +public class MailTemplateRespVO extends MailTemplateBaseVO { | ||
| 17 | + | ||
| 18 | + @ApiModelProperty(value = "编号", required = true, example = "1024") | ||
| 19 | + private Long id; | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "参数数组", example = "name,code") | ||
| 22 | + private List<String> params; | ||
| 23 | + | ||
| 24 | + @ApiModelProperty(value = "创建时间", required = true) | ||
| 25 | + private LocalDateTime createTime; | ||
| 26 | + | ||
| 27 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateSendReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotEmpty; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | +import java.util.Map; | ||
| 10 | + | ||
| 11 | +@ApiModel("管理后台 - 邮件发送 Req VO") | ||
| 12 | +@Data | ||
| 13 | +public class MailTemplateSendReqVO { | ||
| 14 | + | ||
| 15 | + @ApiModelProperty(value = "接收邮箱", required = true, example = "7685413@qq.com") | ||
| 16 | + @NotEmpty(message = "接收邮箱不能为空") | ||
| 17 | + private String mail; | ||
| 18 | + | ||
| 19 | + @ApiModelProperty(value = "模板编码", required = true, example = "test_01") | ||
| 20 | + @NotNull(message = "模板编码不能为空") | ||
| 21 | + private String templateCode; | ||
| 22 | + | ||
| 23 | + @ApiModelProperty(value = "模板参数") | ||
| 24 | + private Map<String, Object> templateParams; | ||
| 25 | + | ||
| 26 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateSimpleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@ApiModel("管理后台 - 邮件模版的精简 Response VO") | ||
| 8 | +@Data | ||
| 9 | +public class MailTemplateSimpleRespVO { | ||
| 10 | + | ||
| 11 | + @ApiModelProperty(value = "模版编号", required = true, example = "1024") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "模版名字", required = true, example = "哒哒哒") | ||
| 15 | + private String name; | ||
| 16 | + | ||
| 17 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import javax.validation.constraints.NotNull; | ||
| 10 | + | ||
| 11 | +@ApiModel("管理后台 - 邮件模版修改 Request VO") | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +@ToString(callSuper = true) | ||
| 15 | +public class MailTemplateUpdateReqVO extends MailTemplateBaseVO { | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "编号", required = true, example = "1024") | ||
| 18 | + @NotNull(message = "编号不能为空") | ||
| 19 | + private Long id; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.convert.mail; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.hutool.extra.mail.MailAccount; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.*; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 8 | +import org.mapstruct.Mapper; | ||
| 9 | +import org.mapstruct.factory.Mappers; | ||
| 10 | + | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +@Mapper | ||
| 14 | +public interface MailAccountConvert { | ||
| 15 | + | ||
| 16 | + MailAccountConvert INSTANCE = Mappers.getMapper(MailAccountConvert.class); | ||
| 17 | + | ||
| 18 | + MailAccountDO convert(MailAccountCreateReqVO bean); | ||
| 19 | + | ||
| 20 | + MailAccountDO convert(MailAccountUpdateReqVO bean); | ||
| 21 | + | ||
| 22 | + MailAccountRespVO convert(MailAccountDO bean); | ||
| 23 | + | ||
| 24 | + PageResult<MailAccountBaseVO> convertPage(PageResult<MailAccountDO> pageResult); | ||
| 25 | + | ||
| 26 | + List<MailAccountSimpleRespVO> convertList02(List<MailAccountDO> list); | ||
| 27 | + | ||
| 28 | + default MailAccount convert(MailAccountDO account, String nickname) { | ||
| 29 | + String from = StrUtil.isNotEmpty(nickname) ? nickname + " <" + account.getMail() + ">" : account.getMail(); | ||
| 30 | + return new MailAccount().setFrom(from).setAuth(true) | ||
| 31 | + .setUser(account.getUsername()).setPass(account.getPassword()) | ||
| 32 | + .setHost(account.getHost()).setPort(account.getPort()).setSslEnable(account.getSslEnable()); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailLogConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.convert.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 6 | +import org.mapstruct.Mapper; | ||
| 7 | +import org.mapstruct.factory.Mappers; | ||
| 8 | + | ||
| 9 | +@Mapper | ||
| 10 | +public interface MailLogConvert { | ||
| 11 | + | ||
| 12 | + MailLogConvert INSTANCE = Mappers.getMapper(MailLogConvert.class); | ||
| 13 | + | ||
| 14 | + PageResult<MailLogRespVO> convertPage(PageResult<MailLogDO> pageResult); | ||
| 15 | + | ||
| 16 | + MailLogRespVO convert(MailLogDO bean); | ||
| 17 | + | ||
| 18 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailTemplateConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.convert.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.*; | ||
| 5 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 6 | +import org.mapstruct.Mapper; | ||
| 7 | +import org.mapstruct.factory.Mappers; | ||
| 8 | + | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +@Mapper | ||
| 12 | +public interface MailTemplateConvert { | ||
| 13 | + | ||
| 14 | + MailTemplateConvert INSTANCE = Mappers.getMapper(MailTemplateConvert.class); | ||
| 15 | + | ||
| 16 | + MailTemplateDO convert(MailTemplateUpdateReqVO bean); | ||
| 17 | + | ||
| 18 | + MailTemplateDO convert(MailTemplateCreateReqVO bean); | ||
| 19 | + | ||
| 20 | + MailTemplateRespVO convert(MailTemplateDO bean); | ||
| 21 | + | ||
| 22 | + PageResult<MailTemplateRespVO> convertPage(PageResult<MailTemplateDO> pageResult); | ||
| 23 | + | ||
| 24 | + List<MailTemplateSimpleRespVO> convertList02(List<MailTemplateDO> list); | ||
| 25 | + | ||
| 26 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/mail/MailAccountDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.dataobject.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 邮箱账号 DO | ||
| 11 | + * | ||
| 12 | + * 用途:配置发送邮箱的账号 | ||
| 13 | + * | ||
| 14 | + * @author wangjingyi | ||
| 15 | + * @since 2022-03-21 | ||
| 16 | + */ | ||
| 17 | +@TableName(value = "system_mail_account", autoResultMap = true) | ||
| 18 | +@Data | ||
| 19 | +@EqualsAndHashCode(callSuper = true) | ||
| 20 | +public class MailAccountDO extends BaseDO { | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 主键 | ||
| 24 | + */ | ||
| 25 | + @TableId | ||
| 26 | + private Long id; | ||
| 27 | + /** | ||
| 28 | + * 邮箱 | ||
| 29 | + */ | ||
| 30 | + private String mail; | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 用户名 | ||
| 34 | + */ | ||
| 35 | + private String username; | ||
| 36 | + /** | ||
| 37 | + * 密码 | ||
| 38 | + */ | ||
| 39 | + private String password; | ||
| 40 | + /** | ||
| 41 | + * SMTP 服务器域名 | ||
| 42 | + */ | ||
| 43 | + private String host; | ||
| 44 | + /** | ||
| 45 | + * SMTP 服务器端口 | ||
| 46 | + */ | ||
| 47 | + private Integer port; | ||
| 48 | + /** | ||
| 49 | + * 是否开启 SSL | ||
| 50 | + */ | ||
| 51 | + private Boolean sslEnable; | ||
| 52 | + | ||
| 53 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/mail/MailLogDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.dataobject.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 5 | +import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | ||
| 6 | +import com.baomidou.mybatisplus.annotation.TableField; | ||
| 7 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 8 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | ||
| 9 | +import lombok.*; | ||
| 10 | + | ||
| 11 | +import java.io.Serializable; | ||
| 12 | +import java.util.Date; | ||
| 13 | +import java.util.Map; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 邮箱日志 DO | ||
| 17 | + * 记录每一次邮件的发送 | ||
| 18 | + * | ||
| 19 | + * @author wangjingyi | ||
| 20 | + * @since 2022-03-21 | ||
| 21 | + */ | ||
| 22 | +@TableName(value = "system_mail_log", autoResultMap = true) | ||
| 23 | +@Data | ||
| 24 | +@EqualsAndHashCode(callSuper = true) | ||
| 25 | +@ToString(callSuper = true) | ||
| 26 | +@Builder | ||
| 27 | +@AllArgsConstructor | ||
| 28 | +@NoArgsConstructor | ||
| 29 | +public class MailLogDO extends BaseDO implements Serializable { | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 日志编号,自增 | ||
| 33 | + */ | ||
| 34 | + private Long id; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 用户编码 | ||
| 38 | + */ | ||
| 39 | + private Long userId; | ||
| 40 | + /** | ||
| 41 | + * 用户类型 | ||
| 42 | + * | ||
| 43 | + * 枚举 {@link UserTypeEnum} | ||
| 44 | + */ | ||
| 45 | + private Integer userType; | ||
| 46 | + /** | ||
| 47 | + * 接收邮箱地址 | ||
| 48 | + */ | ||
| 49 | + private String toMail; | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 邮箱账号编号 | ||
| 53 | + * | ||
| 54 | + * 关联 {@link MailAccountDO#getId()} | ||
| 55 | + */ | ||
| 56 | + private Long accountId; | ||
| 57 | + /** | ||
| 58 | + * 发送邮箱地址 | ||
| 59 | + * | ||
| 60 | + * 冗余 {@link MailAccountDO#getMail()} | ||
| 61 | + */ | ||
| 62 | + private String fromMail; | ||
| 63 | + | ||
| 64 | + // ========= 模板相关字段 ========= | ||
| 65 | + /** | ||
| 66 | + * 模版编号 | ||
| 67 | + * | ||
| 68 | + * 关联 {@link MailTemplateDO#getId()} | ||
| 69 | + */ | ||
| 70 | + private Long templateId; | ||
| 71 | + /** | ||
| 72 | + * 模版编码 | ||
| 73 | + * | ||
| 74 | + * 冗余 {@link MailTemplateDO#getCode()} | ||
| 75 | + */ | ||
| 76 | + private String templateCode; | ||
| 77 | + /** | ||
| 78 | + * 模版发送人名称 | ||
| 79 | + * | ||
| 80 | + * 冗余 {@link MailTemplateDO#getNickname()} | ||
| 81 | + */ | ||
| 82 | + private String templateNickname; | ||
| 83 | + /** | ||
| 84 | + * 模版标题 | ||
| 85 | + */ | ||
| 86 | + private String templateTitle; | ||
| 87 | + /** | ||
| 88 | + * 模版内容 | ||
| 89 | + * | ||
| 90 | + * 基于 {@link MailTemplateDO#getContent()} 格式化后的内容 | ||
| 91 | + */ | ||
| 92 | + private String templateContent; | ||
| 93 | + /** | ||
| 94 | + * 模版参数 | ||
| 95 | + * | ||
| 96 | + * 基于 {@link MailTemplateDO#getParams()} 输入后的参数 | ||
| 97 | + */ | ||
| 98 | + @TableField(typeHandler = JacksonTypeHandler.class) | ||
| 99 | + private Map<String, Object> templateParams; | ||
| 100 | + | ||
| 101 | + // ========= 发送相关字段 ========= | ||
| 102 | + /** | ||
| 103 | + * 发送状态 | ||
| 104 | + * | ||
| 105 | + * 枚举 {@link MailSendStatusEnum} | ||
| 106 | + */ | ||
| 107 | + private Integer sendStatus; | ||
| 108 | + /** | ||
| 109 | + * 发送时间 | ||
| 110 | + */ | ||
| 111 | + private Date sendTime; | ||
| 112 | + /** | ||
| 113 | + * 发送返回的消息 ID | ||
| 114 | + */ | ||
| 115 | + private String sendMessageId; | ||
| 116 | + /** | ||
| 117 | + * 发送异常 | ||
| 118 | + */ | ||
| 119 | + private String sendException; | ||
| 120 | + | ||
| 121 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/mail/MailTemplateDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.dataobject.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableField; | ||
| 6 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 7 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | ||
| 8 | +import lombok.Data; | ||
| 9 | +import lombok.EqualsAndHashCode; | ||
| 10 | + | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 邮件模版 DO | ||
| 15 | + * | ||
| 16 | + * @author wangjingyi | ||
| 17 | + * @since 2022-03-21 | ||
| 18 | + */ | ||
| 19 | +@TableName(value = "system_mail_template", autoResultMap = true) | ||
| 20 | +@Data | ||
| 21 | +@EqualsAndHashCode(callSuper = true) | ||
| 22 | +public class MailTemplateDO extends BaseDO { | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 主键 | ||
| 26 | + */ | ||
| 27 | + private Long id; | ||
| 28 | + /** | ||
| 29 | + * 模版名称 | ||
| 30 | + */ | ||
| 31 | + private String name; | ||
| 32 | + /** | ||
| 33 | + * 模版编号 | ||
| 34 | + */ | ||
| 35 | + private String code; | ||
| 36 | + /** | ||
| 37 | + * 发送的邮箱账号编号 | ||
| 38 | + * | ||
| 39 | + * 关联 {@link MailAccountDO#getId()} | ||
| 40 | + */ | ||
| 41 | + private Long accountId; | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 发送人名称 | ||
| 45 | + */ | ||
| 46 | + private String nickname; | ||
| 47 | + /** | ||
| 48 | + * 标题 | ||
| 49 | + */ | ||
| 50 | + private String title; | ||
| 51 | + /** | ||
| 52 | + * 内容 | ||
| 53 | + */ | ||
| 54 | + private String content; | ||
| 55 | + /** | ||
| 56 | + * 参数数组(自动根据内容生成) | ||
| 57 | + */ | ||
| 58 | + @TableField(typeHandler = JacksonTypeHandler.class) | ||
| 59 | + private List<String> params; | ||
| 60 | + /** | ||
| 61 | + * 状态 | ||
| 62 | + * | ||
| 63 | + * 枚举 {@link CommonStatusEnum} | ||
| 64 | + */ | ||
| 65 | + private Integer status; | ||
| 66 | + /** | ||
| 67 | + * 备注 | ||
| 68 | + */ | ||
| 69 | + private String remark; | ||
| 70 | + | ||
| 71 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/DeptMapper.java
| @@ -6,9 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqV | @@ -6,9 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqV | ||
| 6 | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; |
| 7 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 7 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | -import org.apache.ibatis.annotations.Select; | ||
| 10 | 9 | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | import java.util.List; | 10 | import java.util.List; |
| 13 | 11 | ||
| 14 | @Mapper | 12 | @Mapper |
| @@ -30,7 +28,4 @@ public interface DeptMapper extends BaseMapperX<DeptDO> { | @@ -30,7 +28,4 @@ public interface DeptMapper extends BaseMapperX<DeptDO> { | ||
| 30 | return selectCount(DeptDO::getParentId, parentId); | 28 | return selectCount(DeptDO::getParentId, parentId); |
| 31 | } | 29 | } |
| 32 | 30 | ||
| 33 | - @Select("SELECT COUNT(*) FROM system_dept WHERE update_time > #{maxUpdateTime}") | ||
| 34 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 35 | - | ||
| 36 | } | 31 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/mail/MailAccountMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.mysql.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 9 | +import org.apache.ibatis.annotations.Mapper; | ||
| 10 | + | ||
| 11 | +@Mapper | ||
| 12 | +public interface MailAccountMapper extends BaseMapperX<MailAccountDO> { | ||
| 13 | + | ||
| 14 | + default PageResult<MailAccountDO> selectPage(MailAccountPageReqVO pageReqVO) { | ||
| 15 | + return selectPage(pageReqVO, new LambdaQueryWrapperX<MailAccountDO>() | ||
| 16 | + .likeIfPresent(MailAccountDO::getMail, pageReqVO.getMail()) | ||
| 17 | + .likeIfPresent(MailAccountDO::getUsername , pageReqVO.getUsername())); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/mail/MailLogMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.mysql.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 8 | +import org.apache.ibatis.annotations.Mapper; | ||
| 9 | + | ||
| 10 | +@Mapper | ||
| 11 | +public interface MailLogMapper extends BaseMapperX<MailLogDO> { | ||
| 12 | + | ||
| 13 | + default PageResult<MailLogDO> selectPage(MailLogPageReqVO reqVO) { | ||
| 14 | + return selectPage(reqVO, new LambdaQueryWrapperX<MailLogDO>() | ||
| 15 | + .eqIfPresent(MailLogDO::getUserId, reqVO.getUserId()) | ||
| 16 | + .eqIfPresent(MailLogDO::getUserType, reqVO.getUserType()) | ||
| 17 | + .likeIfPresent(MailLogDO::getToMail, reqVO.getToMail()) | ||
| 18 | + .eqIfPresent(MailLogDO::getAccountId, reqVO.getAccountId()) | ||
| 19 | + .eqIfPresent(MailLogDO::getTemplateId, reqVO.getTemplateId()) | ||
| 20 | + .eqIfPresent(MailLogDO::getSendStatus, reqVO.getSendStatus()) | ||
| 21 | + .betweenIfPresent(MailLogDO::getSendTime, reqVO.getSendTime()) | ||
| 22 | + .orderByDesc(MailLogDO::getId)); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/mail/MailTemplateMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.mysql.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | ||
| 10 | +import org.apache.ibatis.annotations.Mapper; | ||
| 11 | +import org.apache.ibatis.annotations.Select; | ||
| 12 | + | ||
| 13 | +import java.util.Date; | ||
| 14 | + | ||
| 15 | +@Mapper | ||
| 16 | +public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> { | ||
| 17 | + | ||
| 18 | + default PageResult<MailTemplateDO> selectPage(MailTemplatePageReqVO pageReqVO){ | ||
| 19 | + return selectPage(pageReqVO , new LambdaQueryWrapperX<MailTemplateDO>() | ||
| 20 | + .eqIfPresent(MailTemplateDO::getStatus, pageReqVO.getStatus()) | ||
| 21 | + .likeIfPresent(MailTemplateDO::getCode, pageReqVO.getCode()) | ||
| 22 | + .likeIfPresent(MailTemplateDO::getName, pageReqVO.getName()) | ||
| 23 | + .eqIfPresent(MailTemplateDO::getAccountId, pageReqVO.getAccountId()) | ||
| 24 | + .betweenIfPresent(MailTemplateDO::getCreateTime, pageReqVO.getCreateTime())); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + default Long selectCountByAccountId(Long accountId) { | ||
| 28 | + return selectCount(MailTemplateDO::getAccountId, accountId); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + default MailTemplateDO selectByCode(String code) { | ||
| 32 | + return selectOne(MailTemplateDO::getCode, code); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2ClientMapper.java
| @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | -import org.apache.ibatis.annotations.Select; | ||
| 10 | - | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | 9 | ||
| 13 | 10 | ||
| 14 | /** | 11 | /** |
| @@ -30,7 +27,4 @@ public interface OAuth2ClientMapper extends BaseMapperX<OAuth2ClientDO> { | @@ -30,7 +27,4 @@ public interface OAuth2ClientMapper extends BaseMapperX<OAuth2ClientDO> { | ||
| 30 | return selectOne(OAuth2ClientDO::getClientId, clientId); | 27 | return selectOne(OAuth2ClientDO::getClientId, clientId); |
| 31 | } | 28 | } |
| 32 | 29 | ||
| 33 | - @Select("SELECT COUNT(*) FROM system_oauth2_client WHERE update_time > #{maxUpdateTime}") | ||
| 34 | - int selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 35 | - | ||
| 36 | } | 30 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java
| @@ -6,9 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuLi | @@ -6,9 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuLi | ||
| 6 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; |
| 7 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 7 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | -import org.apache.ibatis.annotations.Select; | ||
| 10 | 9 | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | import java.util.List; | 10 | import java.util.List; |
| 13 | 11 | ||
| 14 | @Mapper | 12 | @Mapper |
| @@ -28,7 +26,4 @@ public interface MenuMapper extends BaseMapperX<MenuDO> { | @@ -28,7 +26,4 @@ public interface MenuMapper extends BaseMapperX<MenuDO> { | ||
| 28 | .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())); | 26 | .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())); |
| 29 | } | 27 | } |
| 30 | 28 | ||
| 31 | - @Select("SELECT COUNT(*) FROM system_menu WHERE update_time > #{maxUpdateTime}") | ||
| 32 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 33 | - | ||
| 34 | } | 29 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java
| @@ -8,10 +8,8 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleEx | @@ -8,10 +8,8 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleEx | ||
| 8 | import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| 10 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 11 | -import org.apache.ibatis.annotations.Select; | ||
| 12 | import org.springframework.lang.Nullable; | 11 | import org.springframework.lang.Nullable; |
| 13 | 12 | ||
| 14 | -import java.time.LocalDateTime; | ||
| 15 | import java.util.Collection; | 13 | import java.util.Collection; |
| 16 | import java.util.List; | 14 | import java.util.List; |
| 17 | 15 | ||
| @@ -47,7 +45,4 @@ public interface RoleMapper extends BaseMapperX<RoleDO> { | @@ -47,7 +45,4 @@ public interface RoleMapper extends BaseMapperX<RoleDO> { | ||
| 47 | return selectList(RoleDO::getStatus, statuses); | 45 | return selectList(RoleDO::getStatus, statuses); |
| 48 | } | 46 | } |
| 49 | 47 | ||
| 50 | - @Select("SELECT COUNT(*) FROM system_role WHERE update_time > #{maxUpdateTime}") | ||
| 51 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 52 | - | ||
| 53 | } | 48 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuBatchInsertMapper.java deleted
| 1 | -package cn.iocoder.yudao.module.system.dal.mysql.permission; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; | ||
| 4 | -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||
| 5 | -import org.springframework.stereotype.Repository; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * 实体 {@link RoleMenuDO} 的批量插入 Mapper | ||
| 9 | - * | ||
| 10 | - * @author 芋道源码 | ||
| 11 | - */ | ||
| 12 | -@Repository | ||
| 13 | -public class RoleMenuBatchInsertMapper extends ServiceImpl<RoleMenuMapper, RoleMenuDO> { | ||
| 14 | -} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java
| @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission; | @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; | 4 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; |
| 5 | -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 5 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| 7 | import org.apache.ibatis.annotations.Mapper; | 7 | import org.apache.ibatis.annotations.Mapper; |
| 8 | -import org.apache.ibatis.annotations.Select; | ||
| 9 | import org.springframework.stereotype.Repository; | 8 | import org.springframework.stereotype.Repository; |
| 10 | 9 | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | import java.util.Collection; | 10 | import java.util.Collection; |
| 13 | import java.util.List; | 11 | import java.util.List; |
| 14 | 12 | ||
| @@ -20,23 +18,21 @@ public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> { | @@ -20,23 +18,21 @@ public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> { | ||
| 20 | } | 18 | } |
| 21 | 19 | ||
| 22 | default List<RoleMenuDO> selectListByRoleId(Long roleId) { | 20 | default List<RoleMenuDO> selectListByRoleId(Long roleId) { |
| 23 | - return selectList(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId)); | 21 | + return selectList(RoleMenuDO::getRoleId, roleId); |
| 24 | } | 22 | } |
| 25 | 23 | ||
| 26 | default void deleteListByRoleIdAndMenuIds(Long roleId, Collection<Long> menuIds) { | 24 | default void deleteListByRoleIdAndMenuIds(Long roleId, Collection<Long> menuIds) { |
| 27 | - delete(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId) | ||
| 28 | - .in("menu_id", menuIds)); | 25 | + delete(new LambdaQueryWrapper<RoleMenuDO>() |
| 26 | + .eq(RoleMenuDO::getRoleId, roleId) | ||
| 27 | + .in(RoleMenuDO::getMenuId, menuIds)); | ||
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | default void deleteListByMenuId(Long menuId) { | 30 | default void deleteListByMenuId(Long menuId) { |
| 32 | - delete(new QueryWrapper<RoleMenuDO>().eq("menu_id", menuId)); | 31 | + delete(new LambdaQueryWrapper<RoleMenuDO>().eq(RoleMenuDO::getMenuId, menuId)); |
| 33 | } | 32 | } |
| 34 | 33 | ||
| 35 | default void deleteListByRoleId(Long roleId) { | 34 | default void deleteListByRoleId(Long roleId) { |
| 36 | - delete(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId)); | 35 | + delete(new LambdaQueryWrapper<RoleMenuDO>().eq(RoleMenuDO::getRoleId, roleId)); |
| 37 | } | 36 | } |
| 38 | 37 | ||
| 39 | - @Select("SELECT COUNT(*) FROM system_role_menu WHERE update_time > #{maxUpdateTime}") | ||
| 40 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 41 | - | ||
| 42 | } | 38 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/UserRoleBatchInsertMapper.java deleted
| 1 | -package cn.iocoder.yudao.module.system.dal.mysql.permission; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; | ||
| 4 | -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||
| 5 | -import org.springframework.stereotype.Repository; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * 实体 {@link UserRoleDO} 的批量插入 Mapper | ||
| 9 | - * | ||
| 10 | - * @author 芋道源码 | ||
| 11 | - */ | ||
| 12 | -@Repository | ||
| 13 | -public class UserRoleBatchInsertMapper extends ServiceImpl<UserRoleMapper, UserRoleDO> { | ||
| 14 | -} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/UserRoleMapper.java
| @@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission; | @@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; | 4 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; |
| 5 | -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 5 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 6 | import org.apache.ibatis.annotations.Mapper; | 6 | import org.apache.ibatis.annotations.Mapper; |
| 7 | -import org.apache.ibatis.annotations.Select; | ||
| 8 | 7 | ||
| 9 | -import java.time.LocalDateTime; | ||
| 10 | import java.util.Collection; | 8 | import java.util.Collection; |
| 11 | import java.util.List; | 9 | import java.util.List; |
| 12 | 10 | ||
| @@ -14,32 +12,25 @@ import java.util.List; | @@ -14,32 +12,25 @@ import java.util.List; | ||
| 14 | public interface UserRoleMapper extends BaseMapperX<UserRoleDO> { | 12 | public interface UserRoleMapper extends BaseMapperX<UserRoleDO> { |
| 15 | 13 | ||
| 16 | default List<UserRoleDO> selectListByUserId(Long userId) { | 14 | default List<UserRoleDO> selectListByUserId(Long userId) { |
| 17 | - return selectList(new QueryWrapper<UserRoleDO>().eq("user_id", userId)); | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | - default List<UserRoleDO> selectListByRoleId(Long roleId) { | ||
| 21 | - return selectList(new QueryWrapper<UserRoleDO>().eq("role_id", roleId)); | 15 | + return selectList(UserRoleDO::getUserId, userId); |
| 22 | } | 16 | } |
| 23 | 17 | ||
| 24 | default void deleteListByUserIdAndRoleIdIds(Long userId, Collection<Long> roleIds) { | 18 | default void deleteListByUserIdAndRoleIdIds(Long userId, Collection<Long> roleIds) { |
| 25 | - delete(new QueryWrapper<UserRoleDO>().eq("user_id", userId) | ||
| 26 | - .in("role_id", roleIds)); | 19 | + delete(new LambdaQueryWrapper<UserRoleDO>() |
| 20 | + .eq(UserRoleDO::getUserId, userId) | ||
| 21 | + .in(UserRoleDO::getRoleId, roleIds)); | ||
| 27 | } | 22 | } |
| 28 | 23 | ||
| 29 | default void deleteListByUserId(Long userId) { | 24 | default void deleteListByUserId(Long userId) { |
| 30 | - delete(new QueryWrapper<UserRoleDO>().eq("user_id", userId)); | 25 | + delete(new LambdaQueryWrapper<UserRoleDO>().eq(UserRoleDO::getUserId, userId)); |
| 31 | } | 26 | } |
| 32 | 27 | ||
| 33 | default void deleteListByRoleId(Long roleId) { | 28 | default void deleteListByRoleId(Long roleId) { |
| 34 | - delete(new QueryWrapper<UserRoleDO>().eq("role_id", roleId)); | 29 | + delete(new LambdaQueryWrapper<UserRoleDO>().eq(UserRoleDO::getRoleId, roleId)); |
| 35 | } | 30 | } |
| 36 | 31 | ||
| 37 | - | ||
| 38 | default List<UserRoleDO> selectListByRoleIds(Collection<Long> roleIds) { | 32 | default List<UserRoleDO> selectListByRoleIds(Collection<Long> roleIds) { |
| 39 | return selectList(UserRoleDO::getRoleId, roleIds); | 33 | return selectList(UserRoleDO::getRoleId, roleIds); |
| 40 | } | 34 | } |
| 41 | 35 | ||
| 42 | - @Select("SELECT COUNT(*) FROM system_user_role WHERE update_time > #{maxUpdateTime}") | ||
| 43 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 44 | - | ||
| 45 | } | 36 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sensitiveword/SensitiveWordMapper.java
| @@ -7,9 +7,7 @@ import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.Sensitiv | @@ -7,9 +7,7 @@ import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.Sensitiv | ||
| 7 | import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; | 7 | import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; |
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; |
| 9 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 10 | -import org.apache.ibatis.annotations.Select; | ||
| 11 | 10 | ||
| 12 | -import java.time.LocalDateTime; | ||
| 13 | import java.util.List; | 11 | import java.util.List; |
| 14 | 12 | ||
| 15 | /** | 13 | /** |
| @@ -42,7 +40,4 @@ public interface SensitiveWordMapper extends BaseMapperX<SensitiveWordDO> { | @@ -42,7 +40,4 @@ public interface SensitiveWordMapper extends BaseMapperX<SensitiveWordDO> { | ||
| 42 | return selectOne(SensitiveWordDO::getName, name); | 40 | return selectOne(SensitiveWordDO::getName, name); |
| 43 | } | 41 | } |
| 44 | 42 | ||
| 45 | - @Select("SELECT COUNT(*) FROM system_sensitive_word WHERE update_time > #{maxUpdateTime}") | ||
| 46 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 47 | - | ||
| 48 | } | 43 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsChannelMapper.java
| @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | -import org.apache.ibatis.annotations.Select; | ||
| 10 | - | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | 9 | ||
| 13 | @Mapper | 10 | @Mapper |
| 14 | public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> { | 11 | public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> { |
| @@ -21,7 +18,4 @@ public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> { | @@ -21,7 +18,4 @@ public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> { | ||
| 21 | .orderByDesc(SmsChannelDO::getId)); | 18 | .orderByDesc(SmsChannelDO::getId)); |
| 22 | } | 19 | } |
| 23 | 20 | ||
| 24 | - @Select("SELECT COUNT(*) FROM system_sms_channel WHERE update_time > #{maxUpdateTime}") | ||
| 25 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 26 | - | ||
| 27 | } | 21 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java
| @@ -7,17 +7,12 @@ import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTempla | @@ -7,17 +7,12 @@ import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTempla | ||
| 7 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; | 7 | import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; |
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; |
| 9 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 10 | -import org.apache.ibatis.annotations.Select; | ||
| 11 | 10 | ||
| 12 | -import java.time.LocalDateTime; | ||
| 13 | import java.util.List; | 11 | import java.util.List; |
| 14 | 12 | ||
| 15 | @Mapper | 13 | @Mapper |
| 16 | public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> { | 14 | public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> { |
| 17 | 15 | ||
| 18 | - @Select("SELECT COUNT(*) FROM system_sms_template WHERE update_time > #{maxUpdateTime}") | ||
| 19 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 20 | - | ||
| 21 | default SmsTemplateDO selectByCode(String code) { | 16 | default SmsTemplateDO selectByCode(String code) { |
| 22 | return selectOne(SmsTemplateDO::getCode, code); | 17 | return selectOne(SmsTemplateDO::getCode, code); |
| 23 | } | 18 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java
| 1 | package cn.iocoder.yudao.module.system.dal.mysql.tenant; | 1 | package cn.iocoder.yudao.module.system.dal.mysql.tenant; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; | ||
| 4 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; | ||
| 5 | -import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 8 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; | ||
| 9 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 10 | -import org.apache.ibatis.annotations.Select; | ||
| 11 | 10 | ||
| 12 | -import java.time.LocalDateTime; | ||
| 13 | import java.util.List; | 11 | import java.util.List; |
| 14 | 12 | ||
| 15 | /** | 13 | /** |
| @@ -52,7 +50,4 @@ public interface TenantMapper extends BaseMapperX<TenantDO> { | @@ -52,7 +50,4 @@ public interface TenantMapper extends BaseMapperX<TenantDO> { | ||
| 52 | return selectList(TenantDO::getPackageId, packageId); | 50 | return selectList(TenantDO::getPackageId, packageId); |
| 53 | } | 51 | } |
| 54 | 52 | ||
| 55 | - @Select("SELECT COUNT(*) FROM system_tenant WHERE update_time > #{maxUpdateTime}") | ||
| 56 | - Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime); | ||
| 57 | - | ||
| 58 | } | 53 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailAccountRefreshConsumer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.consumer.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; | ||
| 4 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailAccountRefreshMessage; | ||
| 5 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage; | ||
| 6 | +import cn.iocoder.yudao.module.system.service.mail.MailAccountService; | ||
| 7 | +import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; | ||
| 8 | +import lombok.extern.slf4j.Slf4j; | ||
| 9 | +import org.springframework.stereotype.Component; | ||
| 10 | + | ||
| 11 | +import javax.annotation.Resource; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 针对 {@link MailAccountRefreshMessage} 的消费者 | ||
| 15 | + * | ||
| 16 | + * @author wangjingyi | ||
| 17 | + */ | ||
| 18 | +@Component | ||
| 19 | +@Slf4j | ||
| 20 | +public class MailAccountRefreshConsumer extends AbstractChannelMessageListener<MailAccountRefreshMessage> { | ||
| 21 | + | ||
| 22 | + @Resource | ||
| 23 | + private MailAccountService mailAccountService; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public void onMessage(MailAccountRefreshMessage message) { | ||
| 27 | + log.info("[onMessage][收到 Mail Account 刷新信息]"); | ||
| 28 | + mailAccountService.initLocalCache(); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailSendConsumer.java
| @@ -2,17 +2,29 @@ package cn.iocoder.yudao.module.system.mq.consumer.mail; | @@ -2,17 +2,29 @@ package cn.iocoder.yudao.module.system.mq.consumer.mail; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; | 3 | import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; |
| 4 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | 4 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; |
| 5 | +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; | ||
| 6 | +import cn.iocoder.yudao.module.system.service.mail.MailSendService; | ||
| 5 | import lombok.extern.slf4j.Slf4j; | 7 | import lombok.extern.slf4j.Slf4j; |
| 6 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 7 | 9 | ||
| 8 | -// TODO 芋艿:这个暂未实现 | 10 | +import javax.annotation.Resource; |
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 针对 {@link MailSendMessage} 的消费者 | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 9 | @Component | 17 | @Component |
| 10 | @Slf4j | 18 | @Slf4j |
| 11 | public class MailSendConsumer extends AbstractStreamMessageListener<MailSendMessage> { | 19 | public class MailSendConsumer extends AbstractStreamMessageListener<MailSendMessage> { |
| 12 | 20 | ||
| 21 | + @Resource | ||
| 22 | + private MailSendService mailSendService; | ||
| 23 | + | ||
| 13 | @Override | 24 | @Override |
| 14 | public void onMessage(MailSendMessage message) { | 25 | public void onMessage(MailSendMessage message) { |
| 15 | log.info("[onMessage][消息内容({})]", message); | 26 | log.info("[onMessage][消息内容({})]", message); |
| 27 | + mailSendService.doSendMail(message); | ||
| 16 | } | 28 | } |
| 17 | 29 | ||
| 18 | } | 30 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailTemplateRefreshConsumer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.consumer.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; | ||
| 4 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage; | ||
| 5 | +import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; | ||
| 6 | +import lombok.extern.slf4j.Slf4j; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 针对 {@link MailTemplateRefreshMessage} 的消费者 | ||
| 13 | + * | ||
| 14 | + * @author wangjingyi | ||
| 15 | + */ | ||
| 16 | +@Component | ||
| 17 | +@Slf4j | ||
| 18 | +public class MailTemplateRefreshConsumer extends AbstractChannelMessageListener<MailTemplateRefreshMessage> { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private MailTemplateService mailTemplateService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void onMessage(MailTemplateRefreshMessage message) { | ||
| 25 | + log.info("[onMessage][收到 Mail Template 刷新信息]"); | ||
| 26 | + mailTemplateService.initLocalCache(); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailAccountRefreshMessage.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.message.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 邮箱账号的数据刷新 Message | ||
| 9 | + * | ||
| 10 | + * @author wangjingyi | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +public class MailAccountRefreshMessage extends AbstractChannelMessage { | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + public String getChannel() { | ||
| 18 | + return "system.mail-account.refresh"; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java
| @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; | @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; | ||
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | 6 | ||
| 7 | +import javax.validation.constraints.NotEmpty; | ||
| 7 | import javax.validation.constraints.NotNull; | 8 | import javax.validation.constraints.NotNull; |
| 8 | -import java.util.Map; | ||
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| 11 | * 邮箱发送消息 | 11 | * 邮箱发送消息 |
| @@ -17,28 +17,35 @@ import java.util.Map; | @@ -17,28 +17,35 @@ import java.util.Map; | ||
| 17 | public class MailSendMessage extends AbstractStreamMessage { | 17 | public class MailSendMessage extends AbstractStreamMessage { |
| 18 | 18 | ||
| 19 | /** | 19 | /** |
| 20 | - * 邮箱地址 | 20 | + * 邮件日志编号 |
| 21 | */ | 21 | */ |
| 22 | - @NotNull(message = "邮箱地址不能为空") | ||
| 23 | - private String address; | 22 | + @NotNull(message = "邮件日志编号不能为空") |
| 23 | + private Long logId; | ||
| 24 | /** | 24 | /** |
| 25 | - * 短信模板编号 | 25 | + * 接收邮件地址 |
| 26 | */ | 26 | */ |
| 27 | - @NotNull(message = "短信模板编号不能为空") | ||
| 28 | - private String templateCode; | 27 | + @NotNull(message = "接收邮件地址不能为空") |
| 28 | + private String mail; | ||
| 29 | /** | 29 | /** |
| 30 | - * 短信模板参数 | 30 | + * 邮件账号编号 |
| 31 | */ | 31 | */ |
| 32 | - private Map<String, Object> templateParams; | 32 | + @NotNull(message = "邮件账号编号不能为空") |
| 33 | + private Long accountId; | ||
| 33 | 34 | ||
| 34 | /** | 35 | /** |
| 35 | - * 用户编号,允许空 | 36 | + * 邮件发件人 |
| 36 | */ | 37 | */ |
| 37 | - private Integer userId; | 38 | + private String nickname; |
| 38 | /** | 39 | /** |
| 39 | - * 用户类型,允许空 | 40 | + * 邮件标题 |
| 40 | */ | 41 | */ |
| 41 | - private Integer userType; | 42 | + @NotEmpty(message = "邮件标题不能为空") |
| 43 | + private String title; | ||
| 44 | + /** | ||
| 45 | + * 邮件内容 | ||
| 46 | + */ | ||
| 47 | + @NotEmpty(message = "邮件内容不能为空") | ||
| 48 | + private String content; | ||
| 42 | 49 | ||
| 43 | @Override | 50 | @Override |
| 44 | public String getStreamKey() { | 51 | public String getStreamKey() { |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailTemplateRefreshMessage.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.message.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 邮箱模板的数据刷新 Message | ||
| 9 | + * | ||
| 10 | + * @author wangjingyi | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +public class MailTemplateRefreshMessage extends AbstractChannelMessage { | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + public String getChannel() { | ||
| 18 | + return "system.mail-template.refresh"; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.producer.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; | ||
| 4 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailAccountRefreshMessage; | ||
| 5 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | ||
| 6 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage; | ||
| 7 | +import lombok.extern.slf4j.Slf4j; | ||
| 8 | +import org.springframework.stereotype.Component; | ||
| 9 | + | ||
| 10 | +import javax.annotation.Resource; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * Mail 邮件相关消息的 Producer | ||
| 14 | + * | ||
| 15 | + * @author wangjingyi | ||
| 16 | + * @since 2021/4/19 13:33 | ||
| 17 | + */ | ||
| 18 | +@Slf4j | ||
| 19 | +@Component | ||
| 20 | +public class MailProducer { | ||
| 21 | + | ||
| 22 | + @Resource | ||
| 23 | + private RedisMQTemplate redisMQTemplate; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 发送 {@link MailTemplateRefreshMessage} 消息 | ||
| 27 | + */ | ||
| 28 | + public void sendMailTemplateRefreshMessage() { | ||
| 29 | + MailTemplateRefreshMessage message = new MailTemplateRefreshMessage(); | ||
| 30 | + redisMQTemplate.send(message); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 发送 {@link MailAccountRefreshMessage} 消息 | ||
| 35 | + */ | ||
| 36 | + public void sendMailAccountRefreshMessage() { | ||
| 37 | + MailAccountRefreshMessage message = new MailAccountRefreshMessage(); | ||
| 38 | + redisMQTemplate.send(message); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 发送 {@link MailSendMessage} 消息 | ||
| 43 | + * | ||
| 44 | + * @param sendLogId 发送日志编码 | ||
| 45 | + * @param mail 接收邮件地址 | ||
| 46 | + * @param accountId 邮件账号编号 | ||
| 47 | + * @param nickname 邮件发件人 | ||
| 48 | + * @param title 邮件标题 | ||
| 49 | + * @param content 邮件内容 | ||
| 50 | + */ | ||
| 51 | + public void sendMailSendMessage(Long sendLogId, String mail, Long accountId, | ||
| 52 | + String nickname, String title, String content) { | ||
| 53 | + MailSendMessage message = new MailSendMessage() | ||
| 54 | + .setLogId(sendLogId).setMail(mail).setAccountId(accountId) | ||
| 55 | + .setNickname(nickname).setTitle(title).setContent(content); | ||
| 56 | + redisMQTemplate.send(message); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java
| @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer; | @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer; | ||
| 17 | import com.google.common.collect.ImmutableMap; | 17 | import com.google.common.collect.ImmutableMap; |
| 18 | import com.google.common.collect.ImmutableMultimap; | 18 | import com.google.common.collect.ImmutableMultimap; |
| 19 | import com.google.common.collect.Multimap; | 19 | import com.google.common.collect.Multimap; |
| 20 | +import lombok.Getter; | ||
| 20 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
| 21 | import org.springframework.scheduling.annotation.Scheduled; | 22 | import org.springframework.scheduling.annotation.Scheduled; |
| 22 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
| @@ -41,18 +42,12 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -41,18 +42,12 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 41 | public class DeptServiceImpl implements DeptService { | 42 | public class DeptServiceImpl implements DeptService { |
| 42 | 43 | ||
| 43 | /** | 44 | /** |
| 44 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 45 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 46 | - */ | ||
| 47 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 48 | - | ||
| 49 | - /** | ||
| 50 | * 部门缓存 | 45 | * 部门缓存 |
| 51 | * key:部门编号 {@link DeptDO#getId()} | 46 | * key:部门编号 {@link DeptDO#getId()} |
| 52 | * | 47 | * |
| 53 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | 48 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 |
| 54 | */ | 49 | */ |
| 55 | - @SuppressWarnings("FieldCanBeLocal") | 50 | + @Getter |
| 56 | private volatile Map<Long, DeptDO> deptCache; | 51 | private volatile Map<Long, DeptDO> deptCache; |
| 57 | /** | 52 | /** |
| 58 | * 父部门缓存 | 53 | * 父部门缓存 |
| @@ -61,11 +56,8 @@ public class DeptServiceImpl implements DeptService { | @@ -61,11 +56,8 @@ public class DeptServiceImpl implements DeptService { | ||
| 61 | * | 56 | * |
| 62 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | 57 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 |
| 63 | */ | 58 | */ |
| 59 | + @Getter | ||
| 64 | private volatile Multimap<Long, DeptDO> parentDeptCache; | 60 | private volatile Multimap<Long, DeptDO> parentDeptCache; |
| 65 | - /** | ||
| 66 | - * 缓存部门的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 67 | - */ | ||
| 68 | - private volatile LocalDateTime maxUpdateTime; | ||
| 69 | 61 | ||
| 70 | @Resource | 62 | @Resource |
| 71 | private DeptMapper deptMapper; | 63 | private DeptMapper deptMapper; |
| @@ -79,48 +71,21 @@ public class DeptServiceImpl implements DeptService { | @@ -79,48 +71,21 @@ public class DeptServiceImpl implements DeptService { | ||
| 79 | @Override | 71 | @Override |
| 80 | @PostConstruct | 72 | @PostConstruct |
| 81 | public synchronized void initLocalCache() { | 73 | public synchronized void initLocalCache() { |
| 82 | - initLocalCacheIfUpdate(null); | ||
| 83 | - } | ||
| 84 | - | ||
| 85 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 86 | - public void schedulePeriodicRefresh() { | ||
| 87 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - /** | ||
| 91 | - * 刷新本地缓存 | ||
| 92 | - * | ||
| 93 | - * @param maxUpdateTime 最大更新时间 | ||
| 94 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 95 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 96 | - */ | ||
| 97 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 98 | // 注意:忽略自动多租户,因为要全局初始化缓存 | 74 | // 注意:忽略自动多租户,因为要全局初始化缓存 |
| 99 | TenantUtils.executeIgnore(() -> { | 75 | TenantUtils.executeIgnore(() -> { |
| 100 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 101 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 102 | - if (maxUpdateTime != null | ||
| 103 | - && deptMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 104 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 105 | - return; | ||
| 106 | - } | 76 | + // 第一步:查询数据 |
| 107 | List<DeptDO> depts = deptMapper.selectList(); | 77 | List<DeptDO> depts = deptMapper.selectList(); |
| 108 | - log.info("[initLocalCacheIfUpdate][缓存部门,数量为:{}]", depts.size()); | 78 | + log.info("[initLocalCache][缓存部门,数量为:{}]", depts.size()); |
| 109 | 79 | ||
| 110 | - // 第二步:构建缓存。创建或更新支付 Client | ||
| 111 | - // 构建缓存 | 80 | + // 第二步:构建缓存 |
| 112 | ImmutableMap.Builder<Long, DeptDO> builder = ImmutableMap.builder(); | 81 | ImmutableMap.Builder<Long, DeptDO> builder = ImmutableMap.builder(); |
| 113 | ImmutableMultimap.Builder<Long, DeptDO> parentBuilder = ImmutableMultimap.builder(); | 82 | ImmutableMultimap.Builder<Long, DeptDO> parentBuilder = ImmutableMultimap.builder(); |
| 114 | depts.forEach(sysRoleDO -> { | 83 | depts.forEach(sysRoleDO -> { |
| 115 | builder.put(sysRoleDO.getId(), sysRoleDO); | 84 | builder.put(sysRoleDO.getId(), sysRoleDO); |
| 116 | parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO); | 85 | parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO); |
| 117 | }); | 86 | }); |
| 118 | - // 设置缓存 | ||
| 119 | deptCache = builder.build(); | 87 | deptCache = builder.build(); |
| 120 | parentDeptCache = parentBuilder.build(); | 88 | parentDeptCache = parentBuilder.build(); |
| 121 | - | ||
| 122 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 123 | - this.maxUpdateTime = CollectionUtils.getMaxValue(depts, DeptDO::getUpdateTime); | ||
| 124 | }); | 89 | }); |
| 125 | } | 90 | } |
| 126 | 91 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 8 | + | ||
| 9 | +import javax.validation.Valid; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 邮箱账号 Service 接口 | ||
| 14 | + * | ||
| 15 | + * @author wangjingyi | ||
| 16 | + * @since 2022-03-21 | ||
| 17 | + */ | ||
| 18 | +public interface MailAccountService { | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 初始化邮箱账号的本地缓存 | ||
| 22 | + */ | ||
| 23 | + void initLocalCache(); | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 从缓存中获取邮箱账号 | ||
| 27 | + * | ||
| 28 | + * @param id 编号 | ||
| 29 | + * @return 邮箱账号 | ||
| 30 | + */ | ||
| 31 | + MailAccountDO getMailAccountFromCache(Long id); | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 创建邮箱账号 | ||
| 35 | + * | ||
| 36 | + * @param createReqVO 邮箱账号信息 | ||
| 37 | + * @return 编号 | ||
| 38 | + */ | ||
| 39 | + Long createMailAccount(@Valid MailAccountCreateReqVO createReqVO); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 修改邮箱账号 | ||
| 43 | + * | ||
| 44 | + * @param updateReqVO 邮箱账号信息 | ||
| 45 | + */ | ||
| 46 | + void updateMailAccount(@Valid MailAccountUpdateReqVO updateReqVO); | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 删除邮箱账号 | ||
| 50 | + * | ||
| 51 | + * @param id 编号 | ||
| 52 | + */ | ||
| 53 | + void deleteMailAccount(Long id); | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * 获取邮箱账号信息 | ||
| 57 | + * | ||
| 58 | + * @param id 编号 | ||
| 59 | + * @return 邮箱账号信息 | ||
| 60 | + */ | ||
| 61 | + MailAccountDO getMailAccount(Long id); | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 获取邮箱账号分页信息 | ||
| 65 | + * | ||
| 66 | + * @param pageReqVO 邮箱账号分页参数 | ||
| 67 | + * @return 邮箱账号分页信息 | ||
| 68 | + */ | ||
| 69 | + PageResult<MailAccountDO> getMailAccountPage(MailAccountPageReqVO pageReqVO); | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 获取邮箱数组信息 | ||
| 73 | + * | ||
| 74 | + * @return 邮箱账号信息数组 | ||
| 75 | + */ | ||
| 76 | + List<MailAccountDO> getMailAccountList(); | ||
| 77 | + | ||
| 78 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; | ||
| 10 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 11 | +import lombok.Getter; | ||
| 12 | +import lombok.extern.slf4j.Slf4j; | ||
| 13 | +import org.springframework.stereotype.Service; | ||
| 14 | +import org.springframework.validation.annotation.Validated; | ||
| 15 | + | ||
| 16 | +import javax.annotation.PostConstruct; | ||
| 17 | +import javax.annotation.Resource; | ||
| 18 | +import java.util.List; | ||
| 19 | +import java.util.Map; | ||
| 20 | + | ||
| 21 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 22 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 23 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * 邮箱账号 Service 实现类 | ||
| 27 | + * | ||
| 28 | + * @author wangjingyi | ||
| 29 | + * @since 2022-03-21 | ||
| 30 | + */ | ||
| 31 | +@Service | ||
| 32 | +@Validated | ||
| 33 | +@Slf4j | ||
| 34 | +public class MailAccountServiceImpl implements MailAccountService { | ||
| 35 | + | ||
| 36 | + @Resource | ||
| 37 | + private MailAccountMapper mailAccountMapper; | ||
| 38 | + | ||
| 39 | + @Resource | ||
| 40 | + private MailTemplateService mailTemplateService; | ||
| 41 | + | ||
| 42 | + @Resource | ||
| 43 | + private MailProducer mailProducer; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 邮箱账号缓存 | ||
| 47 | + * key:邮箱账号编码 {@link MailAccountDO#getId()} | ||
| 48 | + * | ||
| 49 | + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | ||
| 50 | + */ | ||
| 51 | + @Getter | ||
| 52 | + private volatile Map<Long, MailAccountDO> mailAccountCache; | ||
| 53 | + | ||
| 54 | + @Override | ||
| 55 | + @PostConstruct | ||
| 56 | + public void initLocalCache() { | ||
| 57 | + // 第一步:查询数据 | ||
| 58 | + List<MailAccountDO> accounts = mailAccountMapper.selectList(); | ||
| 59 | + log.info("[initLocalCache][缓存邮箱账号,数量:{}]", accounts.size()); | ||
| 60 | + | ||
| 61 | + // 第二步:构建缓存 | ||
| 62 | + mailAccountCache = convertMap(accounts, MailAccountDO::getId); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + public MailAccountDO getMailAccountFromCache(Long id) { | ||
| 67 | + return mailAccountCache.get(id); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @Override | ||
| 71 | + public Long createMailAccount(MailAccountCreateReqVO createReqVO) { | ||
| 72 | + // 插入 | ||
| 73 | + MailAccountDO account = MailAccountConvert.INSTANCE.convert(createReqVO); | ||
| 74 | + mailAccountMapper.insert(account); | ||
| 75 | + | ||
| 76 | + // 发送刷新消息 | ||
| 77 | + mailProducer.sendMailAccountRefreshMessage(); | ||
| 78 | + return account.getId(); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) { | ||
| 83 | + // 校验是否存在 | ||
| 84 | + validateMailAccountExists(updateReqVO.getId()); | ||
| 85 | + | ||
| 86 | + // 更新 | ||
| 87 | + MailAccountDO updateObj = MailAccountConvert.INSTANCE.convert(updateReqVO); | ||
| 88 | + mailAccountMapper.updateById(updateObj); | ||
| 89 | + // 发送刷新消息 | ||
| 90 | + mailProducer.sendMailAccountRefreshMessage(); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + @Override | ||
| 94 | + public void deleteMailAccount(Long id) { | ||
| 95 | + // 校验是否存在账号 | ||
| 96 | + validateMailAccountExists(id); | ||
| 97 | + // 校验是否存在关联模版 | ||
| 98 | + if (mailTemplateService.countByAccountId(id) > 0) { | ||
| 99 | + throw exception(MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + // 删除 | ||
| 103 | + mailAccountMapper.deleteById(id); | ||
| 104 | + // 发送刷新消息 | ||
| 105 | + mailProducer.sendMailAccountRefreshMessage(); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + private void validateMailAccountExists(Long id) { | ||
| 109 | + if (mailAccountMapper.selectById(id) == null) { | ||
| 110 | + throw exception(MAIL_ACCOUNT_NOT_EXISTS); | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + @Override | ||
| 115 | + public MailAccountDO getMailAccount(Long id) { | ||
| 116 | + return mailAccountMapper.selectById(id); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + @Override | ||
| 120 | + public PageResult<MailAccountDO> getMailAccountPage(MailAccountPageReqVO pageReqVO) { | ||
| 121 | + return mailAccountMapper.selectPage(pageReqVO); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + @Override | ||
| 125 | + public List<MailAccountDO> getMailAccountList() { | ||
| 126 | + return mailAccountMapper.selectList(); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 6 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 8 | + | ||
| 9 | +import java.util.Map; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 邮件日志 Service 接口 | ||
| 13 | + * | ||
| 14 | + * @author wangjingyi | ||
| 15 | + * @since 2022-03-21 | ||
| 16 | + */ | ||
| 17 | +public interface MailLogService { | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 邮件日志分页 | ||
| 21 | + * | ||
| 22 | + * @param pageVO 分页参数 | ||
| 23 | + * @return 分页结果 | ||
| 24 | + */ | ||
| 25 | + PageResult<MailLogDO> getMailLogPage(MailLogPageReqVO pageVO); | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 获得指定编号的邮件日志 | ||
| 29 | + * | ||
| 30 | + * @param id 日志编号 | ||
| 31 | + * @return 邮件日志 | ||
| 32 | + */ | ||
| 33 | + MailLogDO getMailLog(Long id); | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 创建邮件日志 | ||
| 37 | + * | ||
| 38 | + * @param userId 用户编码 | ||
| 39 | + * @param userType 用户类型 | ||
| 40 | + * @param toMail 收件人邮件 | ||
| 41 | + * @param account 邮件账号信息 | ||
| 42 | + * @param template 模版信息 | ||
| 43 | + * @param templateContent 模版内容 | ||
| 44 | + * @param templateParams 模版参数 | ||
| 45 | + * @param isSend 是否发送成功 | ||
| 46 | + * @return 日志编号 | ||
| 47 | + */ | ||
| 48 | + Long createMailLog(Long userId,Integer userType, String toMail, | ||
| 49 | + MailAccountDO account, MailTemplateDO template , | ||
| 50 | + String templateContent, Map<String, Object> templateParams, Boolean isSend); | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * 更新邮件发送结果 | ||
| 54 | + * | ||
| 55 | + * @param logId 日志编号 | ||
| 56 | + * @param messageId 发送后的消息编号 | ||
| 57 | + * @param exception 发送异常 | ||
| 58 | + */ | ||
| 59 | + void updateMailSendResult(Long logId, String messageId, Exception exception); | ||
| 60 | + | ||
| 61 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 6 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper; | ||
| 9 | +import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | +import org.springframework.validation.annotation.Validated; | ||
| 12 | + | ||
| 13 | +import javax.annotation.Resource; | ||
| 14 | +import java.util.Date; | ||
| 15 | +import java.util.Map; | ||
| 16 | +import java.util.Objects; | ||
| 17 | + | ||
| 18 | +import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * 邮件日志 Service 实现类 | ||
| 22 | + * | ||
| 23 | + * @author wangjingyi | ||
| 24 | + * @since 2022-03-21 | ||
| 25 | + */ | ||
| 26 | +@Service | ||
| 27 | +@Validated | ||
| 28 | +public class MailLogServiceImpl implements MailLogService { | ||
| 29 | + | ||
| 30 | + @Resource | ||
| 31 | + private MailLogMapper mailLogMapper; | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public PageResult<MailLogDO> getMailLogPage(MailLogPageReqVO pageVO) { | ||
| 35 | + return mailLogMapper.selectPage(pageVO); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public MailLogDO getMailLog(Long id) { | ||
| 40 | + return mailLogMapper.selectById(id); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public Long createMailLog(Long userId, Integer userType, String toMail, | ||
| 45 | + MailAccountDO account, MailTemplateDO template, | ||
| 46 | + String templateContent, Map<String, Object> templateParams, Boolean isSend) { | ||
| 47 | + MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder(); | ||
| 48 | + // 根据是否要发送,设置状态 | ||
| 49 | + logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus() | ||
| 50 | + : MailSendStatusEnum.IGNORE.getStatus()) | ||
| 51 | + // 用户信息 | ||
| 52 | + .userId(userId).userType(userType).toMail(toMail) | ||
| 53 | + .accountId(account.getId()).fromMail(account.getMail()) | ||
| 54 | + // 模板相关字段 | ||
| 55 | + .templateId(template.getId()).templateCode(template.getCode()).templateNickname(template.getNickname()) | ||
| 56 | + .templateTitle(template.getTitle()).templateContent(templateContent).templateParams(templateParams); | ||
| 57 | + | ||
| 58 | + // 插入数据库 | ||
| 59 | + MailLogDO logDO = logDOBuilder.build(); | ||
| 60 | + mailLogMapper.insert(logDO); | ||
| 61 | + return logDO.getId(); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + @Override | ||
| 65 | + public void updateMailSendResult(Long logId, String messageId, Exception exception) { | ||
| 66 | + // 1. 成功 | ||
| 67 | + if (exception == null) { | ||
| 68 | + mailLogMapper.updateById(new MailLogDO().setId(logId).setSendTime(new Date()) | ||
| 69 | + .setSendStatus(MailSendStatusEnum.SUCCESS.getStatus()).setSendMessageId(messageId)); | ||
| 70 | + return; | ||
| 71 | + } | ||
| 72 | + // 2. 失败 | ||
| 73 | + mailLogMapper.updateById(new MailLogDO().setId(logId).setSendTime(new Date()) | ||
| 74 | + .setSendStatus(MailSendStatusEnum.FAILURE.getStatus()).setSendException(getRootCauseMessage(exception))); | ||
| 75 | + | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | ||
| 4 | + | ||
| 5 | +import java.util.Map; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 邮件发送 Service 接口 | ||
| 9 | + * | ||
| 10 | + * @author wangjingyi | ||
| 11 | + * @since 2022-03-21 | ||
| 12 | + */ | ||
| 13 | +public interface MailSendService { | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 发送单条邮件给管理后台的用户 | ||
| 17 | + * | ||
| 18 | + * @param mail 邮箱 | ||
| 19 | + * @param userId 用户编码 | ||
| 20 | + * @param templateCode 邮件模版编码 | ||
| 21 | + * @param templateParams 邮件模版参数 | ||
| 22 | + * @return 发送日志编号 | ||
| 23 | + */ | ||
| 24 | + Long sendSingleMailToAdmin(String mail, Long userId, | ||
| 25 | + String templateCode, Map<String, Object> templateParams); | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 发送单条邮件给用户 APP 的用户 | ||
| 29 | + * | ||
| 30 | + * @param mail 邮箱 | ||
| 31 | + * @param userId 用户编码 | ||
| 32 | + * @param templateCode 邮件模版编码 | ||
| 33 | + * @param templateParams 邮件模版参数 | ||
| 34 | + * @return 发送日志编号 | ||
| 35 | + */ | ||
| 36 | + Long sendSingleMailToMember(String mail, Long userId, | ||
| 37 | + String templateCode, Map<String, Object> templateParams); | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 发送单条邮件给用户 | ||
| 41 | + * | ||
| 42 | + * @param mail 邮箱 | ||
| 43 | + * @param userId 用户编码 | ||
| 44 | + * @param userType 用户类型 | ||
| 45 | + * @param templateCode 邮件模版编码 | ||
| 46 | + * @param templateParams 邮件模版参数 | ||
| 47 | + * @return 发送日志编号 | ||
| 48 | + */ | ||
| 49 | + Long sendSingleMail(String mail, Long userId, Integer userType, | ||
| 50 | + String templateCode, Map<String, Object> templateParams); | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * 执行真正的邮件发送 | ||
| 54 | + * 注意,该方法仅仅提供给 MQ Consumer 使用 | ||
| 55 | + * | ||
| 56 | + * @param message 邮件 | ||
| 57 | + */ | ||
| 58 | + void doSendMail(MailSendMessage message); | ||
| 59 | + | ||
| 60 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.hutool.extra.mail.MailAccount; | ||
| 5 | +import cn.hutool.extra.mail.MailUtil; | ||
| 6 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 7 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 8 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | ||
| 10 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 11 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 12 | +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | ||
| 13 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | ||
| 14 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 15 | +import cn.iocoder.yudao.module.system.service.member.MemberService; | ||
| 16 | +import cn.iocoder.yudao.module.system.service.user.AdminUserService; | ||
| 17 | +import com.google.common.annotations.VisibleForTesting; | ||
| 18 | +import lombok.extern.slf4j.Slf4j; | ||
| 19 | +import org.springframework.stereotype.Service; | ||
| 20 | +import org.springframework.validation.annotation.Validated; | ||
| 21 | + | ||
| 22 | +import javax.annotation.Resource; | ||
| 23 | +import java.util.List; | ||
| 24 | +import java.util.Map; | ||
| 25 | +import java.util.stream.Collectors; | ||
| 26 | + | ||
| 27 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 28 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * 邮箱模版 服务实现类 | ||
| 32 | + * | ||
| 33 | + * @author wangjingyi | ||
| 34 | + * @since 2022-03-21 | ||
| 35 | + */ | ||
| 36 | +@Service | ||
| 37 | +@Validated | ||
| 38 | +@Slf4j | ||
| 39 | +public class MailSendServiceImpl implements MailSendService { | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private AdminUserService adminUserService; | ||
| 43 | + @Resource | ||
| 44 | + private MemberService memberService; | ||
| 45 | + | ||
| 46 | + @Resource | ||
| 47 | + private MailAccountService mailAccountService; | ||
| 48 | + @Resource | ||
| 49 | + private MailTemplateService mailTemplateService; | ||
| 50 | + | ||
| 51 | + @Resource | ||
| 52 | + private MailLogService mailLogService; | ||
| 53 | + @Resource | ||
| 54 | + private MailProducer mailProducer; | ||
| 55 | + | ||
| 56 | + @Override | ||
| 57 | + public Long sendSingleMailToAdmin(String mail, Long userId, | ||
| 58 | + String templateCode, Map<String, Object> templateParams) { | ||
| 59 | + // 如果 mail 为空,则加载用户编号对应的邮箱 | ||
| 60 | + if (StrUtil.isEmpty(mail)) { | ||
| 61 | + AdminUserDO user = adminUserService.getUser(userId); | ||
| 62 | + if (user != null) { | ||
| 63 | + mail = user.getEmail(); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + // 执行发送 | ||
| 67 | + return sendSingleMail(mail, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @Override | ||
| 71 | + public Long sendSingleMailToMember(String mail, Long userId, | ||
| 72 | + String templateCode, Map<String, Object> templateParams) { | ||
| 73 | + // 如果 mail 为空,则加载用户编号对应的邮箱 | ||
| 74 | + if (StrUtil.isEmpty(mail)) { | ||
| 75 | + mail = memberService.getMemberUserEmail(userId); | ||
| 76 | + } | ||
| 77 | + // 执行发送 | ||
| 78 | + return sendSingleMail(mail, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public Long sendSingleMail(String mail, Long userId, Integer userType, | ||
| 83 | + String templateCode, Map<String, Object> templateParams) { | ||
| 84 | + // 校验邮箱模版是否合法 | ||
| 85 | + MailTemplateDO template = checkMailTemplateValid(templateCode); | ||
| 86 | + // 校验邮箱账号是否合法 | ||
| 87 | + MailAccountDO account = checkMailAccountValid(template.getAccountId()); | ||
| 88 | + | ||
| 89 | + // 校验邮箱是否存在 | ||
| 90 | + mail = checkMail(mail); | ||
| 91 | + // 构建有序的模板参数。为什么放在这个位置,是提前保证模板参数的正确性,而不是到了插入发送日志 | ||
| 92 | + List<KeyValue<String, Object>> newTemplateParams = buildTemplateParams(template, templateParams); | ||
| 93 | + | ||
| 94 | + // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 | ||
| 95 | + Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); | ||
| 96 | + String content = mailTemplateService.formatMailTemplateContent(template.getContent(), templateParams); | ||
| 97 | + Long sendLogId = mailLogService.createMailLog(userId, userType, mail, | ||
| 98 | + account, template, content, templateParams, isSend); | ||
| 99 | + // 发送 MQ 消息,异步执行发送短信 | ||
| 100 | + if (isSend) { | ||
| 101 | + mailProducer.sendMailSendMessage(sendLogId, mail, account.getId(), | ||
| 102 | + template.getNickname(), template.getTitle(), content); | ||
| 103 | + } | ||
| 104 | + return sendLogId; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + @Override | ||
| 108 | + public void doSendMail(MailSendMessage message) { | ||
| 109 | + // 1. 创建发送账号 | ||
| 110 | + MailAccountDO account = checkMailAccountValid(message.getAccountId()); | ||
| 111 | + MailAccount mailAccount = MailAccountConvert.INSTANCE.convert(account, message.getNickname()); | ||
| 112 | + // 2. 发送邮件 | ||
| 113 | + try { | ||
| 114 | + String messageId = MailUtil.send(mailAccount, message.getMail(), | ||
| 115 | + message.getTitle(), message.getContent(),true); | ||
| 116 | + // 3. 更新结果(成功) | ||
| 117 | + mailLogService.updateMailSendResult(message.getLogId(), messageId, null); | ||
| 118 | + } catch (Exception e) { | ||
| 119 | + // 3. 更新结果(异常) | ||
| 120 | + mailLogService.updateMailSendResult(message.getLogId(), null, e); | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + @VisibleForTesting | ||
| 125 | + public MailTemplateDO checkMailTemplateValid(String templateCode) { | ||
| 126 | + // 获得邮件模板。考虑到效率,从缓存中获取 | ||
| 127 | + MailTemplateDO template = mailTemplateService.getMailTemplateByCodeFromCache(templateCode); | ||
| 128 | + // 邮件模板不存在 | ||
| 129 | + if (template == null) { | ||
| 130 | + throw exception(MAIL_TEMPLATE_NOT_EXISTS); | ||
| 131 | + } | ||
| 132 | + return template; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + @VisibleForTesting | ||
| 136 | + public MailAccountDO checkMailAccountValid(Long accountId) { | ||
| 137 | + // 获得邮箱账号。考虑到效率,从缓存中获取 | ||
| 138 | + MailAccountDO account = mailAccountService.getMailAccountFromCache(accountId); | ||
| 139 | + // 邮箱账号不存在 | ||
| 140 | + if (account == null) { | ||
| 141 | + throw exception(MAIL_ACCOUNT_NOT_EXISTS); | ||
| 142 | + } | ||
| 143 | + return account; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + @VisibleForTesting | ||
| 147 | + public String checkMail(String mail) { | ||
| 148 | + if (StrUtil.isEmpty(mail)) { | ||
| 149 | + throw exception(MAIL_SEND_MAIL_NOT_EXISTS); | ||
| 150 | + } | ||
| 151 | + return mail; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + /** | ||
| 155 | + * 将参数模板,处理成有序的 KeyValue 数组 | ||
| 156 | + * | ||
| 157 | + * @param template 邮箱模板 | ||
| 158 | + * @param templateParams 原始参数 | ||
| 159 | + * @return 处理后的参数 | ||
| 160 | + */ | ||
| 161 | + @VisibleForTesting | ||
| 162 | + public List<KeyValue<String, Object>> buildTemplateParams(MailTemplateDO template, Map<String, Object> templateParams) { | ||
| 163 | + return template.getParams().stream().map(key -> { | ||
| 164 | + Object value = templateParams.get(key); | ||
| 165 | + if (value == null) { | ||
| 166 | + throw exception(MAIL_SEND_TEMPLATE_PARAM_MISS, key); | ||
| 167 | + } | ||
| 168 | + return new KeyValue<>(key, value); | ||
| 169 | + }).collect(Collectors.toList()); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 8 | + | ||
| 9 | +import javax.validation.Valid; | ||
| 10 | +import java.util.List; | ||
| 11 | +import java.util.Map; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 邮件模版 Service 接口 | ||
| 15 | + * | ||
| 16 | + * @author wangjingyi | ||
| 17 | + * @since 2022-03-21 | ||
| 18 | + */ | ||
| 19 | +public interface MailTemplateService { | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 初始化邮件模版的本地缓存 | ||
| 23 | + */ | ||
| 24 | + void initLocalCache(); | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 邮件模版创建 | ||
| 28 | + * | ||
| 29 | + * @param createReqVO 邮件信息 | ||
| 30 | + * @return 编号 | ||
| 31 | + */ | ||
| 32 | + Long createMailTemplate(@Valid MailTemplateCreateReqVO createReqVO); | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 邮件模版修改 | ||
| 36 | + * | ||
| 37 | + * @param updateReqVO 邮件信息 | ||
| 38 | + */ | ||
| 39 | + void updateMailTemplate(@Valid MailTemplateUpdateReqVO updateReqVO); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 邮件模版删除 | ||
| 43 | + * | ||
| 44 | + * @param id 编号 | ||
| 45 | + */ | ||
| 46 | + void deleteMailTemplate(Long id); | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 获取邮件模版 | ||
| 50 | + * | ||
| 51 | + * @param id 编号 | ||
| 52 | + * @return 邮件模版 | ||
| 53 | + */ | ||
| 54 | + MailTemplateDO getMailTemplate(Long id); | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 获取邮件模版分页 | ||
| 58 | + * | ||
| 59 | + * @param pageReqVO 模版信息 | ||
| 60 | + * @return 邮件模版分页信息 | ||
| 61 | + */ | ||
| 62 | + PageResult<MailTemplateDO> getMailTemplatePage(MailTemplatePageReqVO pageReqVO); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 获取邮件模板数组 | ||
| 66 | + * | ||
| 67 | + * @return 模版数组 | ||
| 68 | + */ | ||
| 69 | + List<MailTemplateDO> getMailTemplateList(); | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 从缓存中获取邮件模版 | ||
| 73 | + * | ||
| 74 | + * @param code 模板编码 | ||
| 75 | + * @return 邮件模板 | ||
| 76 | + */ | ||
| 77 | + MailTemplateDO getMailTemplateByCodeFromCache(String code); | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 邮件模版内容合成 | ||
| 81 | + * | ||
| 82 | + * @param content 邮件模版 | ||
| 83 | + * @param params 合成参数 | ||
| 84 | + * @return 格式化后的内容 | ||
| 85 | + */ | ||
| 86 | + String formatMailTemplateContent(String content, Map<String, Object> params); | ||
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * 获得指定邮件账号下的邮件模板数量 | ||
| 90 | + * | ||
| 91 | + * @param accountId 账号编号 | ||
| 92 | + * @return 数量 | ||
| 93 | + */ | ||
| 94 | + long countByAccountId(Long accountId); | ||
| 95 | + | ||
| 96 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ObjUtil; | ||
| 4 | +import cn.hutool.core.util.ReUtil; | ||
| 5 | +import cn.hutool.core.util.StrUtil; | ||
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; | ||
| 11 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 12 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; | ||
| 13 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 14 | +import com.google.common.annotations.VisibleForTesting; | ||
| 15 | +import lombok.Getter; | ||
| 16 | +import lombok.extern.slf4j.Slf4j; | ||
| 17 | +import org.springframework.stereotype.Service; | ||
| 18 | +import org.springframework.validation.annotation.Validated; | ||
| 19 | + | ||
| 20 | +import javax.annotation.PostConstruct; | ||
| 21 | +import javax.annotation.Resource; | ||
| 22 | +import javax.validation.Valid; | ||
| 23 | +import java.util.List; | ||
| 24 | +import java.util.Map; | ||
| 25 | +import java.util.regex.Pattern; | ||
| 26 | + | ||
| 27 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 28 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 29 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * 邮箱模版 Service 实现类 | ||
| 33 | + * | ||
| 34 | + * @author wangjingyi | ||
| 35 | + * @since 2022-03-21 | ||
| 36 | + */ | ||
| 37 | +@Service | ||
| 38 | +@Validated | ||
| 39 | +@Slf4j | ||
| 40 | +public class MailTemplateServiceImpl implements MailTemplateService { | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 正则表达式,匹配 {} 中的变量 | ||
| 44 | + */ | ||
| 45 | + private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); | ||
| 46 | + | ||
| 47 | + @Resource | ||
| 48 | + private MailTemplateMapper mailTemplateMapper; | ||
| 49 | + | ||
| 50 | + @Resource | ||
| 51 | + private MailProducer mailProducer; | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * 邮件模板缓存 | ||
| 55 | + * key:邮件模版标识 {@link MailTemplateDO#getCode()} | ||
| 56 | + * | ||
| 57 | + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | ||
| 58 | + */ | ||
| 59 | + @Getter | ||
| 60 | + private volatile Map<String, MailTemplateDO> mailTemplateCache; | ||
| 61 | + | ||
| 62 | + @Override | ||
| 63 | + @PostConstruct | ||
| 64 | + public void initLocalCache() { | ||
| 65 | + // 第一步:查询数据 | ||
| 66 | + List<MailTemplateDO> templates = mailTemplateMapper.selectList(); | ||
| 67 | + log.info("[initLocalCache][缓存邮件模版,数量:{}]", templates.size()); | ||
| 68 | + | ||
| 69 | + // 第二步:构建缓存 | ||
| 70 | + mailTemplateCache = convertMap(templates, MailTemplateDO::getCode); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + @Override | ||
| 74 | + public Long createMailTemplate(MailTemplateCreateReqVO createReqVO) { | ||
| 75 | + // 校验 code 是否唯一 | ||
| 76 | + validateCodeUnique(null, createReqVO.getCode()); | ||
| 77 | + | ||
| 78 | + // 插入 | ||
| 79 | + MailTemplateDO template = MailTemplateConvert.INSTANCE.convert(createReqVO) | ||
| 80 | + .setParams(parseTemplateContentParams(createReqVO.getContent())); | ||
| 81 | + mailTemplateMapper.insert(template); | ||
| 82 | + // 发送刷新消息 | ||
| 83 | + mailProducer.sendMailTemplateRefreshMessage(); | ||
| 84 | + return template.getId(); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + @Override | ||
| 88 | + public void updateMailTemplate(@Valid MailTemplateUpdateReqVO updateReqVO) { | ||
| 89 | + // 校验是否存在 | ||
| 90 | + validateMailTemplateExists(updateReqVO.getId()); | ||
| 91 | + // 校验 code 是否唯一 | ||
| 92 | + validateCodeUnique(updateReqVO.getId(),updateReqVO.getCode()); | ||
| 93 | + | ||
| 94 | + // 更新 | ||
| 95 | + MailTemplateDO updateObj = MailTemplateConvert.INSTANCE.convert(updateReqVO) | ||
| 96 | + .setParams(parseTemplateContentParams(updateReqVO.getContent())); | ||
| 97 | + mailTemplateMapper.updateById(updateObj); | ||
| 98 | + // 发送刷新消息 | ||
| 99 | + mailProducer.sendMailTemplateRefreshMessage(); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + @VisibleForTesting | ||
| 103 | + public void validateCodeUnique(Long id, String code) { | ||
| 104 | + MailTemplateDO template = mailTemplateMapper.selectByCode(code); | ||
| 105 | + if (template == null) { | ||
| 106 | + return; | ||
| 107 | + } | ||
| 108 | + // 存在 template 记录的情况下 | ||
| 109 | + if (id == null // 新增时,说明重复 | ||
| 110 | + || ObjUtil.notEqual(id, template.getId())) { // 更新时,如果 id 不一致,说明重复 | ||
| 111 | + throw exception(MAIL_TEMPLATE_CODE_EXISTS); | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Override | ||
| 116 | + public void deleteMailTemplate(Long id) { | ||
| 117 | + // 校验是否存在 | ||
| 118 | + validateMailTemplateExists(id); | ||
| 119 | + | ||
| 120 | + // 删除 | ||
| 121 | + mailTemplateMapper.deleteById(id); | ||
| 122 | + // 发送刷新消息 | ||
| 123 | + mailProducer.sendMailTemplateRefreshMessage(); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + private void validateMailTemplateExists(Long id) { | ||
| 127 | + if (mailTemplateMapper.selectById(id) == null) { | ||
| 128 | + throw exception(MAIL_TEMPLATE_NOT_EXISTS); | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + @Override | ||
| 133 | + public MailTemplateDO getMailTemplate(Long id) {return mailTemplateMapper.selectById(id);} | ||
| 134 | + | ||
| 135 | + @Override | ||
| 136 | + public PageResult<MailTemplateDO> getMailTemplatePage(MailTemplatePageReqVO pageReqVO) { | ||
| 137 | + return mailTemplateMapper.selectPage(pageReqVO); | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + @Override | ||
| 141 | + public List<MailTemplateDO> getMailTemplateList() {return mailTemplateMapper.selectList();} | ||
| 142 | + | ||
| 143 | + @Override | ||
| 144 | + public MailTemplateDO getMailTemplateByCodeFromCache(String code) { | ||
| 145 | + return mailTemplateCache.get(code); | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + @Override | ||
| 149 | + public String formatMailTemplateContent(String content, Map<String, Object> params) { | ||
| 150 | + return StrUtil.format(content, params); | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + @VisibleForTesting | ||
| 154 | + public List<String> parseTemplateContentParams(String content) { | ||
| 155 | + return ReUtil.findAllGroup1(PATTERN_PARAMS, content); | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + @Override | ||
| 159 | + public long countByAccountId(Long accountId) { | ||
| 160 | + return mailTemplateMapper.selectCountByAccountId(accountId); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/member/MemberService.java
| @@ -15,4 +15,12 @@ public interface MemberService { | @@ -15,4 +15,12 @@ public interface MemberService { | ||
| 15 | */ | 15 | */ |
| 16 | String getMemberUserMobile(Long id); | 16 | String getMemberUserMobile(Long id); |
| 17 | 17 | ||
| 18 | + /** | ||
| 19 | + * 获得会员用户的邮箱 | ||
| 20 | + * | ||
| 21 | + * @param id 会员用户编号 | ||
| 22 | + * @return 邮箱 | ||
| 23 | + */ | ||
| 24 | + String getMemberUserEmail(Long id); | ||
| 25 | + | ||
| 18 | } | 26 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/member/MemberServiceImpl.java
| @@ -21,14 +21,27 @@ public class MemberServiceImpl implements MemberService { | @@ -21,14 +21,27 @@ public class MemberServiceImpl implements MemberService { | ||
| 21 | 21 | ||
| 22 | @Override | 22 | @Override |
| 23 | public String getMemberUserMobile(Long id) { | 23 | public String getMemberUserMobile(Long id) { |
| 24 | - if (id == null) { | 24 | + Object user = getMemberUser(id); |
| 25 | + if (user == null) { | ||
| 25 | return null; | 26 | return null; |
| 26 | } | 27 | } |
| 27 | - Object user = ReflectUtil.invoke(getMemberUserApi(), "getUser", id); | 28 | + return ReflectUtil.invoke(user, "getMobile"); |
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public String getMemberUserEmail(Long id) { | ||
| 33 | + Object user = getMemberUser(id); | ||
| 28 | if (user == null) { | 34 | if (user == null) { |
| 29 | return null; | 35 | return null; |
| 30 | } | 36 | } |
| 31 | - return ReflectUtil.invoke(user, "getMobile"); | 37 | + return ReflectUtil.invoke(user, "getEmail"); |
| 38 | + } | ||
| 39 | + | ||
| 40 | + private Object getMemberUser(Long id) { | ||
| 41 | + if (id == null) { | ||
| 42 | + return null; | ||
| 43 | + } | ||
| 44 | + return ReflectUtil.invoke(getMemberUserApi(), "getUser", id); | ||
| 32 | } | 45 | } |
| 33 | 46 | ||
| 34 | private Object getMemberUserApi() { | 47 | private Object getMemberUserApi() { |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java
| @@ -17,20 +17,17 @@ import com.google.common.annotations.VisibleForTesting; | @@ -17,20 +17,17 @@ import com.google.common.annotations.VisibleForTesting; | ||
| 17 | import lombok.Getter; | 17 | import lombok.Getter; |
| 18 | import lombok.Setter; | 18 | import lombok.Setter; |
| 19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
| 20 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 21 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
| 22 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 23 | 22 | ||
| 24 | import javax.annotation.PostConstruct; | 23 | import javax.annotation.PostConstruct; |
| 25 | import javax.annotation.Resource; | 24 | import javax.annotation.Resource; |
| 26 | -import java.time.LocalDateTime; | ||
| 27 | import java.util.Collection; | 25 | import java.util.Collection; |
| 28 | import java.util.List; | 26 | import java.util.List; |
| 29 | import java.util.Map; | 27 | import java.util.Map; |
| 30 | 28 | ||
| 31 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 32 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 30 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 33 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue; | ||
| 34 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | 31 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; |
| 35 | 32 | ||
| 36 | /** | 33 | /** |
| @@ -44,12 +41,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -44,12 +41,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 44 | public class OAuth2ClientServiceImpl implements OAuth2ClientService { | 41 | public class OAuth2ClientServiceImpl implements OAuth2ClientService { |
| 45 | 42 | ||
| 46 | /** | 43 | /** |
| 47 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 48 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 49 | - */ | ||
| 50 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 51 | - | ||
| 52 | - /** | ||
| 53 | * 客户端缓存 | 44 | * 客户端缓存 |
| 54 | * key:客户端编号 {@link OAuth2ClientDO#getClientId()} ()} | 45 | * key:客户端编号 {@link OAuth2ClientDO#getClientId()} ()} |
| 55 | * | 46 | * |
| @@ -58,11 +49,6 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { | @@ -58,11 +49,6 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { | ||
| 58 | @Getter // 解决单测 | 49 | @Getter // 解决单测 |
| 59 | @Setter // 解决单测 | 50 | @Setter // 解决单测 |
| 60 | private volatile Map<String, OAuth2ClientDO> clientCache; | 51 | private volatile Map<String, OAuth2ClientDO> clientCache; |
| 61 | - /** | ||
| 62 | - * 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 63 | - */ | ||
| 64 | - @Getter | ||
| 65 | - private volatile LocalDateTime maxUpdateTime; | ||
| 66 | 52 | ||
| 67 | @Resource | 53 | @Resource |
| 68 | private OAuth2ClientMapper oauth2ClientMapper; | 54 | private OAuth2ClientMapper oauth2ClientMapper; |
| @@ -76,37 +62,12 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { | @@ -76,37 +62,12 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { | ||
| 76 | @Override | 62 | @Override |
| 77 | @PostConstruct | 63 | @PostConstruct |
| 78 | public void initLocalCache() { | 64 | public void initLocalCache() { |
| 79 | - initLocalCacheIfUpdate(null); | ||
| 80 | - } | ||
| 81 | - | ||
| 82 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 83 | - public void schedulePeriodicRefresh() { | ||
| 84 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - /** | ||
| 88 | - * 刷新本地缓存 | ||
| 89 | - * | ||
| 90 | - * @param maxUpdateTime 最大更新时间 | ||
| 91 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 92 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 93 | - */ | ||
| 94 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 95 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 96 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 97 | - if (maxUpdateTime != null | ||
| 98 | - && oauth2ClientMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 99 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 100 | - return; | ||
| 101 | - } | 65 | + // 第一步:查询数据 |
| 102 | List<OAuth2ClientDO> clients = oauth2ClientMapper.selectList(); | 66 | List<OAuth2ClientDO> clients = oauth2ClientMapper.selectList(); |
| 103 | - log.info("[initLocalCacheIfUpdate][缓存 OAuth2 客户端,数量为:{}]", clients.size()); | 67 | + log.info("[initLocalCache][缓存 OAuth2 客户端,数量为:{}]", clients.size()); |
| 104 | 68 | ||
| 105 | // 第二步:构建缓存。 | 69 | // 第二步:构建缓存。 |
| 106 | clientCache = convertMap(clients, OAuth2ClientDO::getClientId); | 70 | clientCache = convertMap(clients, OAuth2ClientDO::getClientId); |
| 107 | - | ||
| 108 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 109 | - this.maxUpdateTime = getMaxValue(clients, OAuth2ClientDO::getUpdateTime); | ||
| 110 | } | 71 | } |
| 111 | 72 | ||
| 112 | @Override | 73 | @Override |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java
| @@ -18,9 +18,9 @@ import com.google.common.annotations.VisibleForTesting; | @@ -18,9 +18,9 @@ import com.google.common.annotations.VisibleForTesting; | ||
| 18 | import com.google.common.collect.ImmutableMap; | 18 | import com.google.common.collect.ImmutableMap; |
| 19 | import com.google.common.collect.ImmutableMultimap; | 19 | import com.google.common.collect.ImmutableMultimap; |
| 20 | import com.google.common.collect.Multimap; | 20 | import com.google.common.collect.Multimap; |
| 21 | +import lombok.Getter; | ||
| 21 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
| 22 | import org.springframework.context.annotation.Lazy; | 23 | import org.springframework.context.annotation.Lazy; |
| 23 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 24 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 25 | import org.springframework.transaction.annotation.Transactional; | 25 | import org.springframework.transaction.annotation.Transactional; |
| 26 | import org.springframework.transaction.support.TransactionSynchronization; | 26 | import org.springframework.transaction.support.TransactionSynchronization; |
| @@ -28,7 +28,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | @@ -28,7 +28,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | ||
| 28 | 28 | ||
| 29 | import javax.annotation.PostConstruct; | 29 | import javax.annotation.PostConstruct; |
| 30 | import javax.annotation.Resource; | 30 | import javax.annotation.Resource; |
| 31 | -import java.time.LocalDateTime; | ||
| 32 | import java.util.*; | 31 | import java.util.*; |
| 33 | import java.util.stream.Collectors; | 32 | import java.util.stream.Collectors; |
| 34 | 33 | ||
| @@ -44,17 +43,12 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -44,17 +43,12 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 44 | public class MenuServiceImpl implements MenuService { | 43 | public class MenuServiceImpl implements MenuService { |
| 45 | 44 | ||
| 46 | /** | 45 | /** |
| 47 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 48 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 49 | - */ | ||
| 50 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 51 | - | ||
| 52 | - /** | ||
| 53 | * 菜单缓存 | 46 | * 菜单缓存 |
| 54 | * key:菜单编号 | 47 | * key:菜单编号 |
| 55 | * | 48 | * |
| 56 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | 49 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 |
| 57 | */ | 50 | */ |
| 51 | + @Getter | ||
| 58 | private volatile Map<Long, MenuDO> menuCache; | 52 | private volatile Map<Long, MenuDO> menuCache; |
| 59 | /** | 53 | /** |
| 60 | * 权限与菜单缓存 | 54 | * 权限与菜单缓存 |
| @@ -63,11 +57,8 @@ public class MenuServiceImpl implements MenuService { | @@ -63,11 +57,8 @@ public class MenuServiceImpl implements MenuService { | ||
| 63 | * | 57 | * |
| 64 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | 58 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 |
| 65 | */ | 59 | */ |
| 60 | + @Getter | ||
| 66 | private volatile Multimap<String, MenuDO> permissionMenuCache; | 61 | private volatile Multimap<String, MenuDO> permissionMenuCache; |
| 67 | - /** | ||
| 68 | - * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 69 | - */ | ||
| 70 | - private volatile LocalDateTime maxUpdateTime; | ||
| 71 | 62 | ||
| 72 | @Resource | 63 | @Resource |
| 73 | private MenuMapper menuMapper; | 64 | private MenuMapper menuMapper; |
| @@ -86,33 +77,11 @@ public class MenuServiceImpl implements MenuService { | @@ -86,33 +77,11 @@ public class MenuServiceImpl implements MenuService { | ||
| 86 | @Override | 77 | @Override |
| 87 | @PostConstruct | 78 | @PostConstruct |
| 88 | public synchronized void initLocalCache() { | 79 | public synchronized void initLocalCache() { |
| 89 | - initLocalCacheIfUpdate(null); | ||
| 90 | - } | ||
| 91 | - | ||
| 92 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 93 | - public void schedulePeriodicRefresh() { | ||
| 94 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - /** | ||
| 98 | - * 刷新本地缓存 | ||
| 99 | - * | ||
| 100 | - * @param maxUpdateTime 最大更新时间 | ||
| 101 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 102 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 103 | - */ | ||
| 104 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 105 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 106 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 107 | - if (maxUpdateTime != null | ||
| 108 | - && menuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 109 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 110 | - return; | ||
| 111 | - } | 80 | + // 第一步:查询数据 |
| 112 | List<MenuDO> menuList = menuMapper.selectList(); | 81 | List<MenuDO> menuList = menuMapper.selectList(); |
| 113 | - log.info("[initLocalCacheIfUpdate][缓存菜单,数量为:{}]", menuList.size()); | 82 | + log.info("[initLocalCache][缓存菜单,数量为:{}]", menuList.size()); |
| 114 | 83 | ||
| 115 | - // 第二步:构建缓存。 | 84 | + // 第二步:构建缓存 |
| 116 | ImmutableMap.Builder<Long, MenuDO> menuCacheBuilder = ImmutableMap.builder(); | 85 | ImmutableMap.Builder<Long, MenuDO> menuCacheBuilder = ImmutableMap.builder(); |
| 117 | ImmutableMultimap.Builder<String, MenuDO> permMenuCacheBuilder = ImmutableMultimap.builder(); | 86 | ImmutableMultimap.Builder<String, MenuDO> permMenuCacheBuilder = ImmutableMultimap.builder(); |
| 118 | menuList.forEach(menuDO -> { | 87 | menuList.forEach(menuDO -> { |
| @@ -123,9 +92,6 @@ public class MenuServiceImpl implements MenuService { | @@ -123,9 +92,6 @@ public class MenuServiceImpl implements MenuService { | ||
| 123 | }); | 92 | }); |
| 124 | menuCache = menuCacheBuilder.build(); | 93 | menuCache = menuCacheBuilder.build(); |
| 125 | permissionMenuCache = permMenuCacheBuilder.build(); | 94 | permissionMenuCache = permMenuCacheBuilder.build(); |
| 126 | - | ||
| 127 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 128 | - this.maxUpdateTime = CollectionUtils.getMaxValue(menuList, MenuDO::getUpdateTime); | ||
| 129 | } | 95 | } |
| 130 | 96 | ||
| 131 | @Override | 97 | @Override |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
| @@ -16,9 +16,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | @@ -16,9 +16,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | ||
| 16 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | 16 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| 17 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; | 17 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; |
| 18 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; | 18 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; |
| 19 | -import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuBatchInsertMapper; | ||
| 20 | import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; | 19 | import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; |
| 21 | -import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleBatchInsertMapper; | ||
| 22 | import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; | 20 | import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; |
| 23 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; | 21 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; |
| 24 | import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; | 22 | import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; |
| @@ -32,7 +30,6 @@ import com.google.common.collect.Sets; | @@ -32,7 +30,6 @@ import com.google.common.collect.Sets; | ||
| 32 | import lombok.Getter; | 30 | import lombok.Getter; |
| 33 | import lombok.Setter; | 31 | import lombok.Setter; |
| 34 | import lombok.extern.slf4j.Slf4j; | 32 | import lombok.extern.slf4j.Slf4j; |
| 35 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 36 | import org.springframework.stereotype.Service; | 33 | import org.springframework.stereotype.Service; |
| 37 | import org.springframework.transaction.annotation.Transactional; | 34 | import org.springframework.transaction.annotation.Transactional; |
| 38 | import org.springframework.transaction.support.TransactionSynchronization; | 35 | import org.springframework.transaction.support.TransactionSynchronization; |
| @@ -40,12 +37,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | @@ -40,12 +37,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | ||
| 40 | 37 | ||
| 41 | import javax.annotation.PostConstruct; | 38 | import javax.annotation.PostConstruct; |
| 42 | import javax.annotation.Resource; | 39 | import javax.annotation.Resource; |
| 43 | -import java.time.LocalDateTime; | ||
| 44 | import java.util.*; | 40 | import java.util.*; |
| 45 | import java.util.function.Supplier; | 41 | import java.util.function.Supplier; |
| 46 | 42 | ||
| 47 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 43 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 48 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue; | ||
| 49 | import static java.util.Collections.singleton; | 44 | import static java.util.Collections.singleton; |
| 50 | 45 | ||
| 51 | /** | 46 | /** |
| @@ -58,12 +53,6 @@ import static java.util.Collections.singleton; | @@ -58,12 +53,6 @@ import static java.util.Collections.singleton; | ||
| 58 | public class PermissionServiceImpl implements PermissionService { | 53 | public class PermissionServiceImpl implements PermissionService { |
| 59 | 54 | ||
| 60 | /** | 55 | /** |
| 61 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 62 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 63 | - */ | ||
| 64 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 65 | - | ||
| 66 | - /** | ||
| 67 | * 角色编号与菜单编号的缓存映射 | 56 | * 角色编号与菜单编号的缓存映射 |
| 68 | * key:角色编号 | 57 | * key:角色编号 |
| 69 | * value:菜单编号的数组 | 58 | * value:菜单编号的数组 |
| @@ -83,11 +72,6 @@ public class PermissionServiceImpl implements PermissionService { | @@ -83,11 +72,6 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 83 | @Getter | 72 | @Getter |
| 84 | @Setter // 单元测试需要 | 73 | @Setter // 单元测试需要 |
| 85 | private volatile Multimap<Long, Long> menuRoleCache; | 74 | private volatile Multimap<Long, Long> menuRoleCache; |
| 86 | - /** | ||
| 87 | - * 缓存 RoleMenu 的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 88 | - */ | ||
| 89 | - @Getter | ||
| 90 | - private volatile LocalDateTime roleMenuMaxUpdateTime; | ||
| 91 | 75 | ||
| 92 | /** | 76 | /** |
| 93 | * 用户编号与角色编号的缓存映射 | 77 | * 用户编号与角色编号的缓存映射 |
| @@ -99,20 +83,11 @@ public class PermissionServiceImpl implements PermissionService { | @@ -99,20 +83,11 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 99 | @Getter | 83 | @Getter |
| 100 | @Setter // 单元测试需要 | 84 | @Setter // 单元测试需要 |
| 101 | private volatile Map<Long, Set<Long>> userRoleCache; | 85 | private volatile Map<Long, Set<Long>> userRoleCache; |
| 102 | - /** | ||
| 103 | - * 缓存 UserRole 的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 104 | - */ | ||
| 105 | - @Getter | ||
| 106 | - private volatile LocalDateTime userRoleMaxUpdateTime; | ||
| 107 | 86 | ||
| 108 | @Resource | 87 | @Resource |
| 109 | private RoleMenuMapper roleMenuMapper; | 88 | private RoleMenuMapper roleMenuMapper; |
| 110 | @Resource | 89 | @Resource |
| 111 | - private RoleMenuBatchInsertMapper roleMenuBatchInsertMapper; | ||
| 112 | - @Resource | ||
| 113 | private UserRoleMapper userRoleMapper; | 90 | private UserRoleMapper userRoleMapper; |
| 114 | - @Resource | ||
| 115 | - private UserRoleBatchInsertMapper userRoleBatchInsertMapper; | ||
| 116 | 91 | ||
| 117 | @Resource | 92 | @Resource |
| 118 | private RoleService roleService; | 93 | private RoleService roleService; |
| @@ -129,38 +104,22 @@ public class PermissionServiceImpl implements PermissionService { | @@ -129,38 +104,22 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 129 | @Override | 104 | @Override |
| 130 | @PostConstruct | 105 | @PostConstruct |
| 131 | public void initLocalCache() { | 106 | public void initLocalCache() { |
| 132 | - initLocalCacheIfUpdateForRoleMenu(null); | ||
| 133 | - initLocalCacheIfUpdateForUserRole(null); | ||
| 134 | - } | ||
| 135 | - | ||
| 136 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 137 | - public void schedulePeriodicRefresh() { | ||
| 138 | - initLocalCacheIfUpdateForRoleMenu(this.roleMenuMaxUpdateTime); | ||
| 139 | - initLocalCacheIfUpdateForUserRole(this.userRoleMaxUpdateTime); | 107 | + initLocalCacheForRoleMenu(); |
| 108 | + initLocalCacheForUserRole(); | ||
| 140 | } | 109 | } |
| 141 | 110 | ||
| 142 | /** | 111 | /** |
| 143 | * 刷新 RoleMenu 本地缓存 | 112 | * 刷新 RoleMenu 本地缓存 |
| 144 | - * | ||
| 145 | - * @param maxUpdateTime 最大更新时间 | ||
| 146 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 147 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 148 | */ | 113 | */ |
| 149 | @VisibleForTesting | 114 | @VisibleForTesting |
| 150 | - void initLocalCacheIfUpdateForRoleMenu(LocalDateTime maxUpdateTime) { | 115 | + void initLocalCacheForRoleMenu() { |
| 151 | // 注意:忽略自动多租户,因为要全局初始化缓存 | 116 | // 注意:忽略自动多租户,因为要全局初始化缓存 |
| 152 | TenantUtils.executeIgnore(() -> { | 117 | TenantUtils.executeIgnore(() -> { |
| 153 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 154 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 155 | - if (maxUpdateTime != null | ||
| 156 | - && roleMenuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 157 | - log.info("[initLocalCacheIfUpdateForRoleMenu][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 158 | - return; | ||
| 159 | - } | 118 | + // 第一步:查询数据 |
| 160 | List<RoleMenuDO> roleMenus = roleMenuMapper.selectList(); | 119 | List<RoleMenuDO> roleMenus = roleMenuMapper.selectList(); |
| 161 | - log.info("[initLocalCacheIfUpdateForRoleMenu][缓存角色与菜单,数量为:{}]", roleMenus.size()); | 120 | + log.info("[initLocalCacheForRoleMenu][缓存角色与菜单,数量为:{}]", roleMenus.size()); |
| 162 | 121 | ||
| 163 | - // 第二步:构建缓存。 | 122 | + // 第二步:构建缓存 |
| 164 | ImmutableMultimap.Builder<Long, Long> roleMenuCacheBuilder = ImmutableMultimap.builder(); | 123 | ImmutableMultimap.Builder<Long, Long> roleMenuCacheBuilder = ImmutableMultimap.builder(); |
| 165 | ImmutableMultimap.Builder<Long, Long> menuRoleCacheBuilder = ImmutableMultimap.builder(); | 124 | ImmutableMultimap.Builder<Long, Long> menuRoleCacheBuilder = ImmutableMultimap.builder(); |
| 166 | roleMenus.forEach(roleMenuDO -> { | 125 | roleMenus.forEach(roleMenuDO -> { |
| @@ -169,40 +128,24 @@ public class PermissionServiceImpl implements PermissionService { | @@ -169,40 +128,24 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 169 | }); | 128 | }); |
| 170 | roleMenuCache = roleMenuCacheBuilder.build(); | 129 | roleMenuCache = roleMenuCacheBuilder.build(); |
| 171 | menuRoleCache = menuRoleCacheBuilder.build(); | 130 | menuRoleCache = menuRoleCacheBuilder.build(); |
| 172 | - | ||
| 173 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 174 | - this.roleMenuMaxUpdateTime = getMaxValue(roleMenus, RoleMenuDO::getUpdateTime); | ||
| 175 | }); | 131 | }); |
| 176 | } | 132 | } |
| 177 | 133 | ||
| 178 | /** | 134 | /** |
| 179 | * 刷新 UserRole 本地缓存 | 135 | * 刷新 UserRole 本地缓存 |
| 180 | - * | ||
| 181 | - * @param maxUpdateTime 最大更新时间 | ||
| 182 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 183 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 184 | */ | 136 | */ |
| 185 | @VisibleForTesting | 137 | @VisibleForTesting |
| 186 | - void initLocalCacheIfUpdateForUserRole(LocalDateTime maxUpdateTime) { | 138 | + void initLocalCacheForUserRole() { |
| 187 | // 注意:忽略自动多租户,因为要全局初始化缓存 | 139 | // 注意:忽略自动多租户,因为要全局初始化缓存 |
| 188 | TenantUtils.executeIgnore(() -> { | 140 | TenantUtils.executeIgnore(() -> { |
| 189 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 190 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 191 | - if (maxUpdateTime != null | ||
| 192 | - && userRoleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 193 | - log.info("[initLocalCacheIfUpdateForUserRole][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 194 | - return; | ||
| 195 | - } | 141 | + // 第一步:加载数据 |
| 196 | List<UserRoleDO> userRoles = userRoleMapper.selectList(); | 142 | List<UserRoleDO> userRoles = userRoleMapper.selectList(); |
| 197 | - log.info("[initLocalCacheIfUpdateForUserRole][缓存用户与角色,数量为:{}]", userRoles.size()); | 143 | + log.info("[initLocalCacheForUserRole][缓存用户与角色,数量为:{}]", userRoles.size()); |
| 198 | 144 | ||
| 199 | // 第二步:构建缓存。 | 145 | // 第二步:构建缓存。 |
| 200 | ImmutableMultimap.Builder<Long, Long> userRoleCacheBuilder = ImmutableMultimap.builder(); | 146 | ImmutableMultimap.Builder<Long, Long> userRoleCacheBuilder = ImmutableMultimap.builder(); |
| 201 | userRoles.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId())); | 147 | userRoles.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId())); |
| 202 | userRoleCache = CollectionUtils.convertMultiMap2(userRoles, UserRoleDO::getUserId, UserRoleDO::getRoleId); | 148 | userRoleCache = CollectionUtils.convertMultiMap2(userRoles, UserRoleDO::getUserId, UserRoleDO::getRoleId); |
| 203 | - | ||
| 204 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 205 | - this.userRoleMaxUpdateTime = getMaxValue(userRoles, UserRoleDO::getUpdateTime); | ||
| 206 | }); | 149 | }); |
| 207 | } | 150 | } |
| 208 | 151 | ||
| @@ -264,7 +207,7 @@ public class PermissionServiceImpl implements PermissionService { | @@ -264,7 +207,7 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 264 | Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds); | 207 | Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds); |
| 265 | // 执行新增和删除。对于已经授权的菜单,不用做任何处理 | 208 | // 执行新增和删除。对于已经授权的菜单,不用做任何处理 |
| 266 | if (!CollectionUtil.isEmpty(createMenuIds)) { | 209 | if (!CollectionUtil.isEmpty(createMenuIds)) { |
| 267 | - roleMenuBatchInsertMapper.saveBatch(CollectionUtils.convertList(createMenuIds, menuId -> { | 210 | + roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> { |
| 268 | RoleMenuDO entity = new RoleMenuDO(); | 211 | RoleMenuDO entity = new RoleMenuDO(); |
| 269 | entity.setRoleId(roleId); | 212 | entity.setRoleId(roleId); |
| 270 | entity.setMenuId(menuId); | 213 | entity.setMenuId(menuId); |
| @@ -308,7 +251,7 @@ public class PermissionServiceImpl implements PermissionService { | @@ -308,7 +251,7 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 308 | Collection<Long> deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIds); | 251 | Collection<Long> deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIds); |
| 309 | // 执行新增和删除。对于已经授权的角色,不用做任何处理 | 252 | // 执行新增和删除。对于已经授权的角色,不用做任何处理 |
| 310 | if (!CollectionUtil.isEmpty(createRoleIds)) { | 253 | if (!CollectionUtil.isEmpty(createRoleIds)) { |
| 311 | - userRoleBatchInsertMapper.saveBatch(CollectionUtils.convertList(createRoleIds, roleId -> { | 254 | + userRoleMapper.insertBatch(CollectionUtils.convertList(createRoleIds, roleId -> { |
| 312 | UserRoleDO entity = new UserRoleDO(); | 255 | UserRoleDO entity = new UserRoleDO(); |
| 313 | entity.setUserId(userId); | 256 | entity.setUserId(userId); |
| 314 | entity.setRoleId(roleId); | 257 | entity.setRoleId(roleId); |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
| @@ -22,7 +22,6 @@ import com.google.common.annotations.VisibleForTesting; | @@ -22,7 +22,6 @@ import com.google.common.annotations.VisibleForTesting; | ||
| 22 | import lombok.Getter; | 22 | import lombok.Getter; |
| 23 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
| 24 | import org.springframework.lang.Nullable; | 24 | import org.springframework.lang.Nullable; |
| 25 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 26 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
| 27 | import org.springframework.transaction.annotation.Transactional; | 26 | import org.springframework.transaction.annotation.Transactional; |
| 28 | import org.springframework.transaction.support.TransactionSynchronization; | 27 | import org.springframework.transaction.support.TransactionSynchronization; |
| @@ -31,7 +30,6 @@ import org.springframework.util.StringUtils; | @@ -31,7 +30,6 @@ import org.springframework.util.StringUtils; | ||
| 31 | 30 | ||
| 32 | import javax.annotation.PostConstruct; | 31 | import javax.annotation.PostConstruct; |
| 33 | import javax.annotation.Resource; | 32 | import javax.annotation.Resource; |
| 34 | -import java.time.LocalDateTime; | ||
| 35 | import java.util.*; | 33 | import java.util.*; |
| 36 | import java.util.stream.Collectors; | 34 | import java.util.stream.Collectors; |
| 37 | 35 | ||
| @@ -48,12 +46,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -48,12 +46,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 48 | public class RoleServiceImpl implements RoleService { | 46 | public class RoleServiceImpl implements RoleService { |
| 49 | 47 | ||
| 50 | /** | 48 | /** |
| 51 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 52 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 53 | - */ | ||
| 54 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 55 | - | ||
| 56 | - /** | ||
| 57 | * 角色缓存 | 49 | * 角色缓存 |
| 58 | * key:角色编号 {@link RoleDO#getId()} | 50 | * key:角色编号 {@link RoleDO#getId()} |
| 59 | * | 51 | * |
| @@ -61,11 +53,6 @@ public class RoleServiceImpl implements RoleService { | @@ -61,11 +53,6 @@ public class RoleServiceImpl implements RoleService { | ||
| 61 | */ | 53 | */ |
| 62 | @Getter | 54 | @Getter |
| 63 | private volatile Map<Long, RoleDO> roleCache; | 55 | private volatile Map<Long, RoleDO> roleCache; |
| 64 | - /** | ||
| 65 | - * 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 66 | - */ | ||
| 67 | - @Getter | ||
| 68 | - private volatile LocalDateTime maxUpdateTime; | ||
| 69 | 56 | ||
| 70 | @Resource | 57 | @Resource |
| 71 | private PermissionService permissionService; | 58 | private PermissionService permissionService; |
| @@ -82,39 +69,14 @@ public class RoleServiceImpl implements RoleService { | @@ -82,39 +69,14 @@ public class RoleServiceImpl implements RoleService { | ||
| 82 | @Override | 69 | @Override |
| 83 | @PostConstruct | 70 | @PostConstruct |
| 84 | public void initLocalCache() { | 71 | public void initLocalCache() { |
| 85 | - initLocalCacheIfUpdate(null); | ||
| 86 | - } | ||
| 87 | - | ||
| 88 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 89 | - public void schedulePeriodicRefresh() { | ||
| 90 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 91 | - } | ||
| 92 | - | ||
| 93 | - /** | ||
| 94 | - * 刷新本地缓存 | ||
| 95 | - * | ||
| 96 | - * @param maxUpdateTime 最大更新时间 | ||
| 97 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 98 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 99 | - */ | ||
| 100 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 101 | // 注意:忽略自动多租户,因为要全局初始化缓存 | 72 | // 注意:忽略自动多租户,因为要全局初始化缓存 |
| 102 | TenantUtils.executeIgnore(() -> { | 73 | TenantUtils.executeIgnore(() -> { |
| 103 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 104 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 105 | - if (maxUpdateTime != null | ||
| 106 | - && roleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 107 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 108 | - return; | ||
| 109 | - } | 74 | + // 第一步:查询数据 |
| 110 | List<RoleDO> roleList = roleMapper.selectList(); | 75 | List<RoleDO> roleList = roleMapper.selectList(); |
| 111 | - log.info("[initLocalCacheIfUpdate][缓存角色,数量为:{}]", roleList.size()); | 76 | + log.info("[initLocalCache][缓存角色,数量为:{}]", roleList.size()); |
| 112 | 77 | ||
| 113 | - // 第二步:构建缓存。 | 78 | + // 第二步:构建缓存 |
| 114 | roleCache = CollectionUtils.convertMap(roleList, RoleDO::getId); | 79 | roleCache = CollectionUtils.convertMap(roleList, RoleDO::getId); |
| 115 | - | ||
| 116 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 117 | - this.maxUpdateTime = CollectionUtils.getMaxValue(roleList, RoleDO::getUpdateTime); | ||
| 118 | }); | 80 | }); |
| 119 | } | 81 | } |
| 120 | 82 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java
| @@ -17,13 +17,11 @@ import com.google.common.collect.HashMultimap; | @@ -17,13 +17,11 @@ import com.google.common.collect.HashMultimap; | ||
| 17 | import com.google.common.collect.Multimap; | 17 | import com.google.common.collect.Multimap; |
| 18 | import lombok.Getter; | 18 | import lombok.Getter; |
| 19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
| 20 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 21 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
| 22 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 23 | 22 | ||
| 24 | import javax.annotation.PostConstruct; | 23 | import javax.annotation.PostConstruct; |
| 25 | import javax.annotation.Resource; | 24 | import javax.annotation.Resource; |
| 26 | -import java.time.LocalDateTime; | ||
| 27 | import java.util.*; | 25 | import java.util.*; |
| 28 | 26 | ||
| 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 27 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -41,12 +39,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_ | @@ -41,12 +39,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_ | ||
| 41 | public class SensitiveWordServiceImpl implements SensitiveWordService { | 39 | public class SensitiveWordServiceImpl implements SensitiveWordService { |
| 42 | 40 | ||
| 43 | /** | 41 | /** |
| 44 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 45 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 46 | - */ | ||
| 47 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 48 | - | ||
| 49 | - /** | ||
| 50 | * 敏感词标签缓存 | 42 | * 敏感词标签缓存 |
| 51 | * key:敏感词编号 {@link SensitiveWordDO#getId()} | 43 | * key:敏感词编号 {@link SensitiveWordDO#getId()} |
| 52 | * <p> | 44 | * <p> |
| @@ -55,12 +47,6 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { | @@ -55,12 +47,6 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { | ||
| 55 | @Getter | 47 | @Getter |
| 56 | private volatile Set<String> sensitiveWordTagsCache = Collections.emptySet(); | 48 | private volatile Set<String> sensitiveWordTagsCache = Collections.emptySet(); |
| 57 | 49 | ||
| 58 | - /** | ||
| 59 | - * 缓存敏感词的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 60 | - */ | ||
| 61 | - @Getter | ||
| 62 | - private volatile LocalDateTime maxUpdateTime; | ||
| 63 | - | ||
| 64 | @Resource | 50 | @Resource |
| 65 | private SensitiveWordMapper sensitiveWordMapper; | 51 | private SensitiveWordMapper sensitiveWordMapper; |
| 66 | 52 | ||
| @@ -84,42 +70,17 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { | @@ -84,42 +70,17 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { | ||
| 84 | @Override | 70 | @Override |
| 85 | @PostConstruct | 71 | @PostConstruct |
| 86 | public void initLocalCache() { | 72 | public void initLocalCache() { |
| 87 | - initLocalCacheIfUpdate(null); | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 91 | - public void schedulePeriodicRefresh() { | ||
| 92 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 93 | - } | ||
| 94 | - | ||
| 95 | - /** | ||
| 96 | - * 刷新本地缓存 | ||
| 97 | - * | ||
| 98 | - * @param maxUpdateTime 最大更新时间 | ||
| 99 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 100 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 101 | - */ | ||
| 102 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 103 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 104 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 105 | - if (maxUpdateTime != null | ||
| 106 | - && sensitiveWordMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 107 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 108 | - return; | ||
| 109 | - } | 73 | + // 第一步:查询数据 |
| 110 | List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList(); | 74 | List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList(); |
| 111 | - log.info("[initLocalCacheIfUpdate][缓存敏感词,数量为:{}]", sensitiveWords.size()); | 75 | + log.info("[initLocalCache][缓存敏感词,数量为:{}]", sensitiveWords.size()); |
| 112 | 76 | ||
| 113 | - // 第二步:构建缓存。 | 77 | + // 第二步:构建缓存 |
| 114 | // 写入 sensitiveWordTagsCache 缓存 | 78 | // 写入 sensitiveWordTagsCache 缓存 |
| 115 | Set<String> tags = new HashSet<>(); | 79 | Set<String> tags = new HashSet<>(); |
| 116 | sensitiveWords.forEach(word -> tags.addAll(word.getTags())); | 80 | sensitiveWords.forEach(word -> tags.addAll(word.getTags())); |
| 117 | sensitiveWordTagsCache = tags; | 81 | sensitiveWordTagsCache = tags; |
| 118 | // 写入 defaultSensitiveWordTrie、tagSensitiveWordTries 缓存 | 82 | // 写入 defaultSensitiveWordTrie、tagSensitiveWordTries 缓存 |
| 119 | initSensitiveWordTrie(sensitiveWords); | 83 | initSensitiveWordTrie(sensitiveWords); |
| 120 | - | ||
| 121 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 122 | - this.maxUpdateTime = CollectionUtils.getMaxValue(sensitiveWords, SensitiveWordDO::getUpdateTime); | ||
| 123 | } | 84 | } |
| 124 | 85 | ||
| 125 | private void initSensitiveWordTrie(List<SensitiveWordDO> wordDOs) { | 86 | private void initSensitiveWordTrie(List<SensitiveWordDO> wordDOs) { |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java
| @@ -11,17 +11,14 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | @@ -11,17 +11,14 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | ||
| 11 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; | 11 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; |
| 12 | import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; | 12 | import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; |
| 13 | import lombok.extern.slf4j.Slf4j; | 13 | import lombok.extern.slf4j.Slf4j; |
| 14 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 15 | import org.springframework.stereotype.Service; | 14 | import org.springframework.stereotype.Service; |
| 16 | 15 | ||
| 17 | import javax.annotation.PostConstruct; | 16 | import javax.annotation.PostConstruct; |
| 18 | import javax.annotation.Resource; | 17 | import javax.annotation.Resource; |
| 19 | -import java.time.LocalDateTime; | ||
| 20 | import java.util.Collection; | 18 | import java.util.Collection; |
| 21 | import java.util.List; | 19 | import java.util.List; |
| 22 | 20 | ||
| 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 24 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue; | ||
| 25 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; | 22 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; |
| 26 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; | 23 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; |
| 27 | 24 | ||
| @@ -34,17 +31,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNE | @@ -34,17 +31,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNE | ||
| 34 | @Slf4j | 31 | @Slf4j |
| 35 | public class SmsChannelServiceImpl implements SmsChannelService { | 32 | public class SmsChannelServiceImpl implements SmsChannelService { |
| 36 | 33 | ||
| 37 | - /** | ||
| 38 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 39 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 40 | - */ | ||
| 41 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 42 | - | ||
| 43 | - /** | ||
| 44 | - * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 45 | - */ | ||
| 46 | - private volatile LocalDateTime maxUpdateTime; | ||
| 47 | - | ||
| 48 | @Resource | 34 | @Resource |
| 49 | private SmsClientFactory smsClientFactory; | 35 | private SmsClientFactory smsClientFactory; |
| 50 | 36 | ||
| @@ -60,38 +46,13 @@ public class SmsChannelServiceImpl implements SmsChannelService { | @@ -60,38 +46,13 @@ public class SmsChannelServiceImpl implements SmsChannelService { | ||
| 60 | @Override | 46 | @Override |
| 61 | @PostConstruct | 47 | @PostConstruct |
| 62 | public void initLocalCache() { | 48 | public void initLocalCache() { |
| 63 | - initLocalCacheIfUpdate(null); | ||
| 64 | - } | ||
| 65 | - | ||
| 66 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 67 | - public void schedulePeriodicRefresh() { | ||
| 68 | - initLocalCacheIfUpdate(this.maxUpdateTime); | ||
| 69 | - } | ||
| 70 | - | ||
| 71 | - /** | ||
| 72 | - * 刷新本地缓存 | ||
| 73 | - * | ||
| 74 | - * @param maxUpdateTime 最大更新时间 | ||
| 75 | - * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 | ||
| 76 | - * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 | ||
| 77 | - */ | ||
| 78 | - private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 79 | - // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 | ||
| 80 | - // 如果没有增量的数据变化,则不进行本地缓存的刷新 | ||
| 81 | - if (maxUpdateTime != null | ||
| 82 | - && smsChannelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 83 | - log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); | ||
| 84 | - return; | ||
| 85 | - } | 49 | + // 第一步:查询数据 |
| 86 | List<SmsChannelDO> channels = smsChannelMapper.selectList(); | 50 | List<SmsChannelDO> channels = smsChannelMapper.selectList(); |
| 87 | - log.info("[initLocalCacheIfUpdate][缓存短信渠道,数量为:{}]", channels.size()); | 51 | + log.info("[initLocalCache][缓存短信渠道,数量为:{}]", channels.size()); |
| 88 | 52 | ||
| 89 | - // 第二步:构建缓存。创建或更新短信 Client | 53 | + // 第二步:构建缓存:创建或更新短信 Client |
| 90 | List<SmsChannelProperties> propertiesList = SmsChannelConvert.INSTANCE.convertList02(channels); | 54 | List<SmsChannelProperties> propertiesList = SmsChannelConvert.INSTANCE.convertList02(channels); |
| 91 | propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties)); | 55 | propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties)); |
| 92 | - | ||
| 93 | - // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 | ||
| 94 | - this.maxUpdateTime = getMaxValue(channels, SmsChannelDO::getUpdateTime); | ||
| 95 | } | 56 | } |
| 96 | 57 | ||
| 97 | @Override | 58 | @Override |
| @@ -120,7 +81,7 @@ public class SmsChannelServiceImpl implements SmsChannelService { | @@ -120,7 +81,7 @@ public class SmsChannelServiceImpl implements SmsChannelService { | ||
| 120 | public void deleteSmsChannel(Long id) { | 81 | public void deleteSmsChannel(Long id) { |
| 121 | // 校验存在 | 82 | // 校验存在 |
| 122 | this.validateSmsChannelExists(id); | 83 | this.validateSmsChannelExists(id); |
| 123 | - // 校验是否有字典数据 | 84 | + // 校验是否有在使用该账号的模版 |
| 124 | if (smsTemplateService.countByChannelId(id) > 0) { | 85 | if (smsTemplateService.countByChannelId(id) > 0) { |
| 125 | throw exception(SMS_CHANNEL_HAS_CHILDREN); | 86 | throw exception(SMS_CHANNEL_HAS_CHILDREN); |
| 126 | } | 87 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.sms; | 1 | package cn.iocoder.yudao.module.system.service.sms; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.util.ReUtil; | 3 | import cn.hutool.core.util.ReUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| @@ -20,15 +19,17 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | @@ -20,15 +19,17 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | ||
| 20 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; | 19 | import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; |
| 21 | import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; | 20 | import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; |
| 22 | import com.google.common.annotations.VisibleForTesting; | 21 | import com.google.common.annotations.VisibleForTesting; |
| 22 | +import lombok.Getter; | ||
| 23 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
| 24 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 25 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 26 | import org.springframework.util.Assert; | 25 | import org.springframework.util.Assert; |
| 27 | 26 | ||
| 28 | import javax.annotation.PostConstruct; | 27 | import javax.annotation.PostConstruct; |
| 29 | import javax.annotation.Resource; | 28 | import javax.annotation.Resource; |
| 30 | -import java.time.LocalDateTime; | ||
| 31 | -import java.util.*; | 29 | +import java.util.Collection; |
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Map; | ||
| 32 | +import java.util.Objects; | ||
| 32 | import java.util.regex.Pattern; | 33 | import java.util.regex.Pattern; |
| 33 | 34 | ||
| 34 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 35 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -38,19 +39,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -38,19 +39,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 38 | * 短信模板 Service 实现类 | 39 | * 短信模板 Service 实现类 |
| 39 | * | 40 | * |
| 40 | * @author zzf | 41 | * @author zzf |
| 41 | - * @date 2021/1/25 9:25 | 42 | + * @since 2021/1/25 9:25 |
| 42 | */ | 43 | */ |
| 43 | @Service | 44 | @Service |
| 44 | @Slf4j | 45 | @Slf4j |
| 45 | public class SmsTemplateServiceImpl implements SmsTemplateService { | 46 | public class SmsTemplateServiceImpl implements SmsTemplateService { |
| 46 | 47 | ||
| 47 | /** | 48 | /** |
| 48 | - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 49 | - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 50 | - */ | ||
| 51 | - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 52 | - | ||
| 53 | - /** | ||
| 54 | * 正则表达式,匹配 {} 中的变量 | 49 | * 正则表达式,匹配 {} 中的变量 |
| 55 | */ | 50 | */ |
| 56 | private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); | 51 | private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); |
| @@ -73,51 +68,18 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { | @@ -73,51 +68,18 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { | ||
| 73 | * | 68 | * |
| 74 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | 69 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 |
| 75 | */ | 70 | */ |
| 71 | + @Getter // 为了方便测试,这里提供 getter 方法 | ||
| 76 | private volatile Map<String, SmsTemplateDO> smsTemplateCache; | 72 | private volatile Map<String, SmsTemplateDO> smsTemplateCache; |
| 77 | - /** | ||
| 78 | - * 缓存短信模板的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 79 | - */ | ||
| 80 | - private volatile LocalDateTime maxUpdateTime; | ||
| 81 | 73 | ||
| 82 | @Override | 74 | @Override |
| 83 | @PostConstruct | 75 | @PostConstruct |
| 84 | public void initLocalCache() { | 76 | public void initLocalCache() { |
| 85 | - // 获取短信模板列表,如果有更新 | ||
| 86 | - List<SmsTemplateDO> smsTemplateList = this.loadSmsTemplateIfUpdate(maxUpdateTime); | ||
| 87 | - if (CollUtil.isEmpty(smsTemplateList)) { | ||
| 88 | - return; | ||
| 89 | - } | 77 | + // 第一步:查询数据 |
| 78 | + List<SmsTemplateDO> smsTemplateList = smsTemplateMapper.selectList(); | ||
| 79 | + log.info("[initLocalCache][缓存短信模版,数量为:{}]", smsTemplateList.size()); | ||
| 90 | 80 | ||
| 91 | - // 写入缓存 | 81 | + // 第二步:构建缓存 |
| 92 | smsTemplateCache = CollectionUtils.convertMap(smsTemplateList, SmsTemplateDO::getCode); | 82 | smsTemplateCache = CollectionUtils.convertMap(smsTemplateList, SmsTemplateDO::getCode); |
| 93 | - maxUpdateTime = CollectionUtils.getMaxValue(smsTemplateList, SmsTemplateDO::getUpdateTime); | ||
| 94 | - log.info("[initLocalCache][初始化 SmsTemplate 数量为 {}]", smsTemplateList.size()); | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - /** | ||
| 98 | - * 如果短信模板发生变化,从数据库中获取最新的全量短信模板。 | ||
| 99 | - * 如果未发生变化,则返回空 | ||
| 100 | - * | ||
| 101 | - * @param maxUpdateTime 当前短信模板的最大更新时间 | ||
| 102 | - * @return 短信模板列表 | ||
| 103 | - */ | ||
| 104 | - private List<SmsTemplateDO> loadSmsTemplateIfUpdate(LocalDateTime maxUpdateTime) { | ||
| 105 | - // 第一步,判断是否要更新。 | ||
| 106 | - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 | ||
| 107 | - log.info("[loadSmsTemplateIfUpdate][首次加载全量短信模板]"); | ||
| 108 | - } else { // 判断数据库中是否有更新的短信模板 | ||
| 109 | - if (smsTemplateMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 110 | - return null; | ||
| 111 | - } | ||
| 112 | - log.info("[loadSmsTemplateIfUpdate][增量加载全量短信模板]"); | ||
| 113 | - } | ||
| 114 | - // 第二步,如果有更新,则从数据库加载所有短信模板 | ||
| 115 | - return smsTemplateMapper.selectList(); | ||
| 116 | - } | ||
| 117 | - | ||
| 118 | - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 119 | - public void schedulePeriodicRefresh() { | ||
| 120 | - initLocalCache(); | ||
| 121 | } | 83 | } |
| 122 | 84 | ||
| 123 | @Override | 85 | @Override |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceTest.java
| 1 | package cn.iocoder.yudao.module.system.service.dept; | 1 | package cn.iocoder.yudao.module.system.service.dept; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 4 | import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; | 6 | import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; |
| 7 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 5 | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; |
| 7 | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; | 10 | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; |
| @@ -9,9 +12,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | @@ -9,9 +12,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | ||
| 9 | import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; | 12 | import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; |
| 10 | import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; | 13 | import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; |
| 11 | import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer; | 14 | import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer; |
| 12 | -import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | ||
| 13 | -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 14 | -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 15 | import com.google.common.collect.Multimap; | 15 | import com.google.common.collect.Multimap; |
| 16 | import org.junit.jupiter.api.BeforeEach; | 16 | import org.junit.jupiter.api.BeforeEach; |
| 17 | import org.junit.jupiter.api.Test; | 17 | import org.junit.jupiter.api.Test; |
| @@ -19,17 +19,15 @@ import org.springframework.boot.test.mock.mockito.MockBean; | @@ -19,17 +19,15 @@ import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 19 | import org.springframework.context.annotation.Import; | 19 | import org.springframework.context.annotation.Import; |
| 20 | 20 | ||
| 21 | import javax.annotation.Resource; | 21 | import javax.annotation.Resource; |
| 22 | -import java.time.LocalDateTime; | ||
| 23 | import java.util.List; | 22 | import java.util.List; |
| 24 | import java.util.Map; | 23 | import java.util.Map; |
| 25 | import java.util.function.Consumer; | 24 | import java.util.function.Consumer; |
| 26 | 25 | ||
| 27 | -import static cn.hutool.core.bean.BeanUtil.getFieldValue; | ||
| 28 | import static cn.hutool.core.util.RandomUtil.randomEle; | 26 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| 29 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 30 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 27 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 31 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 28 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 32 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 29 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 30 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 33 | import static org.junit.jupiter.api.Assertions.*; | 31 | import static org.junit.jupiter.api.Assertions.*; |
| 34 | import static org.mockito.Mockito.times; | 32 | import static org.mockito.Mockito.times; |
| 35 | import static org.mockito.Mockito.verify; | 33 | import static org.mockito.Mockito.verify; |
| @@ -56,8 +54,7 @@ public class DeptServiceTest extends BaseDbUnitTest { | @@ -56,8 +54,7 @@ public class DeptServiceTest extends BaseDbUnitTest { | ||
| 56 | } | 54 | } |
| 57 | 55 | ||
| 58 | @Test | 56 | @Test |
| 59 | - @SuppressWarnings("unchecked") | ||
| 60 | - void testInitLocalCache() { | 57 | + public void testInitLocalCache() { |
| 61 | // mock 数据 | 58 | // mock 数据 |
| 62 | DeptDO deptDO1 = randomDeptDO(); | 59 | DeptDO deptDO1 = randomDeptDO(); |
| 63 | deptMapper.insert(deptDO1); | 60 | deptMapper.insert(deptDO1); |
| @@ -67,18 +64,15 @@ public class DeptServiceTest extends BaseDbUnitTest { | @@ -67,18 +64,15 @@ public class DeptServiceTest extends BaseDbUnitTest { | ||
| 67 | // 调用 | 64 | // 调用 |
| 68 | deptService.initLocalCache(); | 65 | deptService.initLocalCache(); |
| 69 | // 断言 deptCache 缓存 | 66 | // 断言 deptCache 缓存 |
| 70 | - Map<Long, DeptDO> deptCache = (Map<Long, DeptDO>) getFieldValue(deptService, "deptCache"); | 67 | + Map<Long, DeptDO> deptCache = deptService.getDeptCache(); |
| 71 | assertEquals(2, deptCache.size()); | 68 | assertEquals(2, deptCache.size()); |
| 72 | assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId())); | 69 | assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId())); |
| 73 | assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId())); | 70 | assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId())); |
| 74 | // 断言 parentDeptCache 缓存 | 71 | // 断言 parentDeptCache 缓存 |
| 75 | - Multimap<Long, DeptDO> parentDeptCache = (Multimap<Long, DeptDO>) getFieldValue(deptService, "parentDeptCache"); | 72 | + Multimap<Long, DeptDO> parentDeptCache = deptService.getParentDeptCache(); |
| 76 | assertEquals(2, parentDeptCache.size()); | 73 | assertEquals(2, parentDeptCache.size()); |
| 77 | assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId())); | 74 | assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId())); |
| 78 | assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId())); | 75 | assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId())); |
| 79 | - // 断言 maxUpdateTime 缓存 | ||
| 80 | - LocalDateTime maxUpdateTime = (LocalDateTime) getFieldValue(deptService, "maxUpdateTime"); | ||
| 81 | - assertEquals(ObjectUtils.max(deptDO1.getUpdateTime(), deptDO2.getUpdateTime()), maxUpdateTime); | ||
| 82 | } | 76 | } |
| 83 | 77 | ||
| 84 | @Test | 78 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImplTest.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | ||
| 10 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; | ||
| 11 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 12 | +import org.junit.jupiter.api.Test; | ||
| 13 | +import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 14 | +import org.springframework.context.annotation.Import; | ||
| 15 | + | ||
| 16 | +import javax.annotation.Resource; | ||
| 17 | + | ||
| 18 | +import java.util.Map; | ||
| 19 | + | ||
| 20 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | ||
| 21 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | ||
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | ||
| 24 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_NOT_EXISTS; | ||
| 25 | +import static org.junit.jupiter.api.Assertions.*; | ||
| 26 | +import static org.mockito.Mockito.verify; | ||
| 27 | + | ||
| 28 | +/** | ||
| 29 | +* {@link MailAccountServiceImpl} 的单元测试类 | ||
| 30 | +* | ||
| 31 | +* @author 芋道源码 | ||
| 32 | +*/ | ||
| 33 | +@Import(MailAccountServiceImpl.class) | ||
| 34 | +public class MailAccountServiceImplTest extends BaseDbUnitTest { | ||
| 35 | + | ||
| 36 | + @Resource | ||
| 37 | + private MailAccountServiceImpl mailAccountService; | ||
| 38 | + | ||
| 39 | + @Resource | ||
| 40 | + private MailAccountMapper mailAccountMapper; | ||
| 41 | + | ||
| 42 | + @MockBean | ||
| 43 | + private MailTemplateService mailTemplateService; | ||
| 44 | + @MockBean | ||
| 45 | + private MailProducer mailProducer; | ||
| 46 | + | ||
| 47 | + @Test | ||
| 48 | + public void testInitLocalCache() { | ||
| 49 | + MailAccountDO accountDO1 = randomPojo(MailAccountDO.class); | ||
| 50 | + mailAccountMapper.insert(accountDO1); | ||
| 51 | + MailAccountDO accountDO02 = randomPojo(MailAccountDO.class); | ||
| 52 | + mailAccountMapper.insert(accountDO02); | ||
| 53 | + | ||
| 54 | + // 调用 | ||
| 55 | + mailAccountService.initLocalCache(); | ||
| 56 | + // 断言 mailAccountCache 缓存 | ||
| 57 | + Map<Long, MailAccountDO> mailAccountCache = mailAccountService.getMailAccountCache(); | ||
| 58 | + assertPojoEquals(accountDO1, mailAccountCache.get(accountDO1.getId())); | ||
| 59 | + assertPojoEquals(accountDO02, mailAccountCache.get(accountDO02.getId())); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @Test | ||
| 63 | + public void testCreateMailAccount_success() { | ||
| 64 | + // 准备参数 | ||
| 65 | + MailAccountCreateReqVO reqVO = randomPojo(MailAccountCreateReqVO.class, o -> o.setMail(randomEmail())); | ||
| 66 | + | ||
| 67 | + // 调用 | ||
| 68 | + Long mailAccountId = mailAccountService.createMailAccount(reqVO); | ||
| 69 | + // 断言 | ||
| 70 | + assertNotNull(mailAccountId); | ||
| 71 | + // 校验记录的属性是否正确 | ||
| 72 | + MailAccountDO mailAccount = mailAccountMapper.selectById(mailAccountId); | ||
| 73 | + assertPojoEquals(reqVO, mailAccount); | ||
| 74 | + verify(mailProducer).sendMailAccountRefreshMessage(); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Test | ||
| 78 | + public void testUpdateMailAccount_success() { | ||
| 79 | + // mock 数据 | ||
| 80 | + MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class); | ||
| 81 | + mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据 | ||
| 82 | + // 准备参数 | ||
| 83 | + MailAccountUpdateReqVO reqVO = randomPojo(MailAccountUpdateReqVO.class, o -> { | ||
| 84 | + o.setId(dbMailAccount.getId()); // 设置更新的 ID | ||
| 85 | + o.setMail(randomEmail()); | ||
| 86 | + }); | ||
| 87 | + | ||
| 88 | + // 调用 | ||
| 89 | + mailAccountService.updateMailAccount(reqVO); | ||
| 90 | + // 校验是否更新正确 | ||
| 91 | + MailAccountDO mailAccount = mailAccountMapper.selectById(reqVO.getId()); // 获取最新的 | ||
| 92 | + assertPojoEquals(reqVO, mailAccount); | ||
| 93 | + verify(mailProducer).sendMailAccountRefreshMessage(); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + @Test | ||
| 97 | + public void testUpdateMailAccount_notExists() { | ||
| 98 | + // 准备参数 | ||
| 99 | + MailAccountUpdateReqVO reqVO = randomPojo(MailAccountUpdateReqVO.class); | ||
| 100 | + | ||
| 101 | + // 调用, 并断言异常 | ||
| 102 | + assertServiceException(() -> mailAccountService.updateMailAccount(reqVO), MAIL_ACCOUNT_NOT_EXISTS); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + @Test | ||
| 106 | + public void testDeleteMailAccount_success() { | ||
| 107 | + // mock 数据 | ||
| 108 | + MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class); | ||
| 109 | + mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据 | ||
| 110 | + // 准备参数 | ||
| 111 | + Long id = dbMailAccount.getId(); | ||
| 112 | + | ||
| 113 | + // 调用 | ||
| 114 | + mailAccountService.deleteMailAccount(id); | ||
| 115 | + // 校验数据不存在了 | ||
| 116 | + assertNull(mailAccountMapper.selectById(id)); | ||
| 117 | + verify(mailProducer).sendMailAccountRefreshMessage(); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + @Test | ||
| 121 | + public void testDeleteMailAccount_notExists() { | ||
| 122 | + // 准备参数 | ||
| 123 | + Long id = randomLongId(); | ||
| 124 | + | ||
| 125 | + // 调用, 并断言异常 | ||
| 126 | + assertServiceException(() -> mailAccountService.deleteMailAccount(id), MAIL_ACCOUNT_NOT_EXISTS); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + @Test | ||
| 130 | + public void testGetMailAccountPage() { | ||
| 131 | + // mock 数据 | ||
| 132 | + MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class, o -> { // 等会查询到 | ||
| 133 | + o.setMail("768@qq.com"); | ||
| 134 | + o.setUsername("yunai"); | ||
| 135 | + }); | ||
| 136 | + mailAccountMapper.insert(dbMailAccount); | ||
| 137 | + // 测试 mail 不匹配 | ||
| 138 | + mailAccountMapper.insert(cloneIgnoreId(dbMailAccount, o -> o.setMail("788@qq.com"))); | ||
| 139 | + // 测试 username 不匹配 | ||
| 140 | + mailAccountMapper.insert(cloneIgnoreId(dbMailAccount, o -> o.setUsername("tudou"))); | ||
| 141 | + // 准备参数 | ||
| 142 | + MailAccountPageReqVO reqVO = new MailAccountPageReqVO(); | ||
| 143 | + reqVO.setMail("768"); | ||
| 144 | + reqVO.setUsername("yu"); | ||
| 145 | + | ||
| 146 | + // 调用 | ||
| 147 | + PageResult<MailAccountDO> pageResult = mailAccountService.getMailAccountPage(reqVO); | ||
| 148 | + // 断言 | ||
| 149 | + assertEquals(1, pageResult.getTotal()); | ||
| 150 | + assertEquals(1, pageResult.getList().size()); | ||
| 151 | + assertPojoEquals(dbMailAccount, pageResult.getList().get(0)); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | +} |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImplTest.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.map.MapUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | ||
| 10 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 11 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper; | ||
| 12 | +import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | ||
| 13 | +import org.junit.jupiter.api.Test; | ||
| 14 | +import org.springframework.context.annotation.Import; | ||
| 15 | + | ||
| 16 | +import javax.annotation.Resource; | ||
| 17 | +import java.util.Map; | ||
| 18 | + | ||
| 19 | +import static cn.hutool.core.util.RandomUtil.randomEle; | ||
| 20 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; | ||
| 21 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | ||
| 22 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | ||
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | ||
| 24 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | ||
| 25 | +import static org.junit.jupiter.api.Assertions.*; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | +* {@link MailLogServiceImpl} 的单元测试类 | ||
| 29 | +* | ||
| 30 | +* @author 芋道源码 | ||
| 31 | +*/ | ||
| 32 | +@Import(MailLogServiceImpl.class) | ||
| 33 | +public class MailLogServiceImplTest extends BaseDbUnitTest { | ||
| 34 | + | ||
| 35 | + @Resource | ||
| 36 | + private MailLogServiceImpl mailLogService; | ||
| 37 | + | ||
| 38 | + @Resource | ||
| 39 | + private MailLogMapper mailLogMapper; | ||
| 40 | + | ||
| 41 | + @Test | ||
| 42 | + public void testCreateMailLog() { | ||
| 43 | + // 准备参数 | ||
| 44 | + Long userId = randomLongId(); | ||
| 45 | + Integer userType = randomEle(UserTypeEnum.values()).getValue(); | ||
| 46 | + String toMail = randomEmail(); | ||
| 47 | + MailAccountDO account = randomPojo(MailAccountDO.class); | ||
| 48 | + MailTemplateDO template = randomPojo(MailTemplateDO.class); | ||
| 49 | + String templateContent = randomString(); | ||
| 50 | + Map<String, Object> templateParams = randomTemplateParams(); | ||
| 51 | + Boolean isSend = true; | ||
| 52 | + // mock 方法 | ||
| 53 | + | ||
| 54 | + // 调用 | ||
| 55 | + Long logId = mailLogService.createMailLog(userId, userType, toMail, account, template, templateContent, templateParams, isSend); | ||
| 56 | + // 断言 | ||
| 57 | + MailLogDO log = mailLogMapper.selectById(logId); | ||
| 58 | + assertNotNull(log); | ||
| 59 | + assertEquals(MailSendStatusEnum.INIT.getStatus(), log.getSendStatus()); | ||
| 60 | + assertEquals(userId, log.getUserId()); | ||
| 61 | + assertEquals(userType, log.getUserType()); | ||
| 62 | + assertEquals(toMail, log.getToMail()); | ||
| 63 | + assertEquals(account.getId(), log.getAccountId()); | ||
| 64 | + assertEquals(account.getMail(), log.getFromMail()); | ||
| 65 | + assertEquals(template.getId(), log.getTemplateId()); | ||
| 66 | + assertEquals(template.getCode(), log.getTemplateCode()); | ||
| 67 | + assertEquals(template.getNickname(), log.getTemplateNickname()); | ||
| 68 | + assertEquals(template.getTitle(), log.getTemplateTitle()); | ||
| 69 | + assertEquals(templateContent, log.getTemplateContent()); | ||
| 70 | + assertEquals(templateParams, log.getTemplateParams()); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + @Test | ||
| 74 | + public void testUpdateMailSendResult_success() { | ||
| 75 | + // mock 数据 | ||
| 76 | + MailLogDO log = randomPojo(MailLogDO.class, o -> { | ||
| 77 | + o.setSendStatus(MailSendStatusEnum.INIT.getStatus()); | ||
| 78 | + o.setSendTime(null).setSendMessageId(null).setSendException(null) | ||
| 79 | + .setTemplateParams(randomTemplateParams()); | ||
| 80 | + }); | ||
| 81 | + mailLogMapper.insert(log); | ||
| 82 | + // 准备参数 | ||
| 83 | + Long logId = log.getId(); | ||
| 84 | + String messageId = randomString(); | ||
| 85 | + | ||
| 86 | + // 调用 | ||
| 87 | + mailLogService.updateMailSendResult(logId, messageId, null); | ||
| 88 | + // 断言 | ||
| 89 | + MailLogDO dbLog = mailLogMapper.selectById(logId); | ||
| 90 | + assertEquals(MailSendStatusEnum.SUCCESS.getStatus(), dbLog.getSendStatus()); | ||
| 91 | + assertNotNull(dbLog.getSendTime()); | ||
| 92 | + assertEquals(messageId, dbLog.getSendMessageId()); | ||
| 93 | + assertNull(dbLog.getSendException()); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + @Test | ||
| 97 | + public void testUpdateMailSendResult_exception() { | ||
| 98 | + // mock 数据 | ||
| 99 | + MailLogDO log = randomPojo(MailLogDO.class, o -> { | ||
| 100 | + o.setSendStatus(MailSendStatusEnum.INIT.getStatus()); | ||
| 101 | + o.setSendTime(null).setSendMessageId(null).setSendException(null) | ||
| 102 | + .setTemplateParams(randomTemplateParams()); | ||
| 103 | + }); | ||
| 104 | + mailLogMapper.insert(log); | ||
| 105 | + // 准备参数 | ||
| 106 | + Long logId = log.getId(); | ||
| 107 | + Exception exception = new NullPointerException("测试异常"); | ||
| 108 | + | ||
| 109 | + // 调用 | ||
| 110 | + mailLogService.updateMailSendResult(logId, null, exception); | ||
| 111 | + // 断言 | ||
| 112 | + MailLogDO dbLog = mailLogMapper.selectById(logId); | ||
| 113 | + assertEquals(MailSendStatusEnum.FAILURE.getStatus(), dbLog.getSendStatus()); | ||
| 114 | + assertNotNull(dbLog.getSendTime()); | ||
| 115 | + assertNull(dbLog.getSendMessageId()); | ||
| 116 | + assertEquals("NullPointerException: 测试异常", dbLog.getSendException()); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + @Test | ||
| 120 | + public void testGetMailLogPage() { | ||
| 121 | + // mock 数据 | ||
| 122 | + MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> { // 等会查询到 | ||
| 123 | + o.setUserId(1L); | ||
| 124 | + o.setUserType(UserTypeEnum.ADMIN.getValue()); | ||
| 125 | + o.setToMail("768@qq.com"); | ||
| 126 | + o.setAccountId(10L); | ||
| 127 | + o.setTemplateId(100L); | ||
| 128 | + o.setSendStatus(MailSendStatusEnum.INIT.getStatus()); | ||
| 129 | + o.setSendTime(buildTime(2023, 2, 10)); | ||
| 130 | + o.setTemplateParams(randomTemplateParams()); | ||
| 131 | + }); | ||
| 132 | + mailLogMapper.insert(dbMailLog); | ||
| 133 | + // 测试 userId 不匹配 | ||
| 134 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserId(2L))); | ||
| 135 | + // 测试 userType 不匹配 | ||
| 136 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserType(UserTypeEnum.MEMBER.getValue()))); | ||
| 137 | + // 测试 toMail 不匹配 | ||
| 138 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setToMail("788@.qq.com"))); | ||
| 139 | + // 测试 accountId 不匹配 | ||
| 140 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setAccountId(11L))); | ||
| 141 | + // 测试 templateId 不匹配 | ||
| 142 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setTemplateId(101L))); | ||
| 143 | + // 测试 sendStatus 不匹配 | ||
| 144 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendStatus(MailSendStatusEnum.SUCCESS.getStatus()))); | ||
| 145 | + // 测试 sendTime 不匹配 | ||
| 146 | + mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendTime(buildTime(2023, 3, 10)))); | ||
| 147 | + // 准备参数 | ||
| 148 | + MailLogPageReqVO reqVO = new MailLogPageReqVO(); | ||
| 149 | + reqVO.setUserId(1L); | ||
| 150 | + reqVO.setUserType(UserTypeEnum.ADMIN.getValue()); | ||
| 151 | + reqVO.setToMail("768"); | ||
| 152 | + reqVO.setAccountId(10L); | ||
| 153 | + reqVO.setTemplateId(100L); | ||
| 154 | + reqVO.setSendStatus(MailSendStatusEnum.INIT.getStatus()); | ||
| 155 | + reqVO.setSendTime((buildBetweenTime(2023, 2, 1, 2023, 2, 15))); | ||
| 156 | + | ||
| 157 | + // 调用 | ||
| 158 | + PageResult<MailLogDO> pageResult = mailLogService.getMailLogPage(reqVO); | ||
| 159 | + // 断言 | ||
| 160 | + assertEquals(1, pageResult.getTotal()); | ||
| 161 | + assertEquals(1, pageResult.getList().size()); | ||
| 162 | + assertPojoEquals(dbMailLog, pageResult.getList().get(0)); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + private static Map<String, Object> randomTemplateParams() { | ||
| 166 | + return MapUtil.<String, Object>builder().put(randomString(), randomString()) | ||
| 167 | + .put(randomString(), randomString()).build(); | ||
| 168 | + } | ||
| 169 | +} |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.map.MapUtil; | ||
| 4 | +import cn.hutool.extra.mail.MailAccount; | ||
| 5 | +import cn.hutool.extra.mail.MailUtil; | ||
| 6 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 7 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 8 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 10 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 11 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 12 | +import org.assertj.core.util.Lists; | ||
| 13 | +import org.junit.jupiter.api.Disabled; | ||
| 14 | +import org.junit.jupiter.api.Test; | ||
| 15 | +import org.mockito.InjectMocks; | ||
| 16 | +import org.mockito.Mock; | ||
| 17 | + | ||
| 18 | +import java.util.HashMap; | ||
| 19 | +import java.util.Map; | ||
| 20 | + | ||
| 21 | +import static cn.hutool.core.util.RandomUtil.randomEle; | ||
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | ||
| 24 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 25 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 26 | +import static org.mockito.ArgumentMatchers.eq; | ||
| 27 | +import static org.mockito.Mockito.*; | ||
| 28 | + | ||
| 29 | +class MailSendServiceImplTest extends BaseMockitoUnitTest { | ||
| 30 | + | ||
| 31 | + @InjectMocks | ||
| 32 | + private MailSendServiceImpl mailSendService; | ||
| 33 | + | ||
| 34 | + @Mock | ||
| 35 | + private MailAccountService mailAccountService; | ||
| 36 | + @Mock | ||
| 37 | + private MailTemplateService mailTemplateService; | ||
| 38 | + @Mock | ||
| 39 | + private MailLogService mailLogService; | ||
| 40 | + @Mock | ||
| 41 | + private MailProducer mailProducer; | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 用于快速测试你的邮箱账号是否正常 | ||
| 45 | + */ | ||
| 46 | + @Test | ||
| 47 | + @Disabled | ||
| 48 | + public void testDemo() { | ||
| 49 | + MailAccount mailAccount = new MailAccount() | ||
| 50 | +// .setFrom("奥特曼 <ydym_test@163.com>") | ||
| 51 | + .setFrom("ydym_test@163.com") // 邮箱地址 | ||
| 52 | + .setHost("smtp.163.com").setPort(465).setSslEnable(true) // SMTP 服务器 | ||
| 53 | + .setAuth(true).setUser("ydym_test@163.com").setPass("WBZTEINMIFVRYSOE"); // 登录账号密码 | ||
| 54 | + String messageId = MailUtil.send(mailAccount, "7685413@qq.com", "主题", "内容", false); | ||
| 55 | + System.out.println("发送结果:" + messageId); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 发送成功,当短信模板开启时 | ||
| 60 | + */ | ||
| 61 | + @Test | ||
| 62 | + public void testSendSingleMail_successWhenMailTemplateEnable() { | ||
| 63 | + // 准备参数 | ||
| 64 | + String mail = randomEmail(); | ||
| 65 | + Long userId = randomLongId(); | ||
| 66 | + Integer userType = randomEle(UserTypeEnum.values()).getValue(); | ||
| 67 | + String templateCode = randomString(); | ||
| 68 | + Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | ||
| 69 | + .put("op", "login").build(); | ||
| 70 | + // mock MailTemplateService 的方法 | ||
| 71 | + MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { | ||
| 72 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 73 | + o.setContent("验证码为{code}, 操作为{op}"); | ||
| 74 | + o.setParams(Lists.newArrayList("code", "op")); | ||
| 75 | + }); | ||
| 76 | + when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); | ||
| 77 | + String content = randomString(); | ||
| 78 | + when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams))) | ||
| 79 | + .thenReturn(content); | ||
| 80 | + // mock MailAccountService 的方法 | ||
| 81 | + MailAccountDO account = randomPojo(MailAccountDO.class); | ||
| 82 | + when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | ||
| 83 | + // mock MailLogService 的方法 | ||
| 84 | + Long mailLogId = randomLongId(); | ||
| 85 | + when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail), | ||
| 86 | + eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); | ||
| 87 | + | ||
| 88 | + // 调用 | ||
| 89 | + Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams); | ||
| 90 | + // 断言 | ||
| 91 | + assertEquals(mailLogId, resultMailLogId); | ||
| 92 | + // 断言调用 | ||
| 93 | + verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail), | ||
| 94 | + eq(account.getId()), eq(template.getNickname()), eq(template.getTitle()), eq(content)); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + /** | ||
| 98 | + * 发送成功,当短信模板关闭时 | ||
| 99 | + */ | ||
| 100 | + @Test | ||
| 101 | + public void testSendSingleMail_successWhenSmsTemplateDisable() { | ||
| 102 | + // 准备参数 | ||
| 103 | + String mail = randomEmail(); | ||
| 104 | + Long userId = randomLongId(); | ||
| 105 | + Integer userType = randomEle(UserTypeEnum.values()).getValue(); | ||
| 106 | + String templateCode = randomString(); | ||
| 107 | + Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234") | ||
| 108 | + .put("op", "login").build(); | ||
| 109 | + // mock MailTemplateService 的方法 | ||
| 110 | + MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> { | ||
| 111 | + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); | ||
| 112 | + o.setContent("验证码为{code}, 操作为{op}"); | ||
| 113 | + o.setParams(Lists.newArrayList("code", "op")); | ||
| 114 | + }); | ||
| 115 | + when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); | ||
| 116 | + String content = randomString(); | ||
| 117 | + when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams))) | ||
| 118 | + .thenReturn(content); | ||
| 119 | + // mock MailAccountService 的方法 | ||
| 120 | + MailAccountDO account = randomPojo(MailAccountDO.class); | ||
| 121 | + when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account); | ||
| 122 | + // mock MailLogService 的方法 | ||
| 123 | + Long mailLogId = randomLongId(); | ||
| 124 | + when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail), | ||
| 125 | + eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId); | ||
| 126 | + | ||
| 127 | + // 调用 | ||
| 128 | + Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams); | ||
| 129 | + // 断言 | ||
| 130 | + assertEquals(mailLogId, resultMailLogId); | ||
| 131 | + // 断言调用 | ||
| 132 | + verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), anyString(), | ||
| 133 | + anyLong(), anyString(), anyString(), anyString()); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + @Test | ||
| 137 | + public void testCheckMailTemplateValid_notExists() { | ||
| 138 | + // 准备参数 | ||
| 139 | + String templateCode = randomString(); | ||
| 140 | + // mock 方法 | ||
| 141 | + | ||
| 142 | + // 调用,并断言异常 | ||
| 143 | + assertServiceException(() -> mailSendService.checkMailTemplateValid(templateCode), | ||
| 144 | + MAIL_TEMPLATE_NOT_EXISTS); | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + @Test | ||
| 148 | + public void testBuildTemplateParams_paramMiss() { | ||
| 149 | + // 准备参数 | ||
| 150 | + MailTemplateDO template = randomPojo(MailTemplateDO.class, | ||
| 151 | + o -> o.setParams(Lists.newArrayList("code"))); | ||
| 152 | + Map<String, Object> templateParams = new HashMap<>(); | ||
| 153 | + // mock 方法 | ||
| 154 | + | ||
| 155 | + // 调用,并断言异常 | ||
| 156 | + assertServiceException(() -> mailSendService.buildTemplateParams(template, templateParams), | ||
| 157 | + MAIL_SEND_TEMPLATE_PARAM_MISS, "code"); | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + @Test | ||
| 161 | + public void testCheckMail_notExists() { | ||
| 162 | + // 准备参数 | ||
| 163 | + // mock 方法 | ||
| 164 | + | ||
| 165 | + // 调用,并断言异常 | ||
| 166 | + assertServiceException(() -> mailSendService.checkMail(null), | ||
| 167 | + MAIL_SEND_MAIL_NOT_EXISTS); | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | +} |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 10 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 11 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; | ||
| 12 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 13 | +import org.junit.jupiter.api.Test; | ||
| 14 | +import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 15 | +import org.springframework.context.annotation.Import; | ||
| 16 | + | ||
| 17 | +import javax.annotation.Resource; | ||
| 18 | + | ||
| 19 | +import java.util.Map; | ||
| 20 | + | ||
| 21 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | ||
| 22 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | ||
| 23 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | ||
| 24 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | ||
| 25 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||
| 26 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | ||
| 27 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 28 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS; | ||
| 29 | +import static org.junit.jupiter.api.Assertions.*; | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | +* {@link MailTemplateServiceImpl} 的单元测试类 | ||
| 33 | +* | ||
| 34 | +* @author 芋道源码 | ||
| 35 | +*/ | ||
| 36 | +@Import(MailTemplateServiceImpl.class) | ||
| 37 | +public class MailTemplateServiceImplTest extends BaseDbUnitTest { | ||
| 38 | + | ||
| 39 | + @Resource | ||
| 40 | + private MailTemplateServiceImpl mailTemplateService; | ||
| 41 | + | ||
| 42 | + @Resource | ||
| 43 | + private MailTemplateMapper mailTemplateMapper; | ||
| 44 | + | ||
| 45 | + @MockBean | ||
| 46 | + private MailProducer mailProducer; | ||
| 47 | + | ||
| 48 | + @Test | ||
| 49 | + public void testInitLocalCache() { | ||
| 50 | + MailTemplateDO templateDO01 = randomPojo(MailTemplateDO.class); | ||
| 51 | + mailTemplateMapper.insert(templateDO01); | ||
| 52 | + MailTemplateDO templateDO02 = randomPojo(MailTemplateDO.class); | ||
| 53 | + mailTemplateMapper.insert(templateDO02); | ||
| 54 | + | ||
| 55 | + // 调用 | ||
| 56 | + mailTemplateService.initLocalCache(); | ||
| 57 | + // 断言 mailTemplateCache 缓存 | ||
| 58 | + Map<String, MailTemplateDO> mailTemplateCache = mailTemplateService.getMailTemplateCache(); | ||
| 59 | + assertPojoEquals(templateDO01, mailTemplateCache.get(templateDO01.getCode())); | ||
| 60 | + assertPojoEquals(templateDO02, mailTemplateCache.get(templateDO02.getCode())); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + @Test | ||
| 64 | + public void testCreateMailTemplate_success() { | ||
| 65 | + // 准备参数 | ||
| 66 | + MailTemplateCreateReqVO reqVO = randomPojo(MailTemplateCreateReqVO.class); | ||
| 67 | + | ||
| 68 | + // 调用 | ||
| 69 | + Long mailTemplateId = mailTemplateService.createMailTemplate(reqVO); | ||
| 70 | + // 断言 | ||
| 71 | + assertNotNull(mailTemplateId); | ||
| 72 | + // 校验记录的属性是否正确 | ||
| 73 | + MailTemplateDO mailTemplate = mailTemplateMapper.selectById(mailTemplateId); | ||
| 74 | + assertPojoEquals(reqVO, mailTemplate); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Test | ||
| 78 | + public void testUpdateMailTemplate_success() { | ||
| 79 | + // mock 数据 | ||
| 80 | + MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class); | ||
| 81 | + mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据 | ||
| 82 | + // 准备参数 | ||
| 83 | + MailTemplateUpdateReqVO reqVO = randomPojo(MailTemplateUpdateReqVO.class, o -> { | ||
| 84 | + o.setId(dbMailTemplate.getId()); // 设置更新的 ID | ||
| 85 | + }); | ||
| 86 | + | ||
| 87 | + // 调用 | ||
| 88 | + mailTemplateService.updateMailTemplate(reqVO); | ||
| 89 | + // 校验是否更新正确 | ||
| 90 | + MailTemplateDO mailTemplate = mailTemplateMapper.selectById(reqVO.getId()); // 获取最新的 | ||
| 91 | + assertPojoEquals(reqVO, mailTemplate); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Test | ||
| 95 | + public void testUpdateMailTemplate_notExists() { | ||
| 96 | + // 准备参数 | ||
| 97 | + MailTemplateUpdateReqVO reqVO = randomPojo(MailTemplateUpdateReqVO.class); | ||
| 98 | + | ||
| 99 | + // 调用, 并断言异常 | ||
| 100 | + assertServiceException(() -> mailTemplateService.updateMailTemplate(reqVO), MAIL_TEMPLATE_NOT_EXISTS); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @Test | ||
| 104 | + public void testDeleteMailTemplate_success() { | ||
| 105 | + // mock 数据 | ||
| 106 | + MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class); | ||
| 107 | + mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据 | ||
| 108 | + // 准备参数 | ||
| 109 | + Long id = dbMailTemplate.getId(); | ||
| 110 | + | ||
| 111 | + // 调用 | ||
| 112 | + mailTemplateService.deleteMailTemplate(id); | ||
| 113 | + // 校验数据不存在了 | ||
| 114 | + assertNull(mailTemplateMapper.selectById(id)); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + @Test | ||
| 118 | + public void testDeleteMailTemplate_notExists() { | ||
| 119 | + // 准备参数 | ||
| 120 | + Long id = randomLongId(); | ||
| 121 | + | ||
| 122 | + // 调用, 并断言异常 | ||
| 123 | + assertServiceException(() -> mailTemplateService.deleteMailTemplate(id), MAIL_TEMPLATE_NOT_EXISTS); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + @Test | ||
| 127 | + public void testGetMailTemplatePage() { | ||
| 128 | + // mock 数据 | ||
| 129 | + MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class, o -> { // 等会查询到 | ||
| 130 | + o.setName("源码"); | ||
| 131 | + o.setCode("test_01"); | ||
| 132 | + o.setAccountId(1L); | ||
| 133 | + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 134 | + o.setCreateTime(buildTime(2023, 2, 3)); | ||
| 135 | + }); | ||
| 136 | + mailTemplateMapper.insert(dbMailTemplate); | ||
| 137 | + // 测试 name 不匹配 | ||
| 138 | + mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setName("芋道"))); | ||
| 139 | + // 测试 code 不匹配 | ||
| 140 | + mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setCode("test_02"))); | ||
| 141 | + // 测试 accountId 不匹配 | ||
| 142 | + mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setAccountId(2L))); | ||
| 143 | + // 测试 status 不匹配 | ||
| 144 | + mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); | ||
| 145 | + // 测试 createTime 不匹配 | ||
| 146 | + mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setCreateTime(buildTime(2023, 1, 5)))); | ||
| 147 | + // 准备参数 | ||
| 148 | + MailTemplatePageReqVO reqVO = new MailTemplatePageReqVO(); | ||
| 149 | + reqVO.setName("源"); | ||
| 150 | + reqVO.setCode("est_01"); | ||
| 151 | + reqVO.setAccountId(1L); | ||
| 152 | + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 153 | + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 5)); | ||
| 154 | + | ||
| 155 | + // 调用 | ||
| 156 | + PageResult<MailTemplateDO> pageResult = mailTemplateService.getMailTemplatePage(reqVO); | ||
| 157 | + // 断言 | ||
| 158 | + assertEquals(1, pageResult.getTotal()); | ||
| 159 | + assertEquals(1, pageResult.getList().size()); | ||
| 160 | + assertPojoEquals(dbMailTemplate, pageResult.getList().get(0)); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | +} |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java
| @@ -19,7 +19,6 @@ import java.util.Collections; | @@ -19,7 +19,6 @@ import java.util.Collections; | ||
| 19 | import java.util.Map; | 19 | import java.util.Map; |
| 20 | 20 | ||
| 21 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 21 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 22 | -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; | ||
| 23 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 22 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 24 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 23 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 25 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 24 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| @@ -59,8 +58,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { | @@ -59,8 +58,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { | ||
| 59 | assertEquals(2, clientCache.size()); | 58 | assertEquals(2, clientCache.size()); |
| 60 | assertPojoEquals(clientDO1, clientCache.get(clientDO1.getClientId())); | 59 | assertPojoEquals(clientDO1, clientCache.get(clientDO1.getClientId())); |
| 61 | assertPojoEquals(clientDO2, clientCache.get(clientDO2.getClientId())); | 60 | assertPojoEquals(clientDO2, clientCache.get(clientDO2.getClientId())); |
| 62 | - // 断言 maxUpdateTime 缓存 | ||
| 63 | - assertEquals(max(clientDO1.getUpdateTime(), clientDO2.getUpdateTime()), oauth2ClientService.getMaxUpdateTime()); | ||
| 64 | } | 61 | } |
| 65 | 62 | ||
| 66 | @Test | 63 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceTest.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.permission; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.permission; | ||
| 3 | import cn.hutool.core.bean.BeanUtil; | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | import cn.hutool.core.lang.Assert; | 4 | import cn.hutool.core.lang.Assert; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.spring.SpringAopUtils; | 6 | import cn.iocoder.yudao.framework.common.util.spring.SpringAopUtils; |
| 8 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 7 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 9 | import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; |
| @@ -20,7 +19,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; | @@ -20,7 +19,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 20 | import org.springframework.context.annotation.Import; | 19 | import org.springframework.context.annotation.Import; |
| 21 | 20 | ||
| 22 | import javax.annotation.Resource; | 21 | import javax.annotation.Resource; |
| 23 | -import java.time.LocalDateTime; | ||
| 24 | import java.util.*; | 22 | import java.util.*; |
| 25 | 23 | ||
| 26 | import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | 24 | import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; |
| @@ -51,32 +49,24 @@ public class MenuServiceTest extends BaseDbUnitTest { | @@ -51,32 +49,24 @@ public class MenuServiceTest extends BaseDbUnitTest { | ||
| 51 | private TenantService tenantService; | 49 | private TenantService tenantService; |
| 52 | 50 | ||
| 53 | @Test | 51 | @Test |
| 54 | - public void testInitLocalCache_success() throws Exception { | ||
| 55 | - MenuDO menuDO1 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L); | 52 | + public void testInitLocalCache_success() { |
| 53 | + MenuDO menuDO1 = randomPojo(MenuDO.class); | ||
| 56 | menuMapper.insert(menuDO1); | 54 | menuMapper.insert(menuDO1); |
| 57 | - MenuDO menuDO2 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L); | 55 | + MenuDO menuDO2 = randomPojo(MenuDO.class); |
| 58 | menuMapper.insert(menuDO2); | 56 | menuMapper.insert(menuDO2); |
| 59 | 57 | ||
| 60 | // 调用 | 58 | // 调用 |
| 61 | menuService.initLocalCache(); | 59 | menuService.initLocalCache(); |
| 62 | - | ||
| 63 | - // 获取代理对象 | ||
| 64 | - MenuServiceImpl target = (MenuServiceImpl) SpringAopUtils.getTarget(menuService); | ||
| 65 | - | ||
| 66 | - Map<Long, MenuDO> menuCache = | ||
| 67 | - (Map<Long, MenuDO>) BeanUtil.getFieldValue(target, "menuCache"); | 60 | + // 校验 menuCache 缓存 |
| 61 | + Map<Long, MenuDO> menuCache = menuService.getMenuCache(); | ||
| 68 | Assert.isTrue(menuCache.size() == 2); | 62 | Assert.isTrue(menuCache.size() == 2); |
| 69 | assertPojoEquals(menuDO1, menuCache.get(menuDO1.getId())); | 63 | assertPojoEquals(menuDO1, menuCache.get(menuDO1.getId())); |
| 70 | assertPojoEquals(menuDO2, menuCache.get(menuDO2.getId())); | 64 | assertPojoEquals(menuDO2, menuCache.get(menuDO2.getId())); |
| 71 | - | ||
| 72 | - Multimap<String, MenuDO> permissionMenuCache = | ||
| 73 | - (Multimap<String, MenuDO>) BeanUtil.getFieldValue(target, "permissionMenuCache"); | 65 | + // 校验 permissionMenuCache 缓存 |
| 66 | + Multimap<String, MenuDO> permissionMenuCache = menuService.getPermissionMenuCache(); | ||
| 74 | Assert.isTrue(permissionMenuCache.size() == 2); | 67 | Assert.isTrue(permissionMenuCache.size() == 2); |
| 75 | assertPojoEquals(menuDO1, permissionMenuCache.get(menuDO1.getPermission())); | 68 | assertPojoEquals(menuDO1, permissionMenuCache.get(menuDO1.getPermission())); |
| 76 | assertPojoEquals(menuDO2, permissionMenuCache.get(menuDO2.getPermission())); | 69 | assertPojoEquals(menuDO2, permissionMenuCache.get(menuDO2.getPermission())); |
| 77 | - | ||
| 78 | - LocalDateTime maxUpdateTime = (LocalDateTime) BeanUtil.getFieldValue(target, "maxUpdateTime"); | ||
| 79 | - assertEquals(ObjectUtils.max(menuDO1.getUpdateTime(), menuDO2.getUpdateTime()), maxUpdateTime); | ||
| 80 | } | 70 | } |
| 81 | 71 | ||
| 82 | @Test | 72 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
| @@ -3,18 +3,15 @@ package cn.iocoder.yudao.module.system.service.permission; | @@ -3,18 +3,15 @@ package cn.iocoder.yudao.module.system.service.permission; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.map.MapUtil; | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||
| 7 | -import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; | ||
| 8 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 6 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 7 | +import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; | ||
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; |
| 11 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| 12 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; | 11 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; |
| 13 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; |
| 14 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | 13 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 15 | -import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuBatchInsertMapper; | ||
| 16 | import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; | 14 | import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; |
| 17 | -import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleBatchInsertMapper; | ||
| 18 | import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; | 15 | import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; |
| 19 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; | 16 | import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; |
| 20 | import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; | 17 | import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; |
| @@ -27,8 +24,10 @@ import org.springframework.boot.test.mock.mockito.MockBean; | @@ -27,8 +24,10 @@ import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 27 | import org.springframework.context.annotation.Import; | 24 | import org.springframework.context.annotation.Import; |
| 28 | 25 | ||
| 29 | import javax.annotation.Resource; | 26 | import javax.annotation.Resource; |
| 30 | -import java.time.LocalDateTime; | ||
| 31 | -import java.util.*; | 27 | +import java.util.Collection; |
| 28 | +import java.util.List; | ||
| 29 | +import java.util.Map; | ||
| 30 | +import java.util.Set; | ||
| 32 | 31 | ||
| 33 | import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | 32 | import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; |
| 34 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 33 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| @@ -42,8 +41,7 @@ import static org.mockito.ArgumentMatchers.same; | @@ -42,8 +41,7 @@ import static org.mockito.ArgumentMatchers.same; | ||
| 42 | import static org.mockito.Mockito.verify; | 41 | import static org.mockito.Mockito.verify; |
| 43 | import static org.mockito.Mockito.when; | 42 | import static org.mockito.Mockito.when; |
| 44 | 43 | ||
| 45 | -@Import({PermissionServiceImpl.class, | ||
| 46 | - RoleMenuBatchInsertMapper.class, UserRoleBatchInsertMapper.class}) | 44 | +@Import({PermissionServiceImpl.class}) |
| 47 | public class PermissionServiceTest extends BaseDbUnitTest { | 45 | public class PermissionServiceTest extends BaseDbUnitTest { |
| 48 | 46 | ||
| 49 | @Resource | 47 | @Resource |
| @@ -52,11 +50,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { | @@ -52,11 +50,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { | ||
| 52 | @Resource | 50 | @Resource |
| 53 | private RoleMenuMapper roleMenuMapper; | 51 | private RoleMenuMapper roleMenuMapper; |
| 54 | @Resource | 52 | @Resource |
| 55 | - private RoleMenuBatchInsertMapper roleMenuBatchInsertMapper; | ||
| 56 | - @Resource | ||
| 57 | private UserRoleMapper userRoleMapper; | 53 | private UserRoleMapper userRoleMapper; |
| 58 | - @Resource | ||
| 59 | - private UserRoleBatchInsertMapper userRoleBatchInsertMapper; | ||
| 60 | 54 | ||
| 61 | @MockBean | 55 | @MockBean |
| 62 | private RoleService roleService; | 56 | private RoleService roleService; |
| @@ -71,7 +65,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { | @@ -71,7 +65,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { | ||
| 71 | private PermissionProducer permissionProducer; | 65 | private PermissionProducer permissionProducer; |
| 72 | 66 | ||
| 73 | @Test | 67 | @Test |
| 74 | - public void testInitLocalCacheIfUpdateForRoleMenu() { | 68 | + public void testInitLocalCacheForRoleMenu() { |
| 75 | // mock 数据 | 69 | // mock 数据 |
| 76 | RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(10L)); | 70 | RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(10L)); |
| 77 | roleMenuMapper.insert(roleMenuDO01); | 71 | roleMenuMapper.insert(roleMenuDO01); |
| @@ -79,7 +73,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { | @@ -79,7 +73,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { | ||
| 79 | roleMenuMapper.insert(roleMenuDO02); | 73 | roleMenuMapper.insert(roleMenuDO02); |
| 80 | 74 | ||
| 81 | // 调用 | 75 | // 调用 |
| 82 | - permissionService.initLocalCacheIfUpdateForRoleMenu(null); | 76 | + permissionService.initLocalCacheForRoleMenu(); |
| 83 | // 断言 roleMenuCache 缓存 | 77 | // 断言 roleMenuCache 缓存 |
| 84 | assertEquals(1, permissionService.getRoleMenuCache().keySet().size()); | 78 | assertEquals(1, permissionService.getRoleMenuCache().keySet().size()); |
| 85 | assertEquals(asList(10L, 20L), permissionService.getRoleMenuCache().get(1L)); | 79 | assertEquals(asList(10L, 20L), permissionService.getRoleMenuCache().get(1L)); |
| @@ -87,13 +81,10 @@ public class PermissionServiceTest extends BaseDbUnitTest { | @@ -87,13 +81,10 @@ public class PermissionServiceTest extends BaseDbUnitTest { | ||
| 87 | assertEquals(2, permissionService.getMenuRoleCache().size()); | 81 | assertEquals(2, permissionService.getMenuRoleCache().size()); |
| 88 | assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(10L)); | 82 | assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(10L)); |
| 89 | assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(20L)); | 83 | assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(20L)); |
| 90 | - // 断言 maxUpdateTime 缓存 | ||
| 91 | - LocalDateTime maxUpdateTime = permissionService.getRoleMenuMaxUpdateTime(); | ||
| 92 | - assertEquals(ObjectUtils.max(roleMenuDO01.getUpdateTime(), roleMenuDO02.getUpdateTime()), maxUpdateTime); | ||
| 93 | } | 84 | } |
| 94 | 85 | ||
| 95 | @Test | 86 | @Test |
| 96 | - public void testInitLocalCacheIfUpdateForUserRole() { | 87 | + public void testInitLocalCacheForUserRole() { |
| 97 | // mock 数据 | 88 | // mock 数据 |
| 98 | UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L)); | 89 | UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L)); |
| 99 | userRoleMapper.insert(userRoleDO01); | 90 | userRoleMapper.insert(userRoleDO01); |
| @@ -101,13 +92,10 @@ public class PermissionServiceTest extends BaseDbUnitTest { | @@ -101,13 +92,10 @@ public class PermissionServiceTest extends BaseDbUnitTest { | ||
| 101 | userRoleMapper.insert(roleMenuDO02); | 92 | userRoleMapper.insert(roleMenuDO02); |
| 102 | 93 | ||
| 103 | // 调用 | 94 | // 调用 |
| 104 | - permissionService.initLocalCacheIfUpdateForUserRole(null); | 95 | + permissionService.initLocalCacheForUserRole(); |
| 105 | // 断言 roleMenuCache 缓存 | 96 | // 断言 roleMenuCache 缓存 |
| 106 | assertEquals(1, permissionService.getUserRoleCache().size()); | 97 | assertEquals(1, permissionService.getUserRoleCache().size()); |
| 107 | assertEquals(asSet(10L, 20L), permissionService.getUserRoleCache().get(1L)); | 98 | assertEquals(asSet(10L, 20L), permissionService.getUserRoleCache().get(1L)); |
| 108 | - // 断言 maxUpdateTime 缓存 | ||
| 109 | - LocalDateTime maxUpdateTime = permissionService.getUserRoleMaxUpdateTime(); | ||
| 110 | - assertEquals(ObjectUtils.max(userRoleDO01.getUpdateTime(), roleMenuDO02.getUpdateTime()), maxUpdateTime); | ||
| 111 | } | 99 | } |
| 112 | 100 | ||
| 113 | @Test | 101 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java
| @@ -23,7 +23,6 @@ import java.util.*; | @@ -23,7 +23,6 @@ import java.util.*; | ||
| 23 | 23 | ||
| 24 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | 24 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; |
| 25 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 25 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 26 | -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; | ||
| 27 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 26 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 28 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 27 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 29 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 28 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| @@ -59,8 +58,6 @@ public class RoleServiceTest extends BaseDbUnitTest { | @@ -59,8 +58,6 @@ public class RoleServiceTest extends BaseDbUnitTest { | ||
| 59 | Map<Long, RoleDO> roleCache = roleService.getRoleCache(); | 58 | Map<Long, RoleDO> roleCache = roleService.getRoleCache(); |
| 60 | assertPojoEquals(roleDO1, roleCache.get(roleDO1.getId())); | 59 | assertPojoEquals(roleDO1, roleCache.get(roleDO1.getId())); |
| 61 | assertPojoEquals(roleDO2, roleCache.get(roleDO2.getId())); | 60 | assertPojoEquals(roleDO2, roleCache.get(roleDO2.getId())); |
| 62 | - // 断言 maxUpdateTime 缓存 | ||
| 63 | - assertEquals(max(roleDO1.getUpdateTime(), roleDO2.getUpdateTime()), roleService.getMaxUpdateTime()); | ||
| 64 | } | 61 | } |
| 65 | 62 | ||
| 66 | @Test | 63 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java
| @@ -60,8 +60,6 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { | @@ -60,8 +60,6 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { | ||
| 60 | 60 | ||
| 61 | // 调用 | 61 | // 调用 |
| 62 | sensitiveWordService.initLocalCache(); | 62 | sensitiveWordService.initLocalCache(); |
| 63 | - // 断言 maxUpdateTime 缓存 | ||
| 64 | - assertEquals(max(wordDO1.getUpdateTime(), wordDO2.getUpdateTime()), sensitiveWordService.getMaxUpdateTime()); | ||
| 65 | // 断言 sensitiveWordTagsCache 缓存 | 63 | // 断言 sensitiveWordTagsCache 缓存 |
| 66 | assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTags()); | 64 | assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTags()); |
| 67 | // 断言 tagSensitiveWordTries 缓存 | 65 | // 断言 tagSensitiveWordTries 缓存 |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java
| 1 | package cn.iocoder.yudao.module.system.service.sms; | 1 | package cn.iocoder.yudao.module.system.service.sms; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; | ||
| 5 | -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; | ||
| 6 | -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; | ||
| 7 | -import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; | ||
| 8 | -import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; | ||
| 9 | -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | ||
| 10 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 11 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 12 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; | 5 | import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; |
| 13 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 6 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 14 | import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; | 7 | import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; |
| 15 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | 8 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 9 | +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; | ||
| 13 | +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; | ||
| 14 | +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; | ||
| 16 | import org.junit.jupiter.api.Test; | 15 | import org.junit.jupiter.api.Test; |
| 17 | import org.springframework.boot.test.mock.mockito.MockBean; | 16 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 18 | import org.springframework.context.annotation.Import; | 17 | import org.springframework.context.annotation.Import; |
| @@ -22,12 +21,11 @@ import java.time.LocalDateTime; | @@ -22,12 +21,11 @@ import java.time.LocalDateTime; | ||
| 22 | import java.util.function.Consumer; | 21 | import java.util.function.Consumer; |
| 23 | 22 | ||
| 24 | import static cn.hutool.core.util.RandomUtil.randomEle; | 23 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| 25 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; | ||
| 26 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; | ||
| 27 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | 24 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; |
| 28 | -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; | ||
| 29 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; | 25 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; |
| 30 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | 26 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 27 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; | ||
| 28 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; | ||
| 31 | import static org.junit.jupiter.api.Assertions.*; | 29 | import static org.junit.jupiter.api.Assertions.*; |
| 32 | import static org.mockito.ArgumentMatchers.eq; | 30 | import static org.mockito.ArgumentMatchers.eq; |
| 33 | import static org.mockito.Mockito.*; | 31 | import static org.mockito.Mockito.*; |
| @@ -58,9 +56,6 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { | @@ -58,9 +56,6 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { | ||
| 58 | 56 | ||
| 59 | // 调用 | 57 | // 调用 |
| 60 | smsChannelService.initLocalCache(); | 58 | smsChannelService.initLocalCache(); |
| 61 | - // 校验 maxUpdateTime 属性 | ||
| 62 | - LocalDateTime maxUpdateTime = (LocalDateTime) BeanUtil.getFieldValue(smsChannelService, "maxUpdateTime"); | ||
| 63 | - assertEquals(max(smsChannelDO01.getUpdateTime(), smsChannelDO02.getUpdateTime()), maxUpdateTime); | ||
| 64 | // 校验调用 | 59 | // 校验调用 |
| 65 | verify(smsClientFactory, times(1)).createOrUpdateSmsClient( | 60 | verify(smsClientFactory, times(1)).createOrUpdateSmsClient( |
| 66 | argThat(properties -> isPojoEquals(smsChannelDO01, properties))); | 61 | argThat(properties -> isPojoEquals(smsChannelDO01, properties))); |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java
| @@ -235,7 +235,6 @@ public class SmsLogServiceTest extends BaseDbUnitTest { | @@ -235,7 +235,6 @@ public class SmsLogServiceTest extends BaseDbUnitTest { | ||
| 235 | return randomPojo(SmsLogDO.class, ArrayUtils.append(consumer, consumers)); | 235 | return randomPojo(SmsLogDO.class, ArrayUtils.append(consumer, consumers)); |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | - | ||
| 239 | private static Map<String, Object> randomTemplateParams() { | 238 | private static Map<String, Object> randomTemplateParams() { |
| 240 | return MapUtil.<String, Object>builder().put(randomString(), randomString()) | 239 | return MapUtil.<String, Object>builder().put(randomString(), randomString()) |
| 241 | .put(randomString(), randomString()).build(); | 240 | .put(randomString(), randomString()).build(); |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java
| @@ -61,7 +61,6 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { | @@ -61,7 +61,6 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { | ||
| 61 | private SmsProducer smsProducer; | 61 | private SmsProducer smsProducer; |
| 62 | 62 | ||
| 63 | @Test | 63 | @Test |
| 64 | - @SuppressWarnings("unchecked") | ||
| 65 | void testInitLocalCache() { | 64 | void testInitLocalCache() { |
| 66 | // mock 数据 | 65 | // mock 数据 |
| 67 | SmsTemplateDO smsTemplate01 = randomSmsTemplateDO(); | 66 | SmsTemplateDO smsTemplate01 = randomSmsTemplateDO(); |
| @@ -72,13 +71,10 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { | @@ -72,13 +71,10 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { | ||
| 72 | // 调用 | 71 | // 调用 |
| 73 | smsTemplateService.initLocalCache(); | 72 | smsTemplateService.initLocalCache(); |
| 74 | // 断言 deptCache 缓存 | 73 | // 断言 deptCache 缓存 |
| 75 | - Map<String, SmsTemplateDO> smsTemplateCache = (Map<String, SmsTemplateDO>) getFieldValue(smsTemplateService, "smsTemplateCache"); | 74 | + Map<String, SmsTemplateDO> smsTemplateCache = smsTemplateService.getSmsTemplateCache(); |
| 76 | assertEquals(2, smsTemplateCache.size()); | 75 | assertEquals(2, smsTemplateCache.size()); |
| 77 | assertPojoEquals(smsTemplate01, smsTemplateCache.get(smsTemplate01.getCode())); | 76 | assertPojoEquals(smsTemplate01, smsTemplateCache.get(smsTemplate01.getCode())); |
| 78 | assertPojoEquals(smsTemplate02, smsTemplateCache.get(smsTemplate02.getCode())); | 77 | assertPojoEquals(smsTemplate02, smsTemplateCache.get(smsTemplate02.getCode())); |
| 79 | - // 断言 maxUpdateTime 缓存 | ||
| 80 | - LocalDateTime maxUpdateTime = (LocalDateTime) getFieldValue(smsTemplateService, "maxUpdateTime"); | ||
| 81 | - assertEquals(max(smsTemplate01.getUpdateTime(), smsTemplate02.getUpdateTime()), maxUpdateTime); | ||
| 82 | } | 78 | } |
| 83 | 79 | ||
| 84 | @Test | 80 | @Test |
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql
| @@ -25,3 +25,6 @@ DELETE FROM "system_oauth2_approve"; | @@ -25,3 +25,6 @@ DELETE FROM "system_oauth2_approve"; | ||
| 25 | DELETE FROM "system_oauth2_access_token"; | 25 | DELETE FROM "system_oauth2_access_token"; |
| 26 | DELETE FROM "system_oauth2_refresh_token"; | 26 | DELETE FROM "system_oauth2_refresh_token"; |
| 27 | DELETE FROM "system_oauth2_code"; | 27 | DELETE FROM "system_oauth2_code"; |
| 28 | +DELETE FROM "system_mail_account"; | ||
| 29 | +DELETE FROM "system_mail_template"; | ||
| 30 | +DELETE FROM "system_mail_log"; |
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql
| @@ -566,3 +566,63 @@ CREATE TABLE IF NOT EXISTS "system_oauth2_code" ( | @@ -566,3 +566,63 @@ CREATE TABLE IF NOT EXISTS "system_oauth2_code" ( | ||
| 566 | "deleted" bit NOT NULL DEFAULT FALSE, | 566 | "deleted" bit NOT NULL DEFAULT FALSE, |
| 567 | PRIMARY KEY ("id") | 567 | PRIMARY KEY ("id") |
| 568 | ) COMMENT 'OAuth2 刷新令牌'; | 568 | ) COMMENT 'OAuth2 刷新令牌'; |
| 569 | + | ||
| 570 | +CREATE TABLE IF NOT EXISTS "system_mail_account" ( | ||
| 571 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | ||
| 572 | + "mail" varchar NOT NULL, | ||
| 573 | + "username" varchar NOT NULL, | ||
| 574 | + "password" varchar NOT NULL, | ||
| 575 | + "host" varchar NOT NULL, | ||
| 576 | + "port" int NOT NULL, | ||
| 577 | + "ssl_enable" bit NOT NULL, | ||
| 578 | + "creator" varchar DEFAULT '', | ||
| 579 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| 580 | + "updater" varchar DEFAULT '', | ||
| 581 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| 582 | + "deleted" bit NOT NULL DEFAULT FALSE, | ||
| 583 | + PRIMARY KEY ("id") | ||
| 584 | +) COMMENT '邮箱账号表'; | ||
| 585 | + | ||
| 586 | +CREATE TABLE IF NOT EXISTS "system_mail_template" ( | ||
| 587 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | ||
| 588 | + "name" varchar NOT NULL, | ||
| 589 | + "code" varchar NOT NULL, | ||
| 590 | + "account_id" bigint NOT NULL, | ||
| 591 | + "nickname" varchar, | ||
| 592 | + "title" varchar NOT NULL, | ||
| 593 | + "content" varchar NOT NULL, | ||
| 594 | + "params" varchar NOT NULL, | ||
| 595 | + "status" varchar NOT NULL, | ||
| 596 | + "remark" varchar, | ||
| 597 | + "creator" varchar DEFAULT '', | ||
| 598 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| 599 | + "updater" varchar DEFAULT '', | ||
| 600 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| 601 | + "deleted" bit NOT NULL DEFAULT FALSE, | ||
| 602 | + PRIMARY KEY ("id") | ||
| 603 | +) COMMENT '邮件模版表'; | ||
| 604 | + | ||
| 605 | +CREATE TABLE IF NOT EXISTS "system_mail_log" ( | ||
| 606 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | ||
| 607 | + "user_id" bigint, | ||
| 608 | + "user_type" varchar, | ||
| 609 | + "to_mail" varchar NOT NULL, | ||
| 610 | + "account_id" bigint NOT NULL, | ||
| 611 | + "from_mail" varchar NOT NULL, | ||
| 612 | + "template_id" bigint NOT NULL, | ||
| 613 | + "template_code" varchar NOT NULL, | ||
| 614 | + "template_nickname" varchar, | ||
| 615 | + "template_title" varchar NOT NULL, | ||
| 616 | + "template_content" varchar NOT NULL, | ||
| 617 | + "template_params" varchar NOT NULL, | ||
| 618 | + "send_status" varchar NOT NULL, | ||
| 619 | + "send_time" datetime, | ||
| 620 | + "send_message_id" varchar, | ||
| 621 | + "send_exception" varchar, | ||
| 622 | + "creator" varchar DEFAULT '', | ||
| 623 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| 624 | + "updater" varchar DEFAULT '', | ||
| 625 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| 626 | + "deleted" bit NOT NULL DEFAULT FALSE, | ||
| 627 | + PRIMARY KEY ("id") | ||
| 628 | +) COMMENT '邮件日志表'; |
yudao-server/src/main/resources/application.yaml
| @@ -156,6 +156,9 @@ yudao: | @@ -156,6 +156,9 @@ yudao: | ||
| 156 | - system_sms_log | 156 | - system_sms_log |
| 157 | - system_sensitive_word | 157 | - system_sensitive_word |
| 158 | - system_oauth2_client | 158 | - system_oauth2_client |
| 159 | + - system_mail_account | ||
| 160 | + - system_mail_template | ||
| 161 | + - system_mail_log | ||
| 159 | - infra_codegen_column | 162 | - infra_codegen_column |
| 160 | - infra_codegen_table | 163 | - infra_codegen_table |
| 161 | - infra_test_demo | 164 | - infra_test_demo |
yudao-ui-admin-vue3/.env.base
yudao-ui-admin-vue3/.env.dev
yudao-ui-admin-vue3/.env.pro
yudao-ui-admin-vue3/.env.test
yudao-ui-admin-vue3/src/api/system/mail/account/index.ts
0 → 100644
| 1 | +import request from '@/config/axios' | ||
| 2 | + | ||
| 3 | +export interface MailAccountVO { | ||
| 4 | + id: number | ||
| 5 | + mail: string | ||
| 6 | + username: string | ||
| 7 | + password: string | ||
| 8 | + host: string | ||
| 9 | + port: number | ||
| 10 | + sslEnable: boolean | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +export interface MailAccountPageReqVO extends PageParam { | ||
| 14 | + mail?: string | ||
| 15 | + username?: string | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +// 查询邮箱账号列表 | ||
| 19 | +export const getMailAccountPageApi = async (params: MailAccountPageReqVO) => { | ||
| 20 | + return await request.get({ url: '/system/mail-account/page', params }) | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +// 查询邮箱账号详情 | ||
| 24 | +export const getMailAccountApi = async (id: number) => { | ||
| 25 | + return await request.get({ url: '/system/mail-account/get?id=' + id }) | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +// 新增邮箱账号 | ||
| 29 | +export const createMailAccountApi = async (data: MailAccountVO) => { | ||
| 30 | + return await request.post({ url: '/system/mail-account/create', data }) | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +// 修改邮箱账号 | ||
| 34 | +export const updateMailAccountApi = async (data: MailAccountVO) => { | ||
| 35 | + return await request.put({ url: '/system/mail-account/update', data }) | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +// 删除邮箱账号 | ||
| 39 | +export const deleteMailAccountApi = async (id: number) => { | ||
| 40 | + return await request.delete({ url: '/system/mail-account/delete?id=' + id }) | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +// 获得邮箱账号精简列表 | ||
| 44 | +export const getSimpleMailAccounts = async () => { | ||
| 45 | + return request.get({ url: '/system/mail-account/list-all-simple' }) | ||
| 46 | +} |
yudao-ui-admin-vue3/src/api/system/mail/log/index.ts
0 → 100644
| 1 | +import request from '@/config/axios' | ||
| 2 | + | ||
| 3 | +export interface MailLogVO { | ||
| 4 | + id: number | ||
| 5 | + userId: number | ||
| 6 | + userType: number | ||
| 7 | + toMail: string | ||
| 8 | + accountId: number | ||
| 9 | + fromMail: string | ||
| 10 | + templateId: number | ||
| 11 | + templateCode: string | ||
| 12 | + templateNickname: string | ||
| 13 | + templateTitle: string | ||
| 14 | + templateContent: string | ||
| 15 | + templateParams: string | ||
| 16 | + sendStatus: number | ||
| 17 | + sendTime: Date | ||
| 18 | + sendMessageId: string | ||
| 19 | + sendException: string | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +export interface MailLogPageReqVO extends PageParam { | ||
| 23 | + userId?: number | ||
| 24 | + userType?: number | ||
| 25 | + toMail?: string | ||
| 26 | + accountId?: number | ||
| 27 | + templateId?: number | ||
| 28 | + sendStatus?: number | ||
| 29 | + sendTime?: Date[] | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +// 查询邮件日志列表 | ||
| 33 | +export const getMailLogPageApi = async (params: MailLogPageReqVO) => { | ||
| 34 | + return await request.get({ url: '/system/mail-log/page', params }) | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +// 查询邮件日志详情 | ||
| 38 | +export const getMailLogApi = async (id: number) => { | ||
| 39 | + return await request.get({ url: '/system/mail-log/get?id=' + id }) | ||
| 40 | +} |
yudao-ui-admin-vue3/src/api/system/mail/template/index.ts
0 → 100644
| 1 | +import request from '@/config/axios' | ||
| 2 | + | ||
| 3 | +export interface MailTemplateVO { | ||
| 4 | + id: number | ||
| 5 | + name: string | ||
| 6 | + code: string | ||
| 7 | + accountId: number | ||
| 8 | + nickname: string | ||
| 9 | + title: string | ||
| 10 | + content: string | ||
| 11 | + params: string | ||
| 12 | + status: number | ||
| 13 | + remark: string | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +export interface MailTemplatePageReqVO extends PageParam { | ||
| 17 | + name?: string | ||
| 18 | + code?: string | ||
| 19 | + accountId?: number | ||
| 20 | + status?: number | ||
| 21 | + createTime?: Date[] | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +export interface MailSmsReqVO { | ||
| 25 | + mail: string | ||
| 26 | + templateCode: string | ||
| 27 | + templateParams: Map<String, Object> | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +// 查询邮件模版列表 | ||
| 31 | +export const getMailTemplatePageApi = async (params: MailTemplatePageReqVO) => { | ||
| 32 | + return await request.get({ url: '/system/mail-template/page', params }) | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +// 查询邮件模版详情 | ||
| 36 | +export const getMailTemplateApi = async (id: number) => { | ||
| 37 | + return await request.get({ url: '/system/mail-template/get?id=' + id }) | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +// 新增邮件模版 | ||
| 41 | +export const createMailTemplateApi = async (data: MailTemplateVO) => { | ||
| 42 | + return await request.post({ url: '/system/mail-template/create', data }) | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +// 修改邮件模版 | ||
| 46 | +export const updateMailTemplateApi = async (data: MailTemplateVO) => { | ||
| 47 | + return await request.put({ url: '/system/mail-template/update', data }) | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +// 删除邮件模版 | ||
| 51 | +export const deleteMailTemplateApi = async (id: number) => { | ||
| 52 | + return await request.delete({ url: '/system/mail-template/delete?id=' + id }) | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +// 发送邮件 | ||
| 56 | +export const sendMailApi = (data: MailSmsReqVO) => { | ||
| 57 | + return request.post({ url: '/system/mail-template/send-mail', data }) | ||
| 58 | +} |
yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue
| @@ -255,16 +255,17 @@ const getToolBarConfig = (options: XTableProps) => { | @@ -255,16 +255,17 @@ const getToolBarConfig = (options: XTableProps) => { | ||
| 255 | if (toolbarConfig) return | 255 | if (toolbarConfig) return |
| 256 | if (toolBar) { | 256 | if (toolBar) { |
| 257 | if (!isBoolean(toolBar)) { | 257 | if (!isBoolean(toolBar)) { |
| 258 | + console.info(2) | ||
| 258 | options.toolbarConfig = toolBar | 259 | options.toolbarConfig = toolBar |
| 259 | return | 260 | return |
| 260 | } | 261 | } |
| 261 | - } else if (!topActionSlots) { | 262 | + } else if (topActionSlots != false) { |
| 262 | options.toolbarConfig = { | 263 | options.toolbarConfig = { |
| 263 | - enabled: true | 264 | + slots: { buttons: 'toolbar_buttons' } |
| 264 | } | 265 | } |
| 265 | } else { | 266 | } else { |
| 266 | options.toolbarConfig = { | 267 | options.toolbarConfig = { |
| 267 | - slots: { buttons: 'toolbar_buttons' } | 268 | + enabled: true |
| 268 | } | 269 | } |
| 269 | } | 270 | } |
| 270 | } | 271 | } |
yudao-ui-admin-vue3/src/main.ts
| @@ -37,6 +37,13 @@ import App from './App.vue' | @@ -37,6 +37,13 @@ import App from './App.vue' | ||
| 37 | 37 | ||
| 38 | import './permission' | 38 | import './permission' |
| 39 | 39 | ||
| 40 | +import { isDevMode } from '@/utils/env' | ||
| 41 | + | ||
| 42 | +if (isDevMode()) { | ||
| 43 | + console.info(isDevMode()) | ||
| 44 | + import('element-plus/dist/index.css') | ||
| 45 | +} | ||
| 46 | + | ||
| 40 | // 创建实例 | 47 | // 创建实例 |
| 41 | const setupAll = async () => { | 48 | const setupAll = async () => { |
| 42 | const app = createApp(App) | 49 | const app = createApp(App) |
yudao-ui-admin-vue3/src/types/auto-components.d.ts
| @@ -21,6 +21,7 @@ declare module '@vue/runtime-core' { | @@ -21,6 +21,7 @@ declare module '@vue/runtime-core' { | ||
| 21 | DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default'] | 21 | DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default'] |
| 22 | Echart: typeof import('./../components/Echart/src/Echart.vue')['default'] | 22 | Echart: typeof import('./../components/Echart/src/Echart.vue')['default'] |
| 23 | Editor: typeof import('./../components/Editor/src/Editor.vue')['default'] | 23 | Editor: typeof import('./../components/Editor/src/Editor.vue')['default'] |
| 24 | + ElAvatar: typeof import('element-plus/es')['ElAvatar'] | ||
| 24 | ElBadge: typeof import('element-plus/es')['ElBadge'] | 25 | ElBadge: typeof import('element-plus/es')['ElBadge'] |
| 25 | ElButton: typeof import('element-plus/es')['ElButton'] | 26 | ElButton: typeof import('element-plus/es')['ElButton'] |
| 26 | ElCard: typeof import('element-plus/es')['ElCard'] | 27 | ElCard: typeof import('element-plus/es')['ElCard'] |
| @@ -30,6 +31,7 @@ declare module '@vue/runtime-core' { | @@ -30,6 +31,7 @@ declare module '@vue/runtime-core' { | ||
| 30 | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] | 31 | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] |
| 31 | ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] | 32 | ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] |
| 32 | ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] | 33 | ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] |
| 34 | + ElDialog: typeof import('element-plus/es')['ElDialog'] | ||
| 33 | ElDivider: typeof import('element-plus/es')['ElDivider'] | 35 | ElDivider: typeof import('element-plus/es')['ElDivider'] |
| 34 | ElDrawer: typeof import('element-plus/es')['ElDrawer'] | 36 | ElDrawer: typeof import('element-plus/es')['ElDrawer'] |
| 35 | ElDropdown: typeof import('element-plus/es')['ElDropdown'] | 37 | ElDropdown: typeof import('element-plus/es')['ElDropdown'] |
| @@ -38,6 +40,7 @@ declare module '@vue/runtime-core' { | @@ -38,6 +40,7 @@ declare module '@vue/runtime-core' { | ||
| 38 | ElForm: typeof import('element-plus/es')['ElForm'] | 40 | ElForm: typeof import('element-plus/es')['ElForm'] |
| 39 | ElFormItem: typeof import('element-plus/es')['ElFormItem'] | 41 | ElFormItem: typeof import('element-plus/es')['ElFormItem'] |
| 40 | ElIcon: typeof import('element-plus/es')['ElIcon'] | 42 | ElIcon: typeof import('element-plus/es')['ElIcon'] |
| 43 | + ElImage: typeof import('element-plus/es')['ElImage'] | ||
| 41 | ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] | 44 | ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] |
| 42 | ElInput: typeof import('element-plus/es')['ElInput'] | 45 | ElInput: typeof import('element-plus/es')['ElInput'] |
| 43 | ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | 46 | ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] |
| @@ -48,10 +51,14 @@ declare module '@vue/runtime-core' { | @@ -48,10 +51,14 @@ declare module '@vue/runtime-core' { | ||
| 48 | ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] | 51 | ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] |
| 49 | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] | 52 | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] |
| 50 | ElRow: typeof import('element-plus/es')['ElRow'] | 53 | ElRow: typeof import('element-plus/es')['ElRow'] |
| 54 | + ElScroll: typeof import('element-plus/es')['ElScroll'] | ||
| 51 | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] | 55 | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] |
| 52 | ElSelect: typeof import('element-plus/es')['ElSelect'] | 56 | ElSelect: typeof import('element-plus/es')['ElSelect'] |
| 53 | ElSkeleton: typeof import('element-plus/es')['ElSkeleton'] | 57 | ElSkeleton: typeof import('element-plus/es')['ElSkeleton'] |
| 58 | + ElSpace: typeof import('element-plus/es')['ElSpace'] | ||
| 54 | ElSwitch: typeof import('element-plus/es')['ElSwitch'] | 59 | ElSwitch: typeof import('element-plus/es')['ElSwitch'] |
| 60 | + ElTable: typeof import('element-plus/es')['ElTable'] | ||
| 61 | + ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] | ||
| 55 | ElTabPane: typeof import('element-plus/es')['ElTabPane'] | 62 | ElTabPane: typeof import('element-plus/es')['ElTabPane'] |
| 56 | ElTabs: typeof import('element-plus/es')['ElTabs'] | 63 | ElTabs: typeof import('element-plus/es')['ElTabs'] |
| 57 | ElTag: typeof import('element-plus/es')['ElTag'] | 64 | ElTag: typeof import('element-plus/es')['ElTag'] |
yudao-ui-admin-vue3/src/utils/dict.ts
| @@ -90,6 +90,7 @@ export enum DICT_TYPE { | @@ -90,6 +90,7 @@ export enum DICT_TYPE { | ||
| 90 | SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status', | 90 | SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status', |
| 91 | SYSTEM_ERROR_CODE_TYPE = 'system_error_code_type', | 91 | SYSTEM_ERROR_CODE_TYPE = 'system_error_code_type', |
| 92 | SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type', | 92 | SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type', |
| 93 | + SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status', | ||
| 93 | 94 | ||
| 94 | // ========== INFRA 模块 ========== | 95 | // ========== INFRA 模块 ========== |
| 95 | INFRA_BOOLEAN_STRING = 'infra_boolean_string', | 96 | INFRA_BOOLEAN_STRING = 'infra_boolean_string', |
yudao-ui-admin-vue3/src/utils/env.ts
0 → 100644
yudao-ui-admin-vue3/src/views/infra/swagger/index.vue
| @@ -5,5 +5,6 @@ | @@ -5,5 +5,6 @@ | ||
| 5 | </template> | 5 | </template> |
| 6 | <script setup lang="ts" name="Swagger"> | 6 | <script setup lang="ts" name="Swagger"> |
| 7 | const BASE_URL = import.meta.env.VITE_BASE_URL | 7 | const BASE_URL = import.meta.env.VITE_BASE_URL |
| 8 | -const src = ref(BASE_URL + '/doc.html') | 8 | +// const src = ref(BASE_URL + '/doc.html') |
| 9 | +const src = ref(BASE_URL + '/swagger-ui') | ||
| 9 | </script> | 10 | </script> |
yudao-ui-admin-vue3/src/views/system/mail/account/account.data.ts
0 → 100644
| 1 | +import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' | ||
| 2 | + | ||
| 3 | +// 表单校验 | ||
| 4 | +export const rules = reactive({ | ||
| 5 | + mail: [required], | ||
| 6 | + username: [required], | ||
| 7 | + password: [required], | ||
| 8 | + host: [required], | ||
| 9 | + port: [required], | ||
| 10 | + sslEnable: [required] | ||
| 11 | +}) | ||
| 12 | + | ||
| 13 | +// CrudSchema | ||
| 14 | +const crudSchemas = reactive<VxeCrudSchema>({ | ||
| 15 | + primaryKey: 'id', // 默认的主键 ID | ||
| 16 | + primaryTitle: '编号', | ||
| 17 | + primaryType: 'id', | ||
| 18 | + action: true, | ||
| 19 | + actionWidth: '200', // 3 个按钮默认 200,如有删减对应增减即可 | ||
| 20 | + columns: [ | ||
| 21 | + { | ||
| 22 | + title: '邮箱', | ||
| 23 | + field: 'mail', | ||
| 24 | + isSearch: true | ||
| 25 | + }, | ||
| 26 | + { | ||
| 27 | + title: '用户名', | ||
| 28 | + field: 'username', | ||
| 29 | + isSearch: true | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + title: '密码', | ||
| 33 | + field: 'password', | ||
| 34 | + isTable: false | ||
| 35 | + }, | ||
| 36 | + { | ||
| 37 | + title: 'SMTP 服务器域名', | ||
| 38 | + field: 'host' | ||
| 39 | + }, | ||
| 40 | + { | ||
| 41 | + title: 'SMTP 服务器端口', | ||
| 42 | + field: 'port', | ||
| 43 | + form: { | ||
| 44 | + component: 'InputNumber', | ||
| 45 | + value: 465 | ||
| 46 | + } | ||
| 47 | + }, | ||
| 48 | + { | ||
| 49 | + title: '是否开启 SSL', | ||
| 50 | + field: 'sslEnable', | ||
| 51 | + dictType: DICT_TYPE.INFRA_BOOLEAN_STRING, | ||
| 52 | + dictClass: 'boolean' | ||
| 53 | + }, | ||
| 54 | + { | ||
| 55 | + title: '创建时间', | ||
| 56 | + field: 'createTime', | ||
| 57 | + isForm: false, | ||
| 58 | + formatter: 'formatDate', | ||
| 59 | + table: { | ||
| 60 | + width: 180 | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + ] | ||
| 64 | +}) | ||
| 65 | +export const { allSchemas } = useVxeCrudSchemas(crudSchemas) |
yudao-ui-admin-vue3/src/views/system/mail/account/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <ContentWrap> | ||
| 3 | + <!-- 列表 --> | ||
| 4 | + <XTable @register="registerTable"> | ||
| 5 | + <template #toolbar_buttons> | ||
| 6 | + <!-- 操作:新增 --> | ||
| 7 | + <XButton | ||
| 8 | + type="primary" | ||
| 9 | + preIcon="ep:zoom-in" | ||
| 10 | + :title="t('action.add')" | ||
| 11 | + v-hasPermi="['system:mail-account:create']" | ||
| 12 | + @click="handleCreate()" | ||
| 13 | + /> | ||
| 14 | + </template> | ||
| 15 | + <template #actionbtns_default="{ row }"> | ||
| 16 | + <!-- 操作:修改 --> | ||
| 17 | + <XTextButton | ||
| 18 | + preIcon="ep:edit" | ||
| 19 | + :title="t('action.edit')" | ||
| 20 | + v-hasPermi="['system:mail-account:update']" | ||
| 21 | + @click="handleUpdate(row.id)" | ||
| 22 | + /> | ||
| 23 | + <!-- 操作:详情 --> | ||
| 24 | + <XTextButton | ||
| 25 | + preIcon="ep:view" | ||
| 26 | + :title="t('action.detail')" | ||
| 27 | + v-hasPermi="['system:mail-account:query']" | ||
| 28 | + @click="handleDetail(row.id)" | ||
| 29 | + /> | ||
| 30 | + <!-- 操作:删除 --> | ||
| 31 | + <XTextButton | ||
| 32 | + preIcon="ep:delete" | ||
| 33 | + :title="t('action.del')" | ||
| 34 | + v-hasPermi="['system:mail-account:delete']" | ||
| 35 | + @click="deleteData(row.id)" | ||
| 36 | + /> | ||
| 37 | + </template> | ||
| 38 | + </XTable> | ||
| 39 | + </ContentWrap> | ||
| 40 | + <!-- 弹窗 --> | ||
| 41 | + <XModal id="mailAccountModel" :loading="modelLoading" v-model="modelVisible" :title="modelTitle"> | ||
| 42 | + <!-- 表单:添加/修改 --> | ||
| 43 | + <Form | ||
| 44 | + ref="formRef" | ||
| 45 | + v-if="['create', 'update'].includes(actionType)" | ||
| 46 | + :schema="allSchemas.formSchema" | ||
| 47 | + :rules="rules" | ||
| 48 | + /> | ||
| 49 | + <!-- 表单:详情 --> | ||
| 50 | + <Descriptions | ||
| 51 | + v-if="actionType === 'detail'" | ||
| 52 | + :schema="allSchemas.detailSchema" | ||
| 53 | + :data="detailData" | ||
| 54 | + /> | ||
| 55 | + <template #footer> | ||
| 56 | + <!-- 按钮:保存 --> | ||
| 57 | + <XButton | ||
| 58 | + v-if="['create', 'update'].includes(actionType)" | ||
| 59 | + type="primary" | ||
| 60 | + :title="t('action.save')" | ||
| 61 | + :loading="actionLoading" | ||
| 62 | + @click="submitForm()" | ||
| 63 | + /> | ||
| 64 | + <!-- 按钮:关闭 --> | ||
| 65 | + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" /> | ||
| 66 | + </template> | ||
| 67 | + </XModal> | ||
| 68 | +</template> | ||
| 69 | +<script setup lang="ts" name="MailAccount"> | ||
| 70 | +import { FormExpose } from '@/components/Form' | ||
| 71 | +// 业务相关的 import | ||
| 72 | +import { rules, allSchemas } from './account.data' | ||
| 73 | +import * as MailAccountApi from '@/api/system/mail/account' | ||
| 74 | + | ||
| 75 | +const { t } = useI18n() // 国际化 | ||
| 76 | +const message = useMessage() // 消息弹窗 | ||
| 77 | + | ||
| 78 | +// 列表相关的变量 | ||
| 79 | +const [registerTable, { reload, deleteData }] = useXTable({ | ||
| 80 | + allSchemas: allSchemas, | ||
| 81 | + getListApi: MailAccountApi.getMailAccountPageApi, | ||
| 82 | + deleteApi: MailAccountApi.deleteMailAccountApi | ||
| 83 | +}) | ||
| 84 | + | ||
| 85 | +// 弹窗相关的变量 | ||
| 86 | +const modelVisible = ref(false) // 是否显示弹出层 | ||
| 87 | +const modelTitle = ref('edit') // 弹出层标题 | ||
| 88 | +const modelLoading = ref(false) // 弹出层loading | ||
| 89 | +const actionType = ref('') // 操作按钮的类型 | ||
| 90 | +const actionLoading = ref(false) // 按钮 Loading | ||
| 91 | +const formRef = ref<FormExpose>() // 表单 Ref | ||
| 92 | +const detailData = ref() // 详情 Ref | ||
| 93 | + | ||
| 94 | +// 设置标题 | ||
| 95 | +const setDialogTile = (type: string) => { | ||
| 96 | + modelLoading.value = true | ||
| 97 | + modelTitle.value = t('action.' + type) | ||
| 98 | + actionType.value = type | ||
| 99 | + modelVisible.value = true | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +// 新增操作 | ||
| 103 | +const handleCreate = () => { | ||
| 104 | + setDialogTile('create') | ||
| 105 | + modelLoading.value = false | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +// 修改操作 | ||
| 109 | +const handleUpdate = async (rowId: number) => { | ||
| 110 | + setDialogTile('update') | ||
| 111 | + // 设置数据 | ||
| 112 | + const res = await MailAccountApi.getMailAccountApi(rowId) | ||
| 113 | + unref(formRef)?.setValues(res) | ||
| 114 | + modelLoading.value = false | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +// 详情操作 | ||
| 118 | +const handleDetail = async (rowId: number) => { | ||
| 119 | + setDialogTile('detail') | ||
| 120 | + const res = await MailAccountApi.getMailAccountApi(rowId) | ||
| 121 | + detailData.value = res | ||
| 122 | + modelLoading.value = false | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +// 提交按钮 | ||
| 126 | +const submitForm = async () => { | ||
| 127 | + const elForm = unref(formRef)?.getElFormRef() | ||
| 128 | + if (!elForm) return | ||
| 129 | + elForm.validate(async (valid) => { | ||
| 130 | + if (valid) { | ||
| 131 | + actionLoading.value = true | ||
| 132 | + // 提交请求 | ||
| 133 | + try { | ||
| 134 | + const data = unref(formRef)?.formModel as MailAccountApi.MailAccountVO | ||
| 135 | + if (actionType.value === 'create') { | ||
| 136 | + await MailAccountApi.createMailAccountApi(data) | ||
| 137 | + message.success(t('common.createSuccess')) | ||
| 138 | + } else { | ||
| 139 | + await MailAccountApi.updateMailAccountApi(data) | ||
| 140 | + message.success(t('common.updateSuccess')) | ||
| 141 | + } | ||
| 142 | + modelVisible.value = false | ||
| 143 | + } finally { | ||
| 144 | + actionLoading.value = false | ||
| 145 | + // 刷新列表 | ||
| 146 | + await reload() | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + }) | ||
| 150 | +} | ||
| 151 | +</script> |
yudao-ui-admin-vue3/src/views/system/mail/log/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <ContentWrap> | ||
| 3 | + <!-- 列表 --> | ||
| 4 | + <XTable @register="registerTable"> | ||
| 5 | + <template #accountId_search> | ||
| 6 | + <el-select v-model="queryParams.accountId"> | ||
| 7 | + <el-option :key="undefined" label="全部" :value="undefined" /> | ||
| 8 | + <el-option | ||
| 9 | + v-for="item in accountOptions" | ||
| 10 | + :key="item.id" | ||
| 11 | + :label="item.mail" | ||
| 12 | + :value="item.id" | ||
| 13 | + /> | ||
| 14 | + </el-select> | ||
| 15 | + </template> | ||
| 16 | + <template #toMail_default="{ row }"> | ||
| 17 | + <div>{{ row.toMail }}</div> | ||
| 18 | + <div v-if="row.userType && row.userId"> | ||
| 19 | + <dict-tag :type="DICT_TYPE.USER_TYPE" :value="row.userType" />{{ '(' + row.userId + ')' }} | ||
| 20 | + </div> | ||
| 21 | + </template> | ||
| 22 | + <template #actionbtns_default="{ row }"> | ||
| 23 | + <!-- 操作:详情 --> | ||
| 24 | + <XTextButton | ||
| 25 | + preIcon="ep:view" | ||
| 26 | + :title="t('action.detail')" | ||
| 27 | + v-hasPermi="['system:mail-log:query']" | ||
| 28 | + @click="handleDetail(row.id)" | ||
| 29 | + /> | ||
| 30 | + </template> | ||
| 31 | + </XTable> | ||
| 32 | + </ContentWrap> | ||
| 33 | + <!-- 弹窗 --> | ||
| 34 | + <XModal id="mailLogModel" :loading="modelLoading" v-model="modelVisible" :title="modelTitle"> | ||
| 35 | + <!-- 表单:详情 --> | ||
| 36 | + <Descriptions | ||
| 37 | + v-if="actionType === 'detail'" | ||
| 38 | + :schema="allSchemas.detailSchema" | ||
| 39 | + :data="detailData" | ||
| 40 | + /> | ||
| 41 | + <template #footer> | ||
| 42 | + <!-- 按钮:关闭 --> | ||
| 43 | + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" /> | ||
| 44 | + </template> | ||
| 45 | + </XModal> | ||
| 46 | +</template> | ||
| 47 | +<script setup lang="ts" name="MailLog"> | ||
| 48 | +// 业务相关的 import | ||
| 49 | +import { allSchemas } from './log.data' | ||
| 50 | +import * as MailLogApi from '@/api/system/mail/log' | ||
| 51 | +import * as MailAccountApi from '@/api/system/mail/account' | ||
| 52 | + | ||
| 53 | +const { t } = useI18n() // 国际化 | ||
| 54 | + | ||
| 55 | +// 列表相关的变量 | ||
| 56 | +const queryParams = reactive({ | ||
| 57 | + accountId: null | ||
| 58 | +}) | ||
| 59 | +const [registerTable] = useXTable({ | ||
| 60 | + allSchemas: allSchemas, | ||
| 61 | + params: queryParams, | ||
| 62 | + getListApi: MailLogApi.getMailLogPageApi | ||
| 63 | +}) | ||
| 64 | +const accountOptions = ref([]) // 账号下拉选项 | ||
| 65 | + | ||
| 66 | +// 弹窗相关的变量 | ||
| 67 | +const modelVisible = ref(false) // 是否显示弹出层 | ||
| 68 | +const modelTitle = ref('edit') // 弹出层标题 | ||
| 69 | +const modelLoading = ref(false) // 弹出层loading | ||
| 70 | +const actionType = ref('') // 操作按钮的类型 | ||
| 71 | +const actionLoading = ref(false) // 按钮 Loading | ||
| 72 | +const detailData = ref() // 详情 Ref | ||
| 73 | + | ||
| 74 | +// 设置标题 | ||
| 75 | +const setDialogTile = (type: string) => { | ||
| 76 | + modelLoading.value = true | ||
| 77 | + modelTitle.value = t('action.' + type) | ||
| 78 | + actionType.value = type | ||
| 79 | + modelVisible.value = true | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +// 详情操作 | ||
| 83 | +const handleDetail = async (rowId: number) => { | ||
| 84 | + setDialogTile('detail') | ||
| 85 | + const res = await MailLogApi.getMailLogApi(rowId) | ||
| 86 | + detailData.value = res | ||
| 87 | + modelLoading.value = false | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +// ========== 初始化 ========== | ||
| 91 | +onMounted(() => { | ||
| 92 | + MailAccountApi.getSimpleMailAccounts().then((data) => { | ||
| 93 | + accountOptions.value = data | ||
| 94 | + }) | ||
| 95 | +}) | ||
| 96 | +</script> |
yudao-ui-admin-vue3/src/views/system/mail/log/log.data.ts
0 → 100644
| 1 | +import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' | ||
| 2 | + | ||
| 3 | +// CrudSchema | ||
| 4 | +const crudSchemas = reactive<VxeCrudSchema>({ | ||
| 5 | + primaryKey: 'id', | ||
| 6 | + primaryTitle: '编号', | ||
| 7 | + primaryType: 'id', | ||
| 8 | + action: true, | ||
| 9 | + actionWidth: '70', | ||
| 10 | + columns: [ | ||
| 11 | + { | ||
| 12 | + title: '发送时间', | ||
| 13 | + field: 'sendTime', | ||
| 14 | + table: { | ||
| 15 | + width: 180 | ||
| 16 | + }, | ||
| 17 | + formatter: 'formatDate', | ||
| 18 | + search: { | ||
| 19 | + show: true, | ||
| 20 | + itemRender: { | ||
| 21 | + name: 'XDataTimePicker' | ||
| 22 | + } | ||
| 23 | + } | ||
| 24 | + }, | ||
| 25 | + { | ||
| 26 | + title: '接收邮箱', | ||
| 27 | + field: 'toMail', | ||
| 28 | + isSearch: true, | ||
| 29 | + table: { | ||
| 30 | + width: 180, | ||
| 31 | + slots: { | ||
| 32 | + default: 'toMail_default' | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + }, | ||
| 36 | + { | ||
| 37 | + title: '用户编号', | ||
| 38 | + field: 'userId', | ||
| 39 | + isSearch: true, | ||
| 40 | + isTable: false | ||
| 41 | + }, | ||
| 42 | + { | ||
| 43 | + title: '用户类型', | ||
| 44 | + field: 'userType', | ||
| 45 | + dictType: DICT_TYPE.USER_TYPE, | ||
| 46 | + dictClass: 'number', | ||
| 47 | + isSearch: true, | ||
| 48 | + isTable: false | ||
| 49 | + }, | ||
| 50 | + { | ||
| 51 | + title: '邮件标题', | ||
| 52 | + field: 'templateTitle' | ||
| 53 | + }, | ||
| 54 | + { | ||
| 55 | + title: '邮件内容', | ||
| 56 | + field: 'templateContent', | ||
| 57 | + isTable: false | ||
| 58 | + }, | ||
| 59 | + { | ||
| 60 | + title: '邮箱参数', | ||
| 61 | + field: 'templateParams', | ||
| 62 | + isTable: false | ||
| 63 | + }, | ||
| 64 | + { | ||
| 65 | + title: '发送状态', | ||
| 66 | + field: 'sendStatus', | ||
| 67 | + dictType: DICT_TYPE.SYSTEM_MAIL_SEND_STATUS, | ||
| 68 | + dictClass: 'string', | ||
| 69 | + isSearch: true | ||
| 70 | + }, | ||
| 71 | + { | ||
| 72 | + title: '邮箱账号', | ||
| 73 | + field: 'accountId', | ||
| 74 | + isSearch: true, | ||
| 75 | + isTable: false, | ||
| 76 | + search: { | ||
| 77 | + slots: { | ||
| 78 | + default: 'accountId_search' | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | + }, | ||
| 82 | + { | ||
| 83 | + title: '发送邮箱地址', | ||
| 84 | + field: 'fromMail', | ||
| 85 | + table: { | ||
| 86 | + title: '邮箱账号' | ||
| 87 | + } | ||
| 88 | + }, | ||
| 89 | + { | ||
| 90 | + title: '模板编号', | ||
| 91 | + field: 'templateId', | ||
| 92 | + isSearch: true | ||
| 93 | + }, | ||
| 94 | + { | ||
| 95 | + title: '模板编码', | ||
| 96 | + field: 'templateCode', | ||
| 97 | + isTable: false | ||
| 98 | + }, | ||
| 99 | + { | ||
| 100 | + title: '模版发送人名称', | ||
| 101 | + field: 'templateNickname', | ||
| 102 | + isTable: false | ||
| 103 | + }, | ||
| 104 | + { | ||
| 105 | + title: '发送返回的消息编号', | ||
| 106 | + field: 'sendMessageId', | ||
| 107 | + isTable: false | ||
| 108 | + }, | ||
| 109 | + { | ||
| 110 | + title: '发送异常', | ||
| 111 | + field: 'sendException', | ||
| 112 | + isTable: false | ||
| 113 | + }, | ||
| 114 | + { | ||
| 115 | + title: '创建时间', | ||
| 116 | + field: 'createTime', | ||
| 117 | + isTable: false | ||
| 118 | + } | ||
| 119 | + ] | ||
| 120 | +}) | ||
| 121 | +export const { allSchemas } = useVxeCrudSchemas(crudSchemas) |
yudao-ui-admin-vue3/src/views/system/mail/template/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <ContentWrap> | ||
| 3 | + <!-- 列表 --> | ||
| 4 | + <XTable @register="registerTable"> | ||
| 5 | + <template #accountId_search> | ||
| 6 | + <el-select v-model="queryParams.accountId"> | ||
| 7 | + <el-option :key="undefined" label="全部" :value="undefined" /> | ||
| 8 | + <el-option | ||
| 9 | + v-for="item in accountOptions" | ||
| 10 | + :key="item.id" | ||
| 11 | + :label="item.mail" | ||
| 12 | + :value="item.id" | ||
| 13 | + /> | ||
| 14 | + </el-select> | ||
| 15 | + </template> | ||
| 16 | + <template #toolbar_buttons> | ||
| 17 | + <!-- 操作:新增 --> | ||
| 18 | + <XButton | ||
| 19 | + type="primary" | ||
| 20 | + preIcon="ep:zoom-in" | ||
| 21 | + :title="t('action.add')" | ||
| 22 | + v-hasPermi="['system:mail-template:create']" | ||
| 23 | + @click="handleCreate()" | ||
| 24 | + /> | ||
| 25 | + </template> | ||
| 26 | + <template #accountId_default="{ row }"> | ||
| 27 | + <span>{{ accountOptions.find((account) => account.id === row.accountId)?.mail }}</span> | ||
| 28 | + </template> | ||
| 29 | + <template #actionbtns_default="{ row }"> | ||
| 30 | + <!-- 操作:测试短信 --> | ||
| 31 | + <XTextButton | ||
| 32 | + preIcon="ep:cpu" | ||
| 33 | + :title="t('action.test')" | ||
| 34 | + v-hasPermi="['system:mail-template:send-mail']" | ||
| 35 | + @click="handleSendMail(row)" | ||
| 36 | + /> | ||
| 37 | + <!-- 操作:修改 --> | ||
| 38 | + <XTextButton | ||
| 39 | + preIcon="ep:edit" | ||
| 40 | + :title="t('action.edit')" | ||
| 41 | + v-hasPermi="['system:mail-template:update']" | ||
| 42 | + @click="handleUpdate(row.id)" | ||
| 43 | + /> | ||
| 44 | + <!-- 操作:详情 --> | ||
| 45 | + <XTextButton | ||
| 46 | + preIcon="ep:view" | ||
| 47 | + :title="t('action.detail')" | ||
| 48 | + v-hasPermi="['system:mail-template:query']" | ||
| 49 | + @click="handleDetail(row.id)" | ||
| 50 | + /> | ||
| 51 | + <!-- 操作:删除 --> | ||
| 52 | + <XTextButton | ||
| 53 | + preIcon="ep:delete" | ||
| 54 | + :title="t('action.del')" | ||
| 55 | + v-hasPermi="['system:mail-template:delete']" | ||
| 56 | + @click="deleteData(row.id)" | ||
| 57 | + /> | ||
| 58 | + </template> | ||
| 59 | + </XTable> | ||
| 60 | + </ContentWrap> | ||
| 61 | + | ||
| 62 | + <!-- 添加/修改/详情的弹窗 --> | ||
| 63 | + <XModal id="mailTemplateModel" :loading="modelLoading" v-model="modelVisible" :title="modelTitle"> | ||
| 64 | + <!-- 表单:添加/修改 --> | ||
| 65 | + <Form | ||
| 66 | + ref="formRef" | ||
| 67 | + v-if="['create', 'update'].includes(actionType)" | ||
| 68 | + :schema="allSchemas.formSchema" | ||
| 69 | + :rules="rules" | ||
| 70 | + > | ||
| 71 | + <template #accountId="form"> | ||
| 72 | + <el-select v-model="form.accountId"> | ||
| 73 | + <el-option | ||
| 74 | + v-for="item in accountOptions" | ||
| 75 | + :key="item.id" | ||
| 76 | + :label="item.mail" | ||
| 77 | + :value="item.id" | ||
| 78 | + /> | ||
| 79 | + </el-select> | ||
| 80 | + </template> | ||
| 81 | + </Form> | ||
| 82 | + <!-- 表单:详情 --> | ||
| 83 | + <Descriptions | ||
| 84 | + v-if="actionType === 'detail'" | ||
| 85 | + :schema="allSchemas.detailSchema" | ||
| 86 | + :data="detailData" | ||
| 87 | + /> | ||
| 88 | + <template #footer> | ||
| 89 | + <!-- 按钮:保存 --> | ||
| 90 | + <XButton | ||
| 91 | + v-if="['create', 'update'].includes(actionType)" | ||
| 92 | + type="primary" | ||
| 93 | + :title="t('action.save')" | ||
| 94 | + :loading="actionLoading" | ||
| 95 | + @click="submitForm()" | ||
| 96 | + /> | ||
| 97 | + <!-- 按钮:关闭 --> | ||
| 98 | + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" /> | ||
| 99 | + </template> | ||
| 100 | + </XModal> | ||
| 101 | + | ||
| 102 | + <!-- 测试邮件的弹窗 --> | ||
| 103 | + <XModal id="sendTest" v-model="sendVisible" title="测试"> | ||
| 104 | + <el-form :model="sendForm" :rules="sendRules" label-width="200px" label-position="top"> | ||
| 105 | + <el-form-item label="模板内容" prop="content"> | ||
| 106 | + <Editor :model-value="sendForm.content" readonly height="150px" /> | ||
| 107 | + </el-form-item> | ||
| 108 | + <el-form-item label="收件邮箱" prop="mail"> | ||
| 109 | + <el-input v-model="sendForm.mail" placeholder="请输入收件邮箱" /> | ||
| 110 | + </el-form-item> | ||
| 111 | + <el-form-item | ||
| 112 | + v-for="param in sendForm.params" | ||
| 113 | + :key="param" | ||
| 114 | + :label="'参数 {' + param + '}'" | ||
| 115 | + :prop="'templateParams.' + param" | ||
| 116 | + > | ||
| 117 | + <el-input | ||
| 118 | + v-model="sendForm.templateParams[param]" | ||
| 119 | + :placeholder="'请输入 ' + param + ' 参数'" | ||
| 120 | + /> | ||
| 121 | + </el-form-item> | ||
| 122 | + </el-form> | ||
| 123 | + <!-- 操作按钮 --> | ||
| 124 | + <template #footer> | ||
| 125 | + <XButton | ||
| 126 | + type="primary" | ||
| 127 | + :title="t('action.test')" | ||
| 128 | + :loading="actionLoading" | ||
| 129 | + @click="sendTest()" | ||
| 130 | + /> | ||
| 131 | + <XButton :title="t('dialog.close')" @click="sendVisible = false" /> | ||
| 132 | + </template> | ||
| 133 | + </XModal> | ||
| 134 | +</template> | ||
| 135 | +<script setup lang="ts" name="MailTemplate"> | ||
| 136 | +import { FormExpose } from '@/components/Form' | ||
| 137 | +// 业务相关的 import | ||
| 138 | +import { rules, allSchemas } from './template.data' | ||
| 139 | +import * as MailTemplateApi from '@/api/system/mail/template' | ||
| 140 | +import * as MailAccountApi from '@/api/system/mail/account' | ||
| 141 | + | ||
| 142 | +const { t } = useI18n() // 国际化 | ||
| 143 | +const message = useMessage() // 消息弹窗 | ||
| 144 | + | ||
| 145 | +// 列表相关的变量 | ||
| 146 | +const queryParams = reactive({ | ||
| 147 | + accountId: null | ||
| 148 | +}) | ||
| 149 | +const [registerTable, { reload, deleteData }] = useXTable({ | ||
| 150 | + allSchemas: allSchemas, | ||
| 151 | + params: queryParams, | ||
| 152 | + getListApi: MailTemplateApi.getMailTemplatePageApi, | ||
| 153 | + deleteApi: MailTemplateApi.deleteMailTemplateApi | ||
| 154 | +}) | ||
| 155 | +const accountOptions = ref([]) // 账号下拉选项 | ||
| 156 | + | ||
| 157 | +// 弹窗相关的变量 | ||
| 158 | +const modelVisible = ref(false) // 是否显示弹出层 | ||
| 159 | +const modelTitle = ref('edit') // 弹出层标题 | ||
| 160 | +const modelLoading = ref(false) // 弹出层loading | ||
| 161 | +const actionType = ref('') // 操作按钮的类型 | ||
| 162 | +const actionLoading = ref(false) // 按钮 Loading | ||
| 163 | +const formRef = ref<FormExpose>() // 表单 Ref | ||
| 164 | +const detailData = ref() // 详情 Ref | ||
| 165 | + | ||
| 166 | +// 设置标题 | ||
| 167 | +const setDialogTile = (type: string) => { | ||
| 168 | + modelLoading.value = true | ||
| 169 | + modelTitle.value = t('action.' + type) | ||
| 170 | + actionType.value = type | ||
| 171 | + modelVisible.value = true | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | +// 新增操作 | ||
| 175 | +const handleCreate = () => { | ||
| 176 | + setDialogTile('create') | ||
| 177 | + modelLoading.value = false | ||
| 178 | +} | ||
| 179 | + | ||
| 180 | +// 修改操作 | ||
| 181 | +const handleUpdate = async (rowId: number) => { | ||
| 182 | + setDialogTile('update') | ||
| 183 | + // 设置数据 | ||
| 184 | + const res = await MailTemplateApi.getMailTemplateApi(rowId) | ||
| 185 | + unref(formRef)?.setValues(res) | ||
| 186 | + modelLoading.value = false | ||
| 187 | +} | ||
| 188 | + | ||
| 189 | +// 详情操作 | ||
| 190 | +const handleDetail = async (rowId: number) => { | ||
| 191 | + setDialogTile('detail') | ||
| 192 | + const res = await MailTemplateApi.getMailTemplateApi(rowId) | ||
| 193 | + detailData.value = res | ||
| 194 | + modelLoading.value = false | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +// 提交按钮 | ||
| 198 | +const submitForm = async () => { | ||
| 199 | + const elForm = unref(formRef)?.getElFormRef() | ||
| 200 | + if (!elForm) return | ||
| 201 | + elForm.validate(async (valid) => { | ||
| 202 | + if (valid) { | ||
| 203 | + actionLoading.value = true | ||
| 204 | + // 提交请求 | ||
| 205 | + try { | ||
| 206 | + const data = unref(formRef)?.formModel as MailTemplateApi.MailTemplateVO | ||
| 207 | + if (actionType.value === 'create') { | ||
| 208 | + await MailTemplateApi.createMailTemplateApi(data) | ||
| 209 | + message.success(t('common.createSuccess')) | ||
| 210 | + } else { | ||
| 211 | + await MailTemplateApi.updateMailTemplateApi(data) | ||
| 212 | + message.success(t('common.updateSuccess')) | ||
| 213 | + } | ||
| 214 | + modelVisible.value = false | ||
| 215 | + } finally { | ||
| 216 | + actionLoading.value = false | ||
| 217 | + // 刷新列表 | ||
| 218 | + await reload() | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | + }) | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +// ========== 测试相关 ========== | ||
| 225 | +const sendForm = ref({ | ||
| 226 | + content: '', | ||
| 227 | + params: {}, | ||
| 228 | + mail: '', | ||
| 229 | + templateCode: '', | ||
| 230 | + templateParams: {} | ||
| 231 | +}) | ||
| 232 | +const sendRules = ref({ | ||
| 233 | + mail: [{ required: true, message: '邮箱不能为空', trigger: 'blur' }], | ||
| 234 | + templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], | ||
| 235 | + templateParams: {} | ||
| 236 | +}) | ||
| 237 | +const sendVisible = ref(false) | ||
| 238 | + | ||
| 239 | +const handleSendMail = (row: any) => { | ||
| 240 | + sendForm.value.content = row.content | ||
| 241 | + sendForm.value.params = row.params | ||
| 242 | + sendForm.value.templateCode = row.code | ||
| 243 | + sendForm.value.templateParams = row.params.reduce(function (obj, item) { | ||
| 244 | + obj[item] = undefined | ||
| 245 | + return obj | ||
| 246 | + }, {}) | ||
| 247 | + sendRules.value.templateParams = row.params.reduce(function (obj, item) { | ||
| 248 | + obj[item] = { required: true, message: '参数 ' + item + ' 不能为空', trigger: 'change' } | ||
| 249 | + return obj | ||
| 250 | + }, {}) | ||
| 251 | + sendVisible.value = true | ||
| 252 | +} | ||
| 253 | + | ||
| 254 | +const sendTest = async () => { | ||
| 255 | + const data: MailTemplateApi.MailSmsReqVO = { | ||
| 256 | + mail: sendForm.value.mail, | ||
| 257 | + templateCode: sendForm.value.templateCode, | ||
| 258 | + templateParams: sendForm.value.templateParams as unknown as Map<string, Object> | ||
| 259 | + } | ||
| 260 | + const res = await MailTemplateApi.sendMailApi(data) | ||
| 261 | + if (res) { | ||
| 262 | + message.success('提交发送成功!发送结果,见发送日志编号:' + res) | ||
| 263 | + } | ||
| 264 | + sendVisible.value = false | ||
| 265 | +} | ||
| 266 | + | ||
| 267 | +// ========== 初始化 ========== | ||
| 268 | +onMounted(() => { | ||
| 269 | + MailAccountApi.getSimpleMailAccounts().then((data) => { | ||
| 270 | + accountOptions.value = data | ||
| 271 | + }) | ||
| 272 | +}) | ||
| 273 | +</script> |
yudao-ui-admin-vue3/src/views/system/mail/template/template.data.ts
0 → 100644
| 1 | +import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' | ||
| 2 | + | ||
| 3 | +// 表单校验 | ||
| 4 | +export const rules = reactive({ | ||
| 5 | + name: [required], | ||
| 6 | + code: [required], | ||
| 7 | + accountId: [required], | ||
| 8 | + title: [required], | ||
| 9 | + content: [required], | ||
| 10 | + params: [required], | ||
| 11 | + status: [required] | ||
| 12 | +}) | ||
| 13 | + | ||
| 14 | +// CrudSchema | ||
| 15 | +const crudSchemas = reactive<VxeCrudSchema>({ | ||
| 16 | + primaryKey: 'id', // 默认的主键ID | ||
| 17 | + primaryTitle: '编号', // 默认显示的值 | ||
| 18 | + primaryType: null, | ||
| 19 | + action: true, | ||
| 20 | + actionWidth: '260', | ||
| 21 | + columns: [ | ||
| 22 | + { | ||
| 23 | + title: '模板编码', | ||
| 24 | + field: 'code', | ||
| 25 | + isSearch: true | ||
| 26 | + }, | ||
| 27 | + { | ||
| 28 | + title: '模板名称', | ||
| 29 | + field: 'name', | ||
| 30 | + isSearch: true | ||
| 31 | + }, | ||
| 32 | + { | ||
| 33 | + title: '模板标题', | ||
| 34 | + field: 'title' | ||
| 35 | + }, | ||
| 36 | + { | ||
| 37 | + title: '模板内容', | ||
| 38 | + field: 'content', | ||
| 39 | + form: { | ||
| 40 | + component: 'Editor', | ||
| 41 | + colProps: { | ||
| 42 | + span: 24 | ||
| 43 | + }, | ||
| 44 | + componentProps: { | ||
| 45 | + valueHtml: '' | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + }, | ||
| 49 | + { | ||
| 50 | + title: '邮箱账号', | ||
| 51 | + field: 'accountId', | ||
| 52 | + isSearch: true, | ||
| 53 | + table: { | ||
| 54 | + width: 200, | ||
| 55 | + slots: { | ||
| 56 | + default: 'accountId_default' | ||
| 57 | + } | ||
| 58 | + }, | ||
| 59 | + search: { | ||
| 60 | + slots: { | ||
| 61 | + default: 'accountId_search' | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + { | ||
| 66 | + title: '发送人名称', | ||
| 67 | + field: 'nickname' | ||
| 68 | + }, | ||
| 69 | + { | ||
| 70 | + title: '开启状态', | ||
| 71 | + field: 'status', | ||
| 72 | + isSearch: true, | ||
| 73 | + dictType: DICT_TYPE.COMMON_STATUS, | ||
| 74 | + dictClass: 'number' | ||
| 75 | + }, | ||
| 76 | + { | ||
| 77 | + title: '备注', | ||
| 78 | + field: 'remark', | ||
| 79 | + isTable: false | ||
| 80 | + }, | ||
| 81 | + { | ||
| 82 | + title: '创建时间', | ||
| 83 | + field: 'createTime', | ||
| 84 | + isForm: false, | ||
| 85 | + formatter: 'formatDate', | ||
| 86 | + table: { | ||
| 87 | + width: 180 | ||
| 88 | + }, | ||
| 89 | + search: { | ||
| 90 | + show: true, | ||
| 91 | + itemRender: { | ||
| 92 | + name: 'XDataTimePicker' | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + ] | ||
| 97 | +}) | ||
| 98 | +export const { allSchemas } = useVxeCrudSchemas(crudSchemas) |
yudao-ui-admin-vue3/src/views/system/sms/smsTemplate/index.vue
| @@ -197,7 +197,7 @@ const sendSmsForm = ref({ | @@ -197,7 +197,7 @@ const sendSmsForm = ref({ | ||
| 197 | }) | 197 | }) |
| 198 | const sendSmsRules = ref({ | 198 | const sendSmsRules = ref({ |
| 199 | mobile: [{ required: true, message: '手机不能为空', trigger: 'blur' }], | 199 | mobile: [{ required: true, message: '手机不能为空', trigger: 'blur' }], |
| 200 | - templateCode: [{ required: true, message: '手机不能为空', trigger: 'blur' }], | 200 | + templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], |
| 201 | templateParams: {} | 201 | templateParams: {} |
| 202 | }) | 202 | }) |
| 203 | const sendVisible = ref(false) | 203 | const sendVisible = ref(false) |
| @@ -225,7 +225,7 @@ const sendSmsTest = async () => { | @@ -225,7 +225,7 @@ const sendSmsTest = async () => { | ||
| 225 | } | 225 | } |
| 226 | const res = await SmsTemplateApi.sendSmsApi(data) | 226 | const res = await SmsTemplateApi.sendSmsApi(data) |
| 227 | if (res) { | 227 | if (res) { |
| 228 | - message.success('发送成功') | 228 | + message.success('提交发送成功!发送结果,见发送日志编号:' + res) |
| 229 | } | 229 | } |
| 230 | sendVisible.value = false | 230 | sendVisible.value = false |
| 231 | } | 231 | } |
yudao-ui-admin-vue3/src/views/system/user/index.vue
| @@ -8,17 +8,19 @@ | @@ -8,17 +8,19 @@ | ||
| 8 | </div> | 8 | </div> |
| 9 | </template> | 9 | </template> |
| 10 | <el-input v-model="filterText" placeholder="搜索部门" /> | 10 | <el-input v-model="filterText" placeholder="搜索部门" /> |
| 11 | - <el-tree | ||
| 12 | - ref="treeRef" | ||
| 13 | - node-key="id" | ||
| 14 | - default-expand-all | ||
| 15 | - :data="deptOptions" | ||
| 16 | - :props="defaultProps" | ||
| 17 | - :highlight-current="true" | ||
| 18 | - :filter-node-method="filterNode" | ||
| 19 | - :expand-on-click-node="false" | ||
| 20 | - @node-click="handleDeptNodeClick" | ||
| 21 | - /> | 11 | + <el-scrollbar height="650"> |
| 12 | + <el-tree | ||
| 13 | + ref="treeRef" | ||
| 14 | + node-key="id" | ||
| 15 | + default-expand-all | ||
| 16 | + :data="deptOptions" | ||
| 17 | + :props="defaultProps" | ||
| 18 | + :highlight-current="true" | ||
| 19 | + :filter-node-method="filterNode" | ||
| 20 | + :expand-on-click-node="false" | ||
| 21 | + @node-click="handleDeptNodeClick" | ||
| 22 | + /> | ||
| 23 | + </el-scrollbar> | ||
| 22 | </el-card> | 24 | </el-card> |
| 23 | <el-card class="w-4/5 user" style="margin-left: 10px" :gutter="12" shadow="hover"> | 25 | <el-card class="w-4/5 user" style="margin-left: 10px" :gutter="12" shadow="hover"> |
| 24 | <template #header> | 26 | <template #header> |
| @@ -534,8 +536,8 @@ onMounted(async () => { | @@ -534,8 +536,8 @@ onMounted(async () => { | ||
| 534 | 536 | ||
| 535 | <style scoped> | 537 | <style scoped> |
| 536 | .user { | 538 | .user { |
| 537 | - height: 900px; | ||
| 538 | - max-height: 960px; | 539 | + height: 780px; |
| 540 | + max-height: 800px; | ||
| 539 | } | 541 | } |
| 540 | .card-header { | 542 | .card-header { |
| 541 | display: flex; | 543 | display: flex; |
yudao-ui-admin-vue3/types/env.d.ts
| @@ -11,6 +11,7 @@ interface ImportMetaEnv { | @@ -11,6 +11,7 @@ interface ImportMetaEnv { | ||
| 11 | readonly VITE_APP_TITLE: string | 11 | readonly VITE_APP_TITLE: string |
| 12 | readonly VITE_PORT: number | 12 | readonly VITE_PORT: number |
| 13 | readonly VITE_OPEN: string | 13 | readonly VITE_OPEN: string |
| 14 | + readonly VITE_DEV: boolean | ||
| 14 | readonly VITE_ROUTE_ALWAYSSHOW_ENABLE: string | 15 | readonly VITE_ROUTE_ALWAYSSHOW_ENABLE: string |
| 15 | readonly VITE_APP_CAPTCHA_ENABLE: string | 16 | readonly VITE_APP_CAPTCHA_ENABLE: string |
| 16 | readonly VITE_APP_TENANT_ENABLE: string | 17 | readonly VITE_APP_TENANT_ENABLE: string |
yudao-ui-admin/package.json
| @@ -49,7 +49,7 @@ | @@ -49,7 +49,7 @@ | ||
| 49 | "core-js": "^3.26.0", | 49 | "core-js": "^3.26.0", |
| 50 | "crypto-js": "^4.0.0", | 50 | "crypto-js": "^4.0.0", |
| 51 | "echarts": "5.4.0", | 51 | "echarts": "5.4.0", |
| 52 | - "element-ui": "2.15.10", | 52 | + "element-ui": "2.15.12", |
| 53 | "file-saver": "2.0.5", | 53 | "file-saver": "2.0.5", |
| 54 | "fuse.js": "6.6.2", | 54 | "fuse.js": "6.6.2", |
| 55 | "highlight.js": "9.18.5", | 55 | "highlight.js": "9.18.5", |
yudao-ui-admin/src/api/system/mail/account.js
0 → 100755
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 创建邮箱账号 | ||
| 4 | +export function createMailAccount(data) { | ||
| 5 | + return request({ | ||
| 6 | + url: '/system/mail-account/create', | ||
| 7 | + method: 'post', | ||
| 8 | + data: data | ||
| 9 | + }) | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +// 更新邮箱账号 | ||
| 13 | +export function updateMailAccount(data) { | ||
| 14 | + return request({ | ||
| 15 | + url: '/system/mail-account/update', | ||
| 16 | + method: 'put', | ||
| 17 | + data: data | ||
| 18 | + }) | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +// 删除邮箱账号 | ||
| 22 | +export function deleteMailAccount(id) { | ||
| 23 | + return request({ | ||
| 24 | + url: '/system/mail-account/delete?id=' + id, | ||
| 25 | + method: 'delete' | ||
| 26 | + }) | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +// 获得邮箱账号 | ||
| 30 | +export function getMailAccount(id) { | ||
| 31 | + return request({ | ||
| 32 | + url: '/system/mail-account/get?id=' + id, | ||
| 33 | + method: 'get' | ||
| 34 | + }) | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +// 获得邮箱账号分页 | ||
| 38 | +export function getMailAccountPage(query) { | ||
| 39 | + return request({ | ||
| 40 | + url: '/system/mail-account/page', | ||
| 41 | + method: 'get', | ||
| 42 | + params: query | ||
| 43 | + }) | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +// 获取邮箱账号的精简信息列表 | ||
| 47 | +export function getSimpleMailAccountList() { | ||
| 48 | + return request({ | ||
| 49 | + url: '/system/mail-account/list-all-simple', | ||
| 50 | + method: 'get', | ||
| 51 | + }) | ||
| 52 | +} |
yudao-ui-admin/src/api/system/mail/log.js
0 → 100755
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获得邮件日志 | ||
| 4 | +export function getMailLog(id) { | ||
| 5 | + return request({ | ||
| 6 | + url: '/system/mail-log/get?id=' + id, | ||
| 7 | + method: 'get' | ||
| 8 | + }) | ||
| 9 | +} | ||
| 10 | + | ||
| 11 | +// 获得邮件日志分页 | ||
| 12 | +export function getMailLogPage(query) { | ||
| 13 | + return request({ | ||
| 14 | + url: '/system/mail-log/page', | ||
| 15 | + method: 'get', | ||
| 16 | + params: query | ||
| 17 | + }) | ||
| 18 | +} |
yudao-ui-admin/src/api/system/mail/template.js
0 → 100755
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 创建邮件模版 | ||
| 4 | +export function createMailTemplate(data) { | ||
| 5 | + return request({ | ||
| 6 | + url: '/system/mail-template/create', | ||
| 7 | + method: 'post', | ||
| 8 | + data: data | ||
| 9 | + }) | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +// 更新邮件模版 | ||
| 13 | +export function updateMailTemplate(data) { | ||
| 14 | + return request({ | ||
| 15 | + url: '/system/mail-template/update', | ||
| 16 | + method: 'put', | ||
| 17 | + data: data | ||
| 18 | + }) | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +// 删除邮件模版 | ||
| 22 | +export function deleteMailTemplate(id) { | ||
| 23 | + return request({ | ||
| 24 | + url: '/system/mail-template/delete?id=' + id, | ||
| 25 | + method: 'delete' | ||
| 26 | + }) | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +// 获得邮件模版 | ||
| 30 | +export function getMailTemplate(id) { | ||
| 31 | + return request({ | ||
| 32 | + url: '/system/mail-template/get?id=' + id, | ||
| 33 | + method: 'get' | ||
| 34 | + }) | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +// 获得邮件模版分页 | ||
| 38 | +export function getMailTemplatePage(query) { | ||
| 39 | + return request({ | ||
| 40 | + url: '/system/mail-template/page', | ||
| 41 | + method: 'get', | ||
| 42 | + params: query | ||
| 43 | + }) | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +// 发送测试邮件 | ||
| 47 | +export function sendMail(data) { | ||
| 48 | + return request({ | ||
| 49 | + url: '/system/mail-template/send-mail', | ||
| 50 | + method: 'post', | ||
| 51 | + data: data | ||
| 52 | + }) | ||
| 53 | +} |
yudao-ui-admin/src/api/system/sms/smsTemplate.js
| @@ -43,7 +43,7 @@ export function getSmsTemplatePage(query) { | @@ -43,7 +43,7 @@ export function getSmsTemplatePage(query) { | ||
| 43 | }) | 43 | }) |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | -// 创建短信模板 | 46 | +// 发送测试短信 |
| 47 | export function sendSms(data) { | 47 | export function sendSms(data) { |
| 48 | return request({ | 48 | return request({ |
| 49 | url: '/system/sms-template/send-sms', | 49 | url: '/system/sms-template/send-sms', |
yudao-ui-admin/src/components/TopNav/index.vue
| @@ -133,7 +133,9 @@ export default { | @@ -133,7 +133,9 @@ export default { | ||
| 133 | } else { | 133 | } else { |
| 134 | // 显示左侧联动菜单 | 134 | // 显示左侧联动菜单 |
| 135 | this.activeRoutes(key); | 135 | this.activeRoutes(key); |
| 136 | - this.$store.dispatch('app/toggleSideBarHide', false); | 136 | + if (!this.$route.meta.link) { |
| 137 | + this.$store.dispatch('app/toggleSideBarHide', false); | ||
| 138 | + } | ||
| 137 | } | 139 | } |
| 138 | }, | 140 | }, |
| 139 | // 当前激活的路由 | 141 | // 当前激活的路由 |
| @@ -149,7 +151,7 @@ export default { | @@ -149,7 +151,7 @@ export default { | ||
| 149 | if(routes.length > 0) { | 151 | if(routes.length > 0) { |
| 150 | this.$store.commit("SET_SIDEBAR_ROUTERS", routes); | 152 | this.$store.commit("SET_SIDEBAR_ROUTERS", routes); |
| 151 | } else { | 153 | } else { |
| 152 | - this.$store.dispatch("app/toggleSideBarHide", true); | 154 | + this.$store.dispatch('app/toggleSideBarHide', true); |
| 153 | } | 155 | } |
| 154 | }, | 156 | }, |
| 155 | ishttp(url) { | 157 | ishttp(url) { |
yudao-ui-admin/src/utils/dict.js
| @@ -25,6 +25,7 @@ export const DICT_TYPE = { | @@ -25,6 +25,7 @@ export const DICT_TYPE = { | ||
| 25 | SYSTEM_SMS_RECEIVE_STATUS: 'system_sms_receive_status', | 25 | SYSTEM_SMS_RECEIVE_STATUS: 'system_sms_receive_status', |
| 26 | SYSTEM_ERROR_CODE_TYPE: 'system_error_code_type', | 26 | SYSTEM_ERROR_CODE_TYPE: 'system_error_code_type', |
| 27 | SYSTEM_OAUTH2_GRANT_TYPE: 'system_oauth2_grant_type', | 27 | SYSTEM_OAUTH2_GRANT_TYPE: 'system_oauth2_grant_type', |
| 28 | + SYSTEM_MAIL_SEND_STATUS: 'system_mail_send_status', | ||
| 28 | 29 | ||
| 29 | // ========== INFRA 模块 ========== | 30 | // ========== INFRA 模块 ========== |
| 30 | INFRA_BOOLEAN_STRING: 'infra_boolean_string', | 31 | INFRA_BOOLEAN_STRING: 'infra_boolean_string', |
yudao-ui-admin/src/views/system/mail/account/index.vue
0 → 100755
| 1 | +<template> | ||
| 2 | + <div class="app-container"> | ||
| 3 | + <doc-alert title="邮件配置" url="https://doc.iocoder.cn/mail" /> | ||
| 4 | + | ||
| 5 | + <!-- 搜索工作栏 --> | ||
| 6 | + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> | ||
| 7 | + <el-form-item label="邮箱" prop="mail"> | ||
| 8 | + <el-input v-model="queryParams.mail" placeholder="请输入邮箱" clearable @keyup.enter.native="handleQuery"/> | ||
| 9 | + </el-form-item> | ||
| 10 | + <el-form-item label="用户名" prop="username"> | ||
| 11 | + <el-input v-model="queryParams.username" placeholder="请输入用户名" clearable @keyup.enter.native="handleQuery"/> | ||
| 12 | + </el-form-item> | ||
| 13 | + <el-form-item> | ||
| 14 | + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | ||
| 15 | + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> | ||
| 16 | + </el-form-item> | ||
| 17 | + </el-form> | ||
| 18 | + | ||
| 19 | + <!-- 操作工具栏 --> | ||
| 20 | + <el-row :gutter="10" class="mb8"> | ||
| 21 | + <el-col :span="1.5"> | ||
| 22 | + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" | ||
| 23 | + v-hasPermi="['system:mail-account:create']">新增</el-button> | ||
| 24 | + </el-col> | ||
| 25 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | ||
| 26 | + </el-row> | ||
| 27 | + | ||
| 28 | + <!-- 列表 --> | ||
| 29 | + <el-table v-loading="loading" :data="list"> | ||
| 30 | + <el-table-column label="编号" align="center" prop="id" /> | ||
| 31 | + <el-table-column label="邮箱" align="center" prop="mail" /> | ||
| 32 | + <el-table-column label="用户名" align="center" prop="username" /> | ||
| 33 | + <el-table-column label="SMTP 服务器域名" align="center" prop="host" /> | ||
| 34 | + <el-table-column label="SMTP 服务器端口" align="center" prop="port" /> | ||
| 35 | + <el-table-column label="是否开启 SSL" align="center" prop="sslEnable"> | ||
| 36 | + <template v-slot="scope"> | ||
| 37 | + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.sslEnable" /> | ||
| 38 | + </template> | ||
| 39 | + </el-table-column> | ||
| 40 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | ||
| 41 | + <template v-slot="scope"> | ||
| 42 | + <span>{{ parseTime(scope.row.createTime) }}</span> | ||
| 43 | + </template> | ||
| 44 | + </el-table-column> | ||
| 45 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||
| 46 | + <template v-slot="scope"> | ||
| 47 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | ||
| 48 | + v-hasPermi="['system:mail-account:update']">修改</el-button> | ||
| 49 | + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | ||
| 50 | + v-hasPermi="['system:mail-account:delete']">删除</el-button> | ||
| 51 | + </template> | ||
| 52 | + </el-table-column> | ||
| 53 | + </el-table> | ||
| 54 | + <!-- 分页组件 --> | ||
| 55 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | ||
| 56 | + @pagination="getList"/> | ||
| 57 | + | ||
| 58 | + <!-- 对话框(添加 / 修改) --> | ||
| 59 | + <el-dialog :title="title" :visible.sync="open" width="500px" v-dialogDrag append-to-body> | ||
| 60 | + <el-form ref="form" :model="form" :rules="rules" label-width="140px"> | ||
| 61 | + <el-form-item label="邮箱" prop="mail"> | ||
| 62 | + <el-input v-model="form.mail" placeholder="请输入邮箱" /> | ||
| 63 | + </el-form-item> | ||
| 64 | + <el-form-item label="用户名" prop="username"> | ||
| 65 | + <el-input v-model="form.username" placeholder="请输入用户名,一般和邮箱一致" /> | ||
| 66 | + </el-form-item> | ||
| 67 | + <el-form-item label="密码" prop="password"> | ||
| 68 | + <el-input v-model="form.password" placeholder="请输入密码" /> | ||
| 69 | + </el-form-item> | ||
| 70 | + <el-form-item label="SMTP 服务器域名" prop="host"> | ||
| 71 | + <el-input v-model="form.host" placeholder="请输入 SMTP 服务器域名" /> | ||
| 72 | + </el-form-item> | ||
| 73 | + <el-form-item label="SMTP 服务器端口" prop="port"> | ||
| 74 | + <el-input v-model="form.port" placeholder="请输入 SMTP 服务器端口" /> | ||
| 75 | + </el-form-item> | ||
| 76 | + <el-form-item label="是否开启 SSL" prop="sslEnable"> | ||
| 77 | + <el-radio-group v-model="form.sslEnable"> | ||
| 78 | + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_BOOLEAN_STRING)" | ||
| 79 | + :key="dict.value" :label="dict.value === 'true'">{{dict.label}}</el-radio> | ||
| 80 | + </el-radio-group> | ||
| 81 | + </el-form-item> | ||
| 82 | + </el-form> | ||
| 83 | + <div slot="footer" class="dialog-footer"> | ||
| 84 | + <el-button type="primary" @click="submitForm">确 定</el-button> | ||
| 85 | + <el-button @click="cancel">取 消</el-button> | ||
| 86 | + </div> | ||
| 87 | + </el-dialog> | ||
| 88 | + </div> | ||
| 89 | +</template> | ||
| 90 | + | ||
| 91 | +<script> | ||
| 92 | +import { createMailAccount, updateMailAccount, deleteMailAccount, getMailAccount, getMailAccountPage } from "@/api/system/mail/account"; | ||
| 93 | + | ||
| 94 | +export default { | ||
| 95 | + name: "MailAccount", | ||
| 96 | + components: { | ||
| 97 | + }, | ||
| 98 | + data() { | ||
| 99 | + return { | ||
| 100 | + // 遮罩层 | ||
| 101 | + loading: true, | ||
| 102 | + // 显示搜索条件 | ||
| 103 | + showSearch: true, | ||
| 104 | + // 总条数 | ||
| 105 | + total: 0, | ||
| 106 | + // 邮箱账号列表 | ||
| 107 | + list: [], | ||
| 108 | + // 弹出层标题 | ||
| 109 | + title: "", | ||
| 110 | + // 是否显示弹出层 | ||
| 111 | + open: false, | ||
| 112 | + // 查询参数 | ||
| 113 | + queryParams: { | ||
| 114 | + pageNo: 1, | ||
| 115 | + pageSize: 10, | ||
| 116 | + mail: null, | ||
| 117 | + username: null | ||
| 118 | + }, | ||
| 119 | + // 表单参数 | ||
| 120 | + form: {}, | ||
| 121 | + // 表单校验 | ||
| 122 | + rules: { | ||
| 123 | + mail: [{ required: true, message: "邮箱不能为空", trigger: "blur" }], | ||
| 124 | + username: [{ required: true, message: "用户名不能为空", trigger: "blur" }], | ||
| 125 | + password: [{ required: true, message: "密码不能为空", trigger: "blur" }], | ||
| 126 | + host: [{ required: true, message: "SMTP 服务器域名不能为空", trigger: "blur" }], | ||
| 127 | + port: [{ required: true, message: "SMTP 服务器端口不能为空", trigger: "blur" }], | ||
| 128 | + sslEnable: [{ required: true, message: "是否开启 SSL不能为空", trigger: "blur" }], | ||
| 129 | + }, | ||
| 130 | + }; | ||
| 131 | + }, | ||
| 132 | + created() { | ||
| 133 | + this.getList(); | ||
| 134 | + }, | ||
| 135 | + methods: { | ||
| 136 | + /** 查询列表 */ | ||
| 137 | + getList() { | ||
| 138 | + this.loading = true; | ||
| 139 | + // 执行查询 | ||
| 140 | + getMailAccountPage(this.queryParams).then(response => { | ||
| 141 | + this.list = response.data.list; | ||
| 142 | + this.total = response.data.total; | ||
| 143 | + this.loading = false; | ||
| 144 | + }); | ||
| 145 | + }, | ||
| 146 | + /** 取消按钮 */ | ||
| 147 | + cancel() { | ||
| 148 | + this.open = false; | ||
| 149 | + this.reset(); | ||
| 150 | + }, | ||
| 151 | + /** 表单重置 */ | ||
| 152 | + reset() { | ||
| 153 | + this.form = { | ||
| 154 | + id: undefined, | ||
| 155 | + mail: undefined, | ||
| 156 | + username: undefined, | ||
| 157 | + password: undefined, | ||
| 158 | + host: undefined, | ||
| 159 | + port: undefined, | ||
| 160 | + sslEnable: true, | ||
| 161 | + }; | ||
| 162 | + this.resetForm("form"); | ||
| 163 | + }, | ||
| 164 | + /** 搜索按钮操作 */ | ||
| 165 | + handleQuery() { | ||
| 166 | + this.queryParams.pageNo = 1; | ||
| 167 | + this.getList(); | ||
| 168 | + }, | ||
| 169 | + /** 重置按钮操作 */ | ||
| 170 | + resetQuery() { | ||
| 171 | + this.resetForm("queryForm"); | ||
| 172 | + this.handleQuery(); | ||
| 173 | + }, | ||
| 174 | + /** 新增按钮操作 */ | ||
| 175 | + handleAdd() { | ||
| 176 | + this.reset(); | ||
| 177 | + this.open = true; | ||
| 178 | + this.title = "添加邮箱账号"; | ||
| 179 | + }, | ||
| 180 | + /** 修改按钮操作 */ | ||
| 181 | + handleUpdate(row) { | ||
| 182 | + this.reset(); | ||
| 183 | + const id = row.id; | ||
| 184 | + getMailAccount(id).then(response => { | ||
| 185 | + this.form = response.data; | ||
| 186 | + this.open = true; | ||
| 187 | + this.title = "修改邮箱账号"; | ||
| 188 | + }); | ||
| 189 | + }, | ||
| 190 | + /** 提交按钮 */ | ||
| 191 | + submitForm() { | ||
| 192 | + this.$refs["form"].validate(valid => { | ||
| 193 | + if (!valid) { | ||
| 194 | + return; | ||
| 195 | + } | ||
| 196 | + // 修改的提交 | ||
| 197 | + if (this.form.id != null) { | ||
| 198 | + updateMailAccount(this.form).then(response => { | ||
| 199 | + this.$modal.msgSuccess("修改成功"); | ||
| 200 | + this.open = false; | ||
| 201 | + this.getList(); | ||
| 202 | + }); | ||
| 203 | + return; | ||
| 204 | + } | ||
| 205 | + // 添加的提交 | ||
| 206 | + createMailAccount(this.form).then(response => { | ||
| 207 | + this.$modal.msgSuccess("新增成功"); | ||
| 208 | + this.open = false; | ||
| 209 | + this.getList(); | ||
| 210 | + }); | ||
| 211 | + }); | ||
| 212 | + }, | ||
| 213 | + /** 删除按钮操作 */ | ||
| 214 | + handleDelete(row) { | ||
| 215 | + const id = row.id; | ||
| 216 | + this.$modal.confirm('是否确认删除邮箱账号编号为"' + id + '"的数据项?').then(function() { | ||
| 217 | + return deleteMailAccount(id); | ||
| 218 | + }).then(() => { | ||
| 219 | + this.getList(); | ||
| 220 | + this.$modal.msgSuccess("删除成功"); | ||
| 221 | + }).catch(() => {}); | ||
| 222 | + } | ||
| 223 | + } | ||
| 224 | +}; | ||
| 225 | +</script> |
yudao-ui-admin/src/views/system/mail/log/index.vue
0 → 100755
| 1 | +<template> | ||
| 2 | + <div class="app-container"> | ||
| 3 | + <doc-alert title="邮件配置" url="https://doc.iocoder.cn/mail" /> | ||
| 4 | + | ||
| 5 | + <!-- 搜索工作栏 --> | ||
| 6 | + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> | ||
| 7 | + <el-form-item label="接收邮箱" prop="toMail"> | ||
| 8 | + <el-input v-model="queryParams.toMail" placeholder="请输入接收邮箱" clearable @keyup.enter.native="handleQuery"/> | ||
| 9 | + </el-form-item> | ||
| 10 | + <el-form-item label="邮箱账号" prop="accountId"> | ||
| 11 | + <el-select v-model="queryParams.accountId" placeholder="请输入邮箱账号" clearable> | ||
| 12 | + <el-option v-for="account in accountOptions" :key="account.id" :value="account.id" :label="account.mail" /> | ||
| 13 | + </el-select> | ||
| 14 | + </el-form-item> | ||
| 15 | + <el-form-item label="模板编号" prop="templateId"> | ||
| 16 | + <el-input v-model="queryParams.templateId" placeholder="请输入模板编号" clearable @keyup.enter.native="handleQuery"/> | ||
| 17 | + </el-form-item> | ||
| 18 | + <el-form-item label="发送状态" prop="sendStatus"> | ||
| 19 | + <el-select v-model="queryParams.sendStatus" placeholder="请选择发送状态" clearable size="small"> | ||
| 20 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYSTEM_MAIL_SEND_STATUS)" | ||
| 21 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 22 | + </el-select> | ||
| 23 | + </el-form-item> | ||
| 24 | + <el-form-item label="发送时间" prop="sendTime"> | ||
| 25 | + <el-date-picker v-model="queryParams.sendTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" | ||
| 26 | + range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" /> | ||
| 27 | + </el-form-item> | ||
| 28 | + <el-form-item label="用户编号" prop="userId"> | ||
| 29 | + <el-input v-model="queryParams.userId" placeholder="请输入用户编号" clearable @keyup.enter.native="handleQuery"/> | ||
| 30 | + </el-form-item> | ||
| 31 | + <el-form-item label="用户类型" prop="userType"> | ||
| 32 | + <el-select v-model="queryParams.userType" placeholder="请选择用户类型" clearable> | ||
| 33 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.USER_TYPE)" | ||
| 34 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 35 | + </el-select> | ||
| 36 | + </el-form-item> | ||
| 37 | + <el-form-item> | ||
| 38 | + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | ||
| 39 | + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> | ||
| 40 | + </el-form-item> | ||
| 41 | + </el-form> | ||
| 42 | + | ||
| 43 | + <!-- 操作工具栏 --> | ||
| 44 | + <el-row :gutter="10" class="mb8"> | ||
| 45 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | ||
| 46 | + </el-row> | ||
| 47 | + | ||
| 48 | + <!-- 列表 --> | ||
| 49 | + <el-table v-loading="loading" :data="list"> | ||
| 50 | + <el-table-column label="编号" align="center" prop="id" /> | ||
| 51 | + <el-table-column label="发送时间" align="center" prop="sendTime" width="180"> | ||
| 52 | + <template v-slot="scope"> | ||
| 53 | + <span>{{ parseTime(scope.row.sendTime) }}</span> | ||
| 54 | + </template> | ||
| 55 | + </el-table-column> | ||
| 56 | + <el-table-column label="接收邮箱" align="center" prop="toMail" width="200"> | ||
| 57 | + <template v-slot="scope"> | ||
| 58 | + <div>{{ scope.row.toMail }}</div> | ||
| 59 | + <div v-if="scope.row.userType && scope.row.userId"> | ||
| 60 | + <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType"/>{{ '(' + scope.row.userId + ')' }} | ||
| 61 | + </div> | ||
| 62 | + </template> | ||
| 63 | + </el-table-column> | ||
| 64 | + <el-table-column label="邮件标题" align="center" prop="templateTitle" /> | ||
| 65 | + <el-table-column label="发送状态" align="center" prop="sendStatus"> | ||
| 66 | + <template v-slot="scope"> | ||
| 67 | + <dict-tag :type="DICT_TYPE.SYSTEM_MAIL_SEND_STATUS" :value="scope.row.sendStatus" /> | ||
| 68 | + </template> | ||
| 69 | + </el-table-column> | ||
| 70 | + <el-table-column label="邮箱账号" align="center" prop="fromMail" /> | ||
| 71 | + <el-table-column label="模板编号" align="center" prop="templateId" /> | ||
| 72 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||
| 73 | + <template v-slot="scope"> | ||
| 74 | + <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)" | ||
| 75 | + v-hasPermi="['system:mail-log:query']">详细</el-button> | ||
| 76 | + </template> | ||
| 77 | + </el-table-column> | ||
| 78 | + </el-table> | ||
| 79 | + <!-- 分页组件 --> | ||
| 80 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | ||
| 81 | + @pagination="getList"/> | ||
| 82 | + | ||
| 83 | + <!-- 邮件日志详细--> | ||
| 84 | + <el-dialog :title="title" :visible.sync="open" width="700px" v-dialogDrag append-to-body> | ||
| 85 | + <el-form ref="form" :model="form" label-width="160px"> | ||
| 86 | + <el-row> | ||
| 87 | + <el-col :span="24"> | ||
| 88 | + <el-form-item label="日志主键:">{{ form.id }}</el-form-item> | ||
| 89 | + <el-form-item label="用户编号:">{{ form.userId }}</el-form-item> | ||
| 90 | + <el-form-item label="用户类型:"> | ||
| 91 | + <dict-tag :type="DICT_TYPE.USER_TYPE" :value="form.userType"/> | ||
| 92 | + </el-form-item> | ||
| 93 | + <el-form-item label="接收邮箱地址:">{{ form.toMail }}</el-form-item> | ||
| 94 | + <el-form-item label="邮箱账号编号:">{{ form.accountId }}</el-form-item> | ||
| 95 | + <el-form-item label="发送邮箱地址:">{{ form.fromMail }}</el-form-item> | ||
| 96 | + <el-form-item label="模板编号:">{{ form.templateId }}</el-form-item> | ||
| 97 | + <el-form-item label="模板编码:">{{ form.templateCode }}</el-form-item> | ||
| 98 | + <el-form-item label="模版发送人名称:">{{ form.templateNickname }}</el-form-item> | ||
| 99 | + <el-form-item label="邮件标题:">{{ form.templateTitle }}</el-form-item> | ||
| 100 | + <el-form-item label="邮件内容:"> | ||
| 101 | + <editor v-model="form.templateContent" :min-height="192" read-only /> | ||
| 102 | + </el-form-item> | ||
| 103 | + <el-form-item label="邮件参数:">{{ form.templateParams }}</el-form-item> | ||
| 104 | + <el-form-item label="发送状态:"> | ||
| 105 | + <dict-tag :type="DICT_TYPE.SYSTEM_MAIL_SEND_STATUS" :value="form.sendStatus" /> | ||
| 106 | + </el-form-item> | ||
| 107 | + <el-form-item label="发送时间:">{{ parseTime(form.sendTime) }}</el-form-item> | ||
| 108 | + <el-form-item label="发送返回的消息编号:">{{ form.sendMessageId }}</el-form-item> | ||
| 109 | + <el-form-item label="发送异常:">{{ form.sendException }}</el-form-item> | ||
| 110 | + </el-col> | ||
| 111 | + </el-row> | ||
| 112 | + </el-form> | ||
| 113 | + <div slot="footer" class="dialog-footer"> | ||
| 114 | + <el-button @click="open = false">关 闭</el-button> | ||
| 115 | + </div> | ||
| 116 | + </el-dialog> | ||
| 117 | + </div> | ||
| 118 | +</template> | ||
| 119 | + | ||
| 120 | +<script> | ||
| 121 | +import { getMailLog, getMailLogPage } from "@/api/system/mail/log"; | ||
| 122 | +import Editor from '@/components/Editor'; | ||
| 123 | +import { getSimpleMailAccountList } from "@/api/system/mail/account"; | ||
| 124 | + | ||
| 125 | +export default { | ||
| 126 | + name: "MailLog", | ||
| 127 | + components: { | ||
| 128 | + Editor, | ||
| 129 | + }, | ||
| 130 | + data() { | ||
| 131 | + return { | ||
| 132 | + // 遮罩层 | ||
| 133 | + loading: true, | ||
| 134 | + // 导出遮罩层 | ||
| 135 | + exportLoading: false, | ||
| 136 | + // 显示搜索条件 | ||
| 137 | + showSearch: true, | ||
| 138 | + // 总条数 | ||
| 139 | + total: 0, | ||
| 140 | + // 邮件日志列表 | ||
| 141 | + list: [], | ||
| 142 | + // 弹出层标题 | ||
| 143 | + title: "", | ||
| 144 | + // 是否显示弹出层 | ||
| 145 | + open: false, | ||
| 146 | + // 查询参数 | ||
| 147 | + queryParams: { | ||
| 148 | + pageNo: 1, | ||
| 149 | + pageSize: 10, | ||
| 150 | + userId: null, | ||
| 151 | + userType: null, | ||
| 152 | + toMail: null, | ||
| 153 | + accountId: null, | ||
| 154 | + templateId: null, | ||
| 155 | + sendStatus: null, | ||
| 156 | + sendTime: [], | ||
| 157 | + }, | ||
| 158 | + // 表单参数 | ||
| 159 | + form: {}, | ||
| 160 | + // 邮箱账号 | ||
| 161 | + accountOptions: [] | ||
| 162 | + }; | ||
| 163 | + }, | ||
| 164 | + created() { | ||
| 165 | + this.getList(); | ||
| 166 | + // 获得邮箱账号列表 | ||
| 167 | + getSimpleMailAccountList().then(response => { | ||
| 168 | + this.accountOptions = response.data | ||
| 169 | + }) | ||
| 170 | + }, | ||
| 171 | + methods: { | ||
| 172 | + /** 查询列表 */ | ||
| 173 | + getList() { | ||
| 174 | + this.loading = true; | ||
| 175 | + // 执行查询 | ||
| 176 | + getMailLogPage(this.queryParams).then(response => { | ||
| 177 | + this.list = response.data.list; | ||
| 178 | + this.total = response.data.total; | ||
| 179 | + this.loading = false; | ||
| 180 | + }); | ||
| 181 | + }, | ||
| 182 | + /** 取消按钮 */ | ||
| 183 | + cancel() { | ||
| 184 | + this.open = false; | ||
| 185 | + this.reset(); | ||
| 186 | + }, | ||
| 187 | + /** 表单重置 */ | ||
| 188 | + reset() { | ||
| 189 | + this.form = { | ||
| 190 | + id: undefined, | ||
| 191 | + userId: undefined, | ||
| 192 | + userType: undefined, | ||
| 193 | + toMail: undefined, | ||
| 194 | + accountId: undefined, | ||
| 195 | + fromMail: undefined, | ||
| 196 | + templateId: undefined, | ||
| 197 | + templateCode: undefined, | ||
| 198 | + templateNickname: undefined, | ||
| 199 | + templateTitle: undefined, | ||
| 200 | + templateContent: undefined, | ||
| 201 | + templateParams: undefined, | ||
| 202 | + sendStatus: undefined, | ||
| 203 | + sendTime: undefined, | ||
| 204 | + sendMessageId: undefined, | ||
| 205 | + sendException: undefined, | ||
| 206 | + }; | ||
| 207 | + this.resetForm("form"); | ||
| 208 | + }, | ||
| 209 | + /** 搜索按钮操作 */ | ||
| 210 | + handleQuery() { | ||
| 211 | + this.queryParams.pageNo = 1; | ||
| 212 | + this.getList(); | ||
| 213 | + }, | ||
| 214 | + /** 重置按钮操作 */ | ||
| 215 | + resetQuery() { | ||
| 216 | + this.resetForm("queryForm"); | ||
| 217 | + this.handleQuery(); | ||
| 218 | + }, | ||
| 219 | + /** 详细按钮操作 */ | ||
| 220 | + handleView(row) { | ||
| 221 | + this.open = true; | ||
| 222 | + this.form = row; | ||
| 223 | + } | ||
| 224 | + } | ||
| 225 | +}; | ||
| 226 | +</script> |
yudao-ui-admin/src/views/system/mail/template/index.vue
0 → 100755
| 1 | +<template> | ||
| 2 | + <div class="app-container"> | ||
| 3 | + <doc-alert title="邮件配置" url="https://doc.iocoder.cn/mail" /> | ||
| 4 | + | ||
| 5 | + <!-- 搜索工作栏 --> | ||
| 6 | + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> | ||
| 7 | + <el-form-item label="模板名称" prop="name"> | ||
| 8 | + <el-input v-model="queryParams.name" placeholder="请输入模板名称" clearable @keyup.enter.native="handleQuery"/> | ||
| 9 | + </el-form-item> | ||
| 10 | + <el-form-item label="模板编码" prop="code"> | ||
| 11 | + <el-input v-model="queryParams.code" placeholder="请输入模板编码" clearable @keyup.enter.native="handleQuery"/> | ||
| 12 | + </el-form-item> | ||
| 13 | + <el-form-item label="邮箱账号" prop="accountId"> | ||
| 14 | + <el-select v-model="queryParams.accountId" placeholder="请输入邮箱账号" clearable> | ||
| 15 | + <el-option v-for="account in accountOptions" :key="account.id" :value="account.id" :label="account.mail" /> | ||
| 16 | + </el-select> | ||
| 17 | + </el-form-item> | ||
| 18 | + <el-form-item label="开启状态" prop="status"> | ||
| 19 | + <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable size="small"> | ||
| 20 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" | ||
| 21 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 22 | + </el-select> | ||
| 23 | + </el-form-item> | ||
| 24 | + <el-form-item label="创建时间" prop="createTime"> | ||
| 25 | + <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" | ||
| 26 | + range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" /> | ||
| 27 | + </el-form-item> | ||
| 28 | + <el-form-item> | ||
| 29 | + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | ||
| 30 | + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> | ||
| 31 | + </el-form-item> | ||
| 32 | + </el-form> | ||
| 33 | + | ||
| 34 | + <!-- 操作工具栏 --> | ||
| 35 | + <el-row :gutter="10" class="mb8"> | ||
| 36 | + <el-col :span="1.5"> | ||
| 37 | + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" | ||
| 38 | + v-hasPermi="['system:mail-template:create']">新增</el-button> | ||
| 39 | + </el-col> | ||
| 40 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | ||
| 41 | + </el-row> | ||
| 42 | + | ||
| 43 | + <!-- 列表 --> | ||
| 44 | + <el-table v-loading="loading" :data="list"> | ||
| 45 | + <el-table-column label="模板编码" align="center" prop="code" /> | ||
| 46 | + <el-table-column label="模板名称" align="center" prop="name" /> | ||
| 47 | + <el-table-column label="模板标题" align="center" prop="title" /> | ||
| 48 | + <el-table-column label="模板内容" align="center" prop="content" :show-overflow-tooltip="true" /> | ||
| 49 | + <el-table-column label="邮箱账号" align="center" prop="accountId" width="200"> | ||
| 50 | + <template v-slot="scope"> | ||
| 51 | + {{ accountOptions.find(account => account.id === scope.row.accountId)?.mail }} | ||
| 52 | + </template> | ||
| 53 | + </el-table-column> | ||
| 54 | + <el-table-column label="发送人名称" align="center" prop="nickname" /> | ||
| 55 | + <el-table-column label="开启状态" align="center" prop="status"> | ||
| 56 | + <template v-slot="scope"> | ||
| 57 | + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> | ||
| 58 | + </template> | ||
| 59 | + </el-table-column> | ||
| 60 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | ||
| 61 | + <template v-slot="scope"> | ||
| 62 | + <span>{{ parseTime(scope.row.createTime) }}</span> | ||
| 63 | + </template> | ||
| 64 | + </el-table-column> | ||
| 65 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150"> | ||
| 66 | + <template v-slot="scope"> | ||
| 67 | + <el-button size="mini" type="text" icon="el-icon-share" @click="handleSend(scope.row)" | ||
| 68 | + v-hasPermi="['system:mail-template:send-mail']">测试</el-button> | ||
| 69 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | ||
| 70 | + v-hasPermi="['system:mail-template:update']">修改</el-button> | ||
| 71 | + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | ||
| 72 | + v-hasPermi="['system:mail-template:delete']">删除</el-button> | ||
| 73 | + </template> | ||
| 74 | + </el-table-column> | ||
| 75 | + </el-table> | ||
| 76 | + <!-- 分页组件 --> | ||
| 77 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | ||
| 78 | + @pagination="getList"/> | ||
| 79 | + | ||
| 80 | + <!-- 对话框(添加 / 修改) --> | ||
| 81 | + <el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body> | ||
| 82 | + <el-form ref="form" :model="form" :rules="rules" label-width="100px"> | ||
| 83 | + <el-form-item label="模板名称" prop="name"> | ||
| 84 | + <el-input v-model="form.name" placeholder="请输入模板名称" /> | ||
| 85 | + </el-form-item> | ||
| 86 | + <el-form-item label="模板编码" prop="code"> | ||
| 87 | + <el-input v-model="form.code" placeholder="请输入模板编码" /> | ||
| 88 | + </el-form-item> | ||
| 89 | + <el-form-item label="邮箱账号" prop="accountId"> | ||
| 90 | + <el-select v-model="form.accountId" placeholder="请输入邮箱账号"> | ||
| 91 | + <el-option v-for="account in accountOptions" :key="account.id" :value="account.id" :label="account.mail" /> | ||
| 92 | + </el-select> | ||
| 93 | + </el-form-item> | ||
| 94 | + <el-form-item label="发送人名称" prop="nickname"> | ||
| 95 | + <el-input v-model="form.nickname" placeholder="请输入发送人名称" /> | ||
| 96 | + </el-form-item> | ||
| 97 | + <el-form-item label="模板标题" prop="title"> | ||
| 98 | + <el-input v-model="form.title" placeholder="请输入模板标题" /> | ||
| 99 | + </el-form-item> | ||
| 100 | + <el-form-item label="模板内容"> | ||
| 101 | + <editor v-model="form.content" :min-height="192"/> | ||
| 102 | + </el-form-item> | ||
| 103 | + <el-form-item label="开启状态" prop="status"> | ||
| 104 | + <el-radio-group v-model="form.status"> | ||
| 105 | + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" | ||
| 106 | + :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio> | ||
| 107 | + </el-radio-group> | ||
| 108 | + </el-form-item> | ||
| 109 | + <el-form-item label="备注" prop="remark"> | ||
| 110 | + <el-input v-model="form.remark" placeholder="请输入备注" /> | ||
| 111 | + </el-form-item> | ||
| 112 | + </el-form> | ||
| 113 | + <div slot="footer" class="dialog-footer"> | ||
| 114 | + <el-button type="primary" @click="submitForm">确 定</el-button> | ||
| 115 | + <el-button @click="cancel">取 消</el-button> | ||
| 116 | + </div> | ||
| 117 | + </el-dialog> | ||
| 118 | + | ||
| 119 | + <!-- 对话框(发送邮件) --> | ||
| 120 | + <el-dialog title="测试发送邮件" :visible.sync="sendOpen" width="500px" append-to-body> | ||
| 121 | + <el-form ref="sendForm" :model="sendForm" :rules="sendRules" label-width="140px"> | ||
| 122 | + <el-form-item label="模板内容" prop="content"> | ||
| 123 | + <editor v-model="sendForm.content" :min-height="192" readonly /> | ||
| 124 | + </el-form-item> | ||
| 125 | + <el-form-item label="收件邮箱" prop="mail"> | ||
| 126 | + <el-input v-model="sendForm.mail" placeholder="请输入收件邮箱" /> | ||
| 127 | + </el-form-item> | ||
| 128 | + <el-form-item v-for="param in sendForm.params" :key="param" :label="'参数 {' + param + '}'" :prop="'templateParams.' + param"> | ||
| 129 | + <el-input v-model="sendForm.templateParams[param]" :placeholder="'请输入 ' + param + ' 参数'" /> | ||
| 130 | + </el-form-item> | ||
| 131 | + </el-form> | ||
| 132 | + <div slot="footer" class="dialog-footer"> | ||
| 133 | + <el-button type="primary" @click="submitSendForm">确 定</el-button> | ||
| 134 | + <el-button @click="cancelSend">取 消</el-button> | ||
| 135 | + </div> | ||
| 136 | + </el-dialog> | ||
| 137 | + </div> | ||
| 138 | +</template> | ||
| 139 | + | ||
| 140 | +<script> | ||
| 141 | +import { createMailTemplate, updateMailTemplate, deleteMailTemplate, getMailTemplate, getMailTemplatePage, sendMail } from "@/api/system/mail/template"; | ||
| 142 | +import Editor from '@/components/Editor'; | ||
| 143 | +import { CommonStatusEnum } from "@/utils/constants"; | ||
| 144 | +import { getSimpleMailAccountList } from "@/api/system/mail/account"; | ||
| 145 | + | ||
| 146 | +export default { | ||
| 147 | + name: "MailTemplate", | ||
| 148 | + components: { | ||
| 149 | + Editor, | ||
| 150 | + }, | ||
| 151 | + data() { | ||
| 152 | + return { | ||
| 153 | + // 遮罩层 | ||
| 154 | + loading: true, | ||
| 155 | + // 显示搜索条件 | ||
| 156 | + showSearch: true, | ||
| 157 | + // 总条数 | ||
| 158 | + total: 0, | ||
| 159 | + // 邮件模版列表 | ||
| 160 | + list: [], | ||
| 161 | + // 弹出层标题 | ||
| 162 | + title: "", | ||
| 163 | + // 是否显示弹出层 | ||
| 164 | + open: false, | ||
| 165 | + // 查询参数 | ||
| 166 | + queryParams: { | ||
| 167 | + pageNo: 1, | ||
| 168 | + pageSize: 10, | ||
| 169 | + name: null, | ||
| 170 | + code: null, | ||
| 171 | + accountId: null, | ||
| 172 | + status: null, | ||
| 173 | + createTime: [], | ||
| 174 | + }, | ||
| 175 | + // 表单参数 | ||
| 176 | + form: {}, | ||
| 177 | + // 表单校验 | ||
| 178 | + rules: { | ||
| 179 | + name: [{ required: true, message: "模板名称不能为空", trigger: "blur" }], | ||
| 180 | + code: [{ required: true, message: "模板编码不能为空", trigger: "blur" }], | ||
| 181 | + accountId: [{ required: true, message: "邮箱账号不能为空", trigger: "blur" }], | ||
| 182 | + title: [{ required: true, message: "模板标题不能为空", trigger: "blur" }], | ||
| 183 | + content: [{ required: true, message: "模板内容不能为空", trigger: "blur" }], | ||
| 184 | + status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }], | ||
| 185 | + }, | ||
| 186 | + // 邮箱账号 | ||
| 187 | + accountOptions: [], | ||
| 188 | + | ||
| 189 | + // 发送邮箱 | ||
| 190 | + sendOpen: false, | ||
| 191 | + sendForm: { | ||
| 192 | + params: [], // 模板的参数列表 | ||
| 193 | + }, | ||
| 194 | + sendRules: { | ||
| 195 | + mail: [{ required: true, message: "收件邮箱不能为空", trigger: "blur" }], | ||
| 196 | + templateCode: [{ required: true, message: "模版编码不能为空", trigger: "blur" }], | ||
| 197 | + templateParams: { } | ||
| 198 | + } | ||
| 199 | + }; | ||
| 200 | + }, | ||
| 201 | + created() { | ||
| 202 | + this.getList(); | ||
| 203 | + // 获得邮箱账号列表 | ||
| 204 | + getSimpleMailAccountList().then(response => { | ||
| 205 | + this.accountOptions = response.data | ||
| 206 | + }) | ||
| 207 | + }, | ||
| 208 | + methods: { | ||
| 209 | + /** 查询列表 */ | ||
| 210 | + getList() { | ||
| 211 | + this.loading = true; | ||
| 212 | + // 执行查询 | ||
| 213 | + getMailTemplatePage(this.queryParams).then(response => { | ||
| 214 | + this.list = response.data.list; | ||
| 215 | + this.total = response.data.total; | ||
| 216 | + this.loading = false; | ||
| 217 | + }); | ||
| 218 | + }, | ||
| 219 | + /** 取消按钮 */ | ||
| 220 | + cancel() { | ||
| 221 | + this.open = false; | ||
| 222 | + this.reset(); | ||
| 223 | + }, | ||
| 224 | + /** 表单重置 */ | ||
| 225 | + reset() { | ||
| 226 | + this.form = { | ||
| 227 | + id: undefined, | ||
| 228 | + name: undefined, | ||
| 229 | + code: undefined, | ||
| 230 | + accountId: undefined, | ||
| 231 | + nickname: undefined, | ||
| 232 | + title: undefined, | ||
| 233 | + content: undefined, | ||
| 234 | + status: CommonStatusEnum.ENABLE, | ||
| 235 | + remark: undefined, | ||
| 236 | + }; | ||
| 237 | + this.resetForm("form"); | ||
| 238 | + }, | ||
| 239 | + /** 搜索按钮操作 */ | ||
| 240 | + handleQuery() { | ||
| 241 | + this.queryParams.pageNo = 1; | ||
| 242 | + this.getList(); | ||
| 243 | + }, | ||
| 244 | + /** 重置按钮操作 */ | ||
| 245 | + resetQuery() { | ||
| 246 | + this.resetForm("queryForm"); | ||
| 247 | + this.handleQuery(); | ||
| 248 | + }, | ||
| 249 | + /** 新增按钮操作 */ | ||
| 250 | + handleAdd() { | ||
| 251 | + this.reset(); | ||
| 252 | + this.open = true; | ||
| 253 | + this.title = "添加邮件模版"; | ||
| 254 | + }, | ||
| 255 | + /** 修改按钮操作 */ | ||
| 256 | + handleUpdate(row) { | ||
| 257 | + this.reset(); | ||
| 258 | + const id = row.id; | ||
| 259 | + getMailTemplate(id).then(response => { | ||
| 260 | + this.form = response.data; | ||
| 261 | + this.open = true; | ||
| 262 | + this.title = "修改邮件模版"; | ||
| 263 | + }); | ||
| 264 | + }, | ||
| 265 | + /** 提交按钮 */ | ||
| 266 | + submitForm() { | ||
| 267 | + this.$refs["form"].validate(valid => { | ||
| 268 | + if (!valid) { | ||
| 269 | + return; | ||
| 270 | + } | ||
| 271 | + // 修改的提交 | ||
| 272 | + if (this.form.id != null) { | ||
| 273 | + updateMailTemplate(this.form).then(response => { | ||
| 274 | + this.$modal.msgSuccess("修改成功"); | ||
| 275 | + this.open = false; | ||
| 276 | + this.getList(); | ||
| 277 | + }); | ||
| 278 | + return; | ||
| 279 | + } | ||
| 280 | + // 添加的提交 | ||
| 281 | + createMailTemplate(this.form).then(response => { | ||
| 282 | + this.$modal.msgSuccess("新增成功"); | ||
| 283 | + this.open = false; | ||
| 284 | + this.getList(); | ||
| 285 | + }); | ||
| 286 | + }); | ||
| 287 | + }, | ||
| 288 | + /** 删除按钮操作 */ | ||
| 289 | + handleDelete(row) { | ||
| 290 | + const id = row.id; | ||
| 291 | + this.$modal.confirm('是否确认删除邮件模版编号为"' + id + '"的数据项?').then(function() { | ||
| 292 | + return deleteMailTemplate(id); | ||
| 293 | + }).then(() => { | ||
| 294 | + this.getList(); | ||
| 295 | + this.$modal.msgSuccess("删除成功"); | ||
| 296 | + }).catch(() => {}); | ||
| 297 | + }, | ||
| 298 | + /** 发送短息按钮 */ | ||
| 299 | + handleSend(row) { | ||
| 300 | + this.resetSend(row); | ||
| 301 | + // 设置参数 | ||
| 302 | + this.sendForm.content = row.content; | ||
| 303 | + this.sendForm.params = row.params; | ||
| 304 | + this.sendForm.templateCode = row.code; | ||
| 305 | + this.sendForm.templateParams = row.params.reduce(function(obj, item) { | ||
| 306 | + obj[item] = undefined; | ||
| 307 | + return obj; | ||
| 308 | + }, {}); | ||
| 309 | + // 根据 row 重置 rules | ||
| 310 | + this.sendRules.templateParams = row.params.reduce(function(obj, item) { | ||
| 311 | + obj[item] = { required: true, message: '参数 ' + item + " 不能为空", trigger: "change" }; | ||
| 312 | + return obj; | ||
| 313 | + }, {}); | ||
| 314 | + // 设置打开 | ||
| 315 | + this.sendOpen = true; | ||
| 316 | + }, | ||
| 317 | + /** 重置发送邮箱的表单 */ | ||
| 318 | + resetSend() { | ||
| 319 | + // 根据 row 重置表单 | ||
| 320 | + this.sendForm = { | ||
| 321 | + content: undefined, | ||
| 322 | + params: undefined, | ||
| 323 | + mail: undefined, | ||
| 324 | + templateCode: undefined, | ||
| 325 | + templateParams: {} | ||
| 326 | + }; | ||
| 327 | + this.resetForm("sendForm"); | ||
| 328 | + }, | ||
| 329 | + /** 取消发送邮箱 */ | ||
| 330 | + cancelSend() { | ||
| 331 | + this.sendOpen = false; | ||
| 332 | + this.resetSend(); | ||
| 333 | + }, | ||
| 334 | + /** 提交按钮 */ | ||
| 335 | + submitSendForm() { | ||
| 336 | + this.$refs["sendForm"].validate(valid => { | ||
| 337 | + if (!valid) { | ||
| 338 | + return; | ||
| 339 | + } | ||
| 340 | + // 添加的提交 | ||
| 341 | + sendMail(this.sendForm).then(response => { | ||
| 342 | + this.$modal.msgSuccess("提交发送成功!发送结果,见发送日志编号:" + response.data); | ||
| 343 | + this.sendOpen = false; | ||
| 344 | + }); | ||
| 345 | + }); | ||
| 346 | + }, | ||
| 347 | + } | ||
| 348 | +}; | ||
| 349 | +</script> |
yudao-ui-admin/src/views/system/sms/smsLog.vue
| @@ -94,7 +94,7 @@ | @@ -94,7 +94,7 @@ | ||
| 94 | </el-table-column> | 94 | </el-table-column> |
| 95 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | 95 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
| 96 | <template v-slot="scope"> | 96 | <template v-slot="scope"> |
| 97 | - <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row,scope.index)" | 97 | + <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)" |
| 98 | v-hasPermi="['system:sms-log:query']">详细</el-button> | 98 | v-hasPermi="['system:sms-log:query']">详细</el-button> |
| 99 | </template> | 99 | </template> |
| 100 | </el-table-column> | 100 | </el-table-column> |
yudao-ui-admin/src/views/system/sms/smsTemplate.vue
| @@ -216,7 +216,7 @@ export default { | @@ -216,7 +216,7 @@ export default { | ||
| 216 | }, | 216 | }, |
| 217 | sendSmsRules: { | 217 | sendSmsRules: { |
| 218 | mobile: [{ required: true, message: "手机不能为空", trigger: "blur" }], | 218 | mobile: [{ required: true, message: "手机不能为空", trigger: "blur" }], |
| 219 | - templateCode: [{ required: true, message: "手机不能为空", trigger: "blur" }], | 219 | + templateCode: [{ required: true, message: "模版编码不能为空", trigger: "blur" }], |
| 220 | templateParams: { } | 220 | templateParams: { } |
| 221 | } | 221 | } |
| 222 | }; | 222 | }; |
yudao-ui-admin/src/views/system/user/index.vue
| @@ -364,9 +364,9 @@ export default { | @@ -364,9 +364,9 @@ export default { | ||
| 364 | created() { | 364 | created() { |
| 365 | this.getList(); | 365 | this.getList(); |
| 366 | this.getTreeselect(); | 366 | this.getTreeselect(); |
| 367 | - this.getConfigKey("sys.user.init-password").then(response => { | ||
| 368 | - this.initPassword = response.msg; | ||
| 369 | - }); | 367 | + // this.getConfigKey("sys.user.init-password").then(response => { |
| 368 | + // this.initPassword = response.msg; | ||
| 369 | + // }); | ||
| 370 | }, | 370 | }, |
| 371 | methods: { | 371 | methods: { |
| 372 | // 更多操作 | 372 | // 更多操作 |
yudao-ui-admin/yarn.lock
| @@ -3999,10 +3999,10 @@ electron-to-chromium@^1.4.251: | @@ -3999,10 +3999,10 @@ electron-to-chromium@^1.4.251: | ||
| 3999 | resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz" | 3999 | resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz" |
| 4000 | integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== | 4000 | integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== |
| 4001 | 4001 | ||
| 4002 | -element-ui@2.15.10: | ||
| 4003 | - version "2.15.10" | ||
| 4004 | - resolved "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.10.tgz" | ||
| 4005 | - integrity sha512-jmD++mU2wKXbisvx4fxOl2mHaU+HWHTAq/3Wf8x9Bwyu4GdDZPLABb+CGi3DWN6fPqdgRcd74aX39DO+YHObLw== | 4002 | +element-ui@2.15.12: |
| 4003 | + version "2.15.12" | ||
| 4004 | + resolved "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.12.tgz#fdde927a54078b17a85541ff7c0f0dad32488b8e" | ||
| 4005 | + integrity sha512-Y5FMT2BPOindU2GkDEQ5ZKUVxDawKONRNMh2eL3uBx1FOtvUJ+L6IxXLVsNxq4WnaX/UnVNgWXebl7DobygZMg== | ||
| 4006 | dependencies: | 4006 | dependencies: |
| 4007 | async-validator "~1.8.1" | 4007 | async-validator "~1.8.1" |
| 4008 | babel-helper-vue-jsx-merge-props "^2.0.0" | 4008 | babel-helper-vue-jsx-merge-props "^2.0.0" |