Commit c24a3a02c28161e91672668037031c44bbf4f597

Authored by YunaiV
2 parents c48f52ec 97096216

Merge branch 'feature/im-dev' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17

# Conflicts:
#	sql/mysql/ruoyi-vue-pro.sql
Showing 155 changed files with 2800 additions and 2541 deletions

Too many changes.

To preserve performance only 100 of 155 files are displayed.

sql/mysql/ruoyi-vue-pro.sql
... ... @@ -11,7 +11,7 @@
11 11 Target Server Version : 80200 (8.2.0)
12 12 File Encoding : 65001
13 13  
14   - Date: 19/06/2026 18:41:15
  14 + Date: 31/05/2026 22:29:18
15 15 */
16 16  
17 17 SET NAMES utf8mb4;
... ... @@ -49,7 +49,7 @@ CREATE TABLE `infra_api_access_log` (
49 49 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
50 50 PRIMARY KEY (`id`) USING BTREE,
51 51 INDEX `idx_create_time`(`create_time` ASC) USING BTREE
52   -) ENGINE = InnoDB AUTO_INCREMENT = 36333 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
  52 +) ENGINE = InnoDB AUTO_INCREMENT = 36301 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
53 53  
54 54 -- ----------------------------
55 55 -- Records of infra_api_access_log
... ... @@ -92,7 +92,7 @@ CREATE TABLE `infra_api_error_log` (
92 92 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
93 93 PRIMARY KEY (`id`) USING BTREE,
94 94 INDEX `idx_create_time`(`create_time` ASC) USING BTREE
95   -) ENGINE = InnoDB AUTO_INCREMENT = 24233 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
  95 +) ENGINE = InnoDB AUTO_INCREMENT = 23958 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
96 96  
97 97 -- ----------------------------
98 98 -- Records of infra_api_error_log
... ... @@ -253,7 +253,7 @@ CREATE TABLE `infra_file` (
253 253 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
254 254 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
255 255 PRIMARY KEY (`id`) USING BTREE
256   -) ENGINE = InnoDB AUTO_INCREMENT = 2260 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
  256 +) ENGINE = InnoDB AUTO_INCREMENT = 2233 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
257 257  
258 258 -- ----------------------------
259 259 -- Records of infra_file
... ... @@ -462,7 +462,7 @@ CREATE TABLE `system_dict_data` (
462 462 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
463 463 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
464 464 PRIMARY KEY (`id`) USING BTREE
465   -) ENGINE = InnoDB AUTO_INCREMENT = 1061137 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
  465 +) ENGINE = InnoDB AUTO_INCREMENT = 1061122 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
466 466  
467 467 -- ----------------------------
468 468 -- Records of system_dict_data
... ... @@ -1374,14 +1374,14 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1374 1374 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 (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0');
1375 1375 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 (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0');
1376 1376 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 (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0');
1377   -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 (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, 'default', '', 'PREPARE', '1', '2026-04-16 09:47:00', '1', '2026-06-13 10:32:58', b'0');
1378   -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 (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, 'success', '', 'FINISHED', '1', '2026-04-16 09:47:00', '1', '2026-06-13 10:32:58', b'0');
1379   -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 (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, 'danger', '', 'CANCELED', '1', '2026-04-16 09:47:00', '1', '2026-06-13 10:32:58', b'0');
1380   -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 (3525, 1, '正常', '0', 'im_message_status', 0, 'success', '', '正常(初始状态)', 'admin', '2026-04-30 15:14:36', 'admin', '2026-06-16 03:41:55', b'0');
1381   -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 (3526, 2, '已撤回', '2', 'im_message_status', 0, 'danger', '', '已撤回', 'admin', '2026-04-30 15:14:36', 'admin', '2026-06-16 03:41:55', b'0');
1382   -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 (3530, 1, '不需要回执', '0', 'im_message_receipt_status', 0, 'info', '', 'NO_RECEIPT', 'admin', '2026-04-30 11:35:07', 'admin', '2026-06-14 00:32:47', b'0');
1383   -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 (3531, 2, '待完成', '1', 'im_message_receipt_status', 0, 'warning', '', 'PENDING', 'admin', '2026-04-30 11:35:07', 'admin', '2026-06-14 00:32:47', b'0');
1384   -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 (3532, 3, '已完成', '2', 'im_message_receipt_status', 0, 'success', '', 'DONE', 'admin', '2026-04-30 11:35:07', 'admin', '2026-06-14 00:32:47', b'0');
  1377 +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 (3446, 0, '草稿', '0', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', b'0');
  1378 +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 (3447, 1, '已完成', '4', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', b'0');
  1379 +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 (3448, 2, '已取消', '5', 'mes_pro_task_status', 0, '', '', NULL, '1', '2026-04-16 09:47:00', '1', '2026-04-16 09:47:00', b'0');
  1380 +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 (3525, 1, '正常', '0', 'im_message_status', 0, 'success', '', '正常(初始状态)', 'admin', '2026-04-30 15:14:36', 'admin', '2026-04-30 15:14:36', b'0');
  1381 +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 (3526, 2, '已撤回', '2', 'im_message_status', 0, 'danger', '', '已撤回', 'admin', '2026-04-30 15:14:36', 'admin', '2026-04-30 15:14:36', b'0');
  1382 +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 (3530, 1, '不需要回执', '0', 'im_message_receipt_status', 0, 'info', '', 'NO_RECEIPT', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0');
  1383 +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 (3531, 2, '待完成', '1', 'im_message_receipt_status', 0, 'warning', '', 'PENDING', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0');
  1384 +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 (3532, 3, '已完成', '2', 'im_message_receipt_status', 0, 'success', '', 'DONE', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0');
1385 1385 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 (3540, 1, '正常', '0', 'im_friend_status', 0, 'success', '', '正常好友关系', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0');
1386 1386 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 (3541, 2, '已删除', '1', 'im_friend_status', 0, 'danger', '', '已删除好友关系', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0');
1387 1387 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 (3550, 1, '正常', '0', 'im_group_status', 0, 'success', '', '群正常', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0');
... ... @@ -1396,39 +1396,39 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1396 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 (3559, 1, '等待验证', '0', 'im_friend_request_handle_result', 0, 'warning', '', NULL, '1', '2026-05-04 02:43:41', '1', '2026-05-04 02:43:41', b'0');
1397 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 (3560, 2, '已添加', '1', 'im_friend_request_handle_result', 0, 'success', '', NULL, '1', '2026-05-04 02:43:41', '1', '2026-05-04 02:43:41', b'0');
1398 1398 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 (3561, 3, '已拒绝', '2', 'im_friend_request_handle_result', 0, 'info', '', NULL, '1', '2026-05-04 02:43:41', '1', '2026-05-04 02:43:41', b'0');
1399   -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 (3562, 101, '文本', '101', 'im_content_type', 0, '', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1400   -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 (3563, 102, '图片', '102', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1401   -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 (3564, 103, '语音', '103', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1402   -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 (3565, 104, '视频', '104', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1403   -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 (3566, 105, '文件', '105', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1404   -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 (3568, 2101, '撤回', '2101', 'im_content_type', 0, 'danger', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1405   -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 (3569, 2200, '回执', '2200', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1406   -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 (3570, 2201, '已读', '2201', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1407   -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 (3571, 1501, '群创建', '1501', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1408   -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 (3572, 1502, '群信息变更', '1502', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1409   -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 (3573, 1503, '收到新的入群申请', '1503', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:47:00', b'0');
1410   -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 (3574, 1504, '成员退群', '1504', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1411   -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 (3575, 1505, '入群申请被同意', '1505', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:47:00', b'0');
1412   -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 (3576, 1506, '入群申请被拒绝', '1506', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:47:00', b'0');
1413   -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 (3577, 1507, '群主转让', '1507', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1414   -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 (3578, 1508, '成员被移出', '1508', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1415   -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 (3579, 1509, '成员加入', '1509', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1416   -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 (3580, 1510, '自由进群', '1510', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1417   -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 (3581, 1511, '群解散', '1511', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1418   -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 (3582, 1512, '成员禁言', '1512', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1419   -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 (3583, 1513, '成员取消禁言', '1513', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1420   -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 (3584, 1514, '全群禁言', '1514', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1421   -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 (3585, 1515, '全群取消禁言', '1515', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1422   -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 (3586, 1516, '成员昵称变更', '1516', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1423   -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 (3587, 1517, '添加管理员', '1517', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1424   -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 (3588, 1518, '撤销管理员', '1518', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1425   -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 (3589, 1519, '群公告变更', '1519', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1426   -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 (3590, 1520, '群名变更', '1520', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1427   -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3591, 1531, '群消息置顶', '1531', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1428   -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3592, 1532, '群消息取消置顶', '1532', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1429   -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3593, 1533, '群封禁变更', '1533', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-06-16 03:41:55', b'0');
1430   -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 (3594, 1204, '新增好友', '1204', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 13:26:53', 'admin', '2026-06-16 03:41:55', b'0');
1431   -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 (3595, 1205, '好友被删除', '1205', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 13:26:53', 'admin', '2026-06-16 03:41:55', b'0');
  1399 +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 (3562, 101, '文本', '101', 'im_content_type', 0, '', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1400 +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 (3563, 102, '图片', '102', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1401 +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 (3564, 103, '语音', '103', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1402 +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 (3565, 104, '视频', '104', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1403 +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 (3566, 105, '文件', '105', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1404 +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 (3568, 2101, '撤回', '2101', 'im_content_type', 0, 'danger', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1405 +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 (3569, 2200, '回执', '2200', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1406 +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 (3570, 2201, '已读', '2201', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1407 +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 (3571, 1501, '群创建', '1501', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1408 +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 (3572, 1502, '群信息变更', '1502', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1409 +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 (3573, 1503, '入群申请', '1503', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1410 +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 (3574, 1504, '成员退群', '1504', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1411 +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 (3575, 1505, '入群申请通过', '1505', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1412 +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 (3576, 1506, '入群申请拒绝', '1506', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1413 +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 (3577, 1507, '群主转让', '1507', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1414 +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 (3578, 1508, '成员被移出', '1508', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1415 +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 (3579, 1509, '成员加入', '1509', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1416 +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 (3580, 1510, '自由进群', '1510', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1417 +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 (3581, 1511, '群解散', '1511', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1418 +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 (3582, 1512, '成员禁言', '1512', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1419 +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 (3583, 1513, '成员取消禁言', '1513', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1420 +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 (3584, 1514, '全群禁言', '1514', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1421 +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 (3585, 1515, '全群取消禁言', '1515', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1422 +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 (3586, 1516, '成员昵称变更', '1516', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1423 +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 (3587, 1517, '添加管理员', '1517', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1424 +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 (3588, 1518, '撤销管理员', '1518', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1425 +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 (3589, 1519, '群公告变更', '1519', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1426 +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 (3590, 1520, '群名变更', '1520', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1427 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3591, 1531, '群消息置顶', '1531', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1428 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3592, 1532, '群消息取消置顶', '1532', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1429 +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3593, 1533, '群封禁变更', '1533', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 11:52:30', 'admin', '2026-05-05 11:52:30', b'0');
  1430 +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 (3594, 1204, '新增好友', '1204', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-05-05 13:26:53', 'admin', '2026-05-05 13:26:53', b'0');
  1431 +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 (3595, 1205, '好友被删除', '1205', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 13:26:53', 'admin', '2026-05-05 13:26:53', b'0');
1432 1432 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 (3596, 1, '搜索', '1', 'im_group_add_source', 0, '', '', NULL, '', '2026-05-06 09:26:36', '', '2026-05-06 09:26:36', b'0');
1433 1433 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 (3597, 2, '邀请', '2', 'im_group_add_source', 0, '', '', NULL, '', '2026-05-06 09:26:36', '', '2026-05-06 09:26:36', b'0');
1434 1434 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 (3598, 3, '扫码', '3', 'im_group_add_source', 0, '', '', NULL, '', '2026-05-06 09:26:36', '', '2026-05-06 09:26:36', b'0');
... ... @@ -1474,26 +1474,11 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
1474 1474 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1061114, 3, '已拒绝', '30', 'im_rtc_participant_status', 0, 'warning', '', '接通前点拒接', 'admin', '2026-05-18 03:36:12', 'admin', '2026-05-18 03:36:12', b'0');
1475 1475 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1061115, 4, '未应答', '40', 'im_rtc_participant_status', 0, 'info', '', '通话已结束仍未应答', 'admin', '2026-05-18 03:36:12', 'admin', '2026-05-18 03:36:12', b'0');
1476 1476 INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1061116, 5, '已离开', '50', 'im_rtc_participant_status', 0, 'success', '', '接通后挂断 / 离开', 'admin', '2026-05-18 03:36:12', 'admin', '2026-05-18 03:36:12', b'0');
1477   -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 (1061117, 1610, '通话开始', '1610', 'im_content_type', 0, 'info', '', '入消息流;私聊定向通知,群聊全员广播', 'admin', '2026-05-18 03:36:12', 'admin', '2026-06-16 03:41:55', b'0');
1478   -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 (1061118, 1611, '通话结束', '1611', 'im_content_type', 0, 'info', '', '入消息流;私聊准气泡,群聊系统 tip', 'admin', '2026-05-18 03:36:12', 'admin', '2026-06-16 03:41:55', b'0');
1479   -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 (1061119, 125, '素材', '125', 'im_content_type', 0, 'success', '', '频道运营推送的图文卡片消息', '1', '2026-05-18 13:14:34', 'admin', '2026-06-16 03:41:55', b'0');
  1477 +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 (1061117, 1610, '通话开始', '1610', 'im_content_type', 0, 'info', '', '入消息流;私聊定向通知,群聊全员广播', 'admin', '2026-05-18 03:36:12', 'admin', '2026-05-18 03:36:12', b'0');
  1478 +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 (1061118, 1611, '通话结束', '1611', 'im_content_type', 0, 'info', '', '入消息流;私聊准气泡,群聊系统 tip', 'admin', '2026-05-18 03:36:12', 'admin', '2026-05-18 03:36:12', b'0');
  1479 +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 (1061119, 125, '素材', '125', 'im_content_type', 0, 'success', '', '频道运营推送的图文卡片消息', '1', '2026-05-18 13:14:34', '1', '2026-05-18 13:14:34', b'0');
1480 1480 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 (1061120, 1, '富文本', '1', 'im_channel_material_type', 0, 'primary', '', '', '1', '2026-05-19 14:09:25', '1', '2026-05-19 14:09:25', b'0');
1481 1481 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 (1061121, 2, '外链', '2', 'im_channel_material_type', 0, 'info', '', '', '1', '2026-05-19 14:09:25', '1', '2026-05-19 14:09:25', b'0');
1482   -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 (1061122, 7, 'SN 码', '109', 'mes_wm_barcode_biz_type', 0, 'default', '', 'SN', '1', '2026-06-13 10:30:30', '1', '2026-06-13 10:30:30', b'0');
1483   -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 (1061123, 107, '合并转发', '107', 'im_content_type', 0, '', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1484   -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 (1061124, 108, '名片', '108', 'im_content_type', 0, '', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1485   -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 (1061125, 115, '表情', '115', 'im_content_type', 0, '', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1486   -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 (1061126, 1201, '好友申请被同意', '1201', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1487   -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 (1061127, 1202, '好友申请被拒绝', '1202', 'im_content_type', 0, 'warning', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1488   -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 (1061128, 1203, '收到新的好友申请', '1203', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1489   -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 (1061129, 1207, '加入黑名单', '1207', 'im_content_type', 0, 'danger', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1490   -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 (1061130, 1208, '移出黑名单', '1208', 'im_content_type', 0, 'success', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1491   -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 (1061131, 1209, '好友资料变更', '1209', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1492   -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 (1061132, 1210, '好友信息批量更新', '1210', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1493   -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 (1061133, 1530, '群成员个人设置变更', '1530', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1494   -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 (1061134, 1601, '通话信令', '1601', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1495   -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 (1061135, 1602, '通话参与者加入', '1602', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1496   -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 (1061136, 1603, '通话参与者离开', '1603', 'im_content_type', 0, 'info', '', NULL, 'admin', '2026-06-16 03:47:00', 'admin', '2026-06-16 03:47:00', b'0');
1497 1482 COMMIT;
1498 1483  
1499 1484 -- ----------------------------
... ... @@ -1651,7 +1636,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
1651 1636 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2029, 'MES 工单类型', 'mes_pro_work_order_type', 0, 'MES 生产管理 - 工单类型(1=自行生产,2=代工,3=采购)', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0', NULL);
1652 1637 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2036, 'MES 工序关系类型', 'mes_pro_link_type', 0, '工艺路线中工序之间的关系类型', '1', '2026-02-19 04:24:53', '1', '2026-04-05 15:05:07', b'0', NULL);
1653 1638 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2037, 'MES 时间单位', 'mes_time_unit_type', 0, '生产时间的计量单位', '1', '2026-02-19 04:24:53', '1', '2026-04-05 15:04:57', b'0', NULL);
1654   -INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2038, 'MES 生产任务状态', 'mes_pro_task_status', 0, 'MES 生产管理 - 任务状态(0=草稿,4=已完成,5=已取消)', '1', '2026-02-19 15:25:27', '1', '2026-06-13 10:32:58', b'0', NULL);
  1639 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2038, 'MES 生产任务状态', 'mes_pro_task_status', 0, 'MES 生产管理 - 任务状态(0=草稿,1=进行中,2=暂停,3=已完成,4=已取消)', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0', NULL);
1655 1640 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2039, 'MES 点检保养项目类型', 'mes_dv_subject_type', 0, 'MES 设备管理 - 点检保养项目类型(1=设备点检,2=设备保养)', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0', NULL);
1656 1641 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2040, 'MES 保养记录状态', 'mes_mainten_record_status', 0, NULL, 'admin', '2026-02-20 02:59:55', 'admin', '2026-02-20 02:59:55', b'0', NULL);
1657 1642 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2041, 'MES 保养结果', 'mes_mainten_status', 0, NULL, 'admin', '2026-02-20 02:59:55', 'admin', '2026-02-20 02:59:55', b'0', NULL);
... ... @@ -1704,11 +1689,11 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
1704 1689 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2133, 'MES 销售退货单状态', 'mes_wm_return_sales_status', 0, 'MES 销售退货单状态枚举', '1', '2026-04-03 17:20:25', '1', '2026-04-05 15:05:39', b'0', NULL);
1705 1690 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2135, 'MES 上下工状态类型', 'mes_pro_work_record_type', 0, 'MES 上下工状态类型', '1', '2026-04-05 14:07:27', '1', '2026-04-05 14:07:27', b'0', NULL);
1706 1691 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2138, 'MES 生产入库单状态', 'mes_wm_product_produce_status', 0, 'MES 生产入库单状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0', '1970-01-01 00:00:00');
1707   -INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2200, 'IM 内容类型', 'im_content_type', 0, '对应 ImContentTypeEnum', 'admin', '2026-04-30 11:35:07', 'admin', '2026-06-16 03:41:55', b'0', NULL);
1708   -INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2202, 'IM 消息回执状态', 'im_message_receipt_status', 0, '对应 ImMessageReceiptStatusEnum', 'admin', '2026-04-30 11:35:07', 'admin', '2026-06-16 03:41:55', b'0', NULL);
  1692 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2200, 'IM 内容类型', 'im_content_type', 0, '对应 ImContentTypeEnum', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0', NULL);
  1693 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2202, 'IM 消息回执状态', 'im_message_receipt_status', 0, '对应 ImMessageReceiptStatusEnum', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0', NULL);
1709 1694 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2203, 'IM 好友状态', 'im_friend_status', 0, '0=正常 / 1=已删除', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0', NULL);
1710 1695 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2204, 'IM 群状态', 'im_group_status', 0, '0=正常 / 1=已解散', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', b'0', NULL);
1711   -INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2205, 'IM 消息状态', 'im_message_status', 0, '对应 ImMessageStatusEnum;0=正常 / 2=已撤回(私聊 / 群聊共用)', 'admin', '2026-04-30 15:14:36', 'admin', '2026-06-16 03:41:55', b'0', NULL);
  1696 +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2205, 'IM 消息状态', 'im_message_status', 0, '对应 ImMessageStatusEnum;0=正常 / 2=已撤回(私聊 / 群聊共用)', 'admin', '2026-04-30 15:14:36', 'admin', '2026-04-30 15:14:36', b'0', NULL);
1712 1697 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2206, 'IM 群成员角色', 'im_group_member_role', 0, NULL, '1', '2026-05-02 02:14:12', '1', '2026-05-02 02:14:12', b'0', NULL);
1713 1698 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2207, 'IM 好友添加来源', 'im_friend_add_source', 0, NULL, '1', '2026-05-04 02:43:41', '1', '2026-05-04 02:43:41', b'0', NULL);
1714 1699 INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2208, 'IM 好友申请处理结果', 'im_friend_request_handle_result', 0, NULL, '1', '2026-05-04 02:43:41', '1', '2026-05-04 02:43:41', b'0', NULL);
... ... @@ -1751,7 +1736,7 @@ CREATE TABLE `system_login_log` (
1751 1736 PRIMARY KEY (`id`) USING BTREE,
1752 1737 INDEX `idx_username`(`username` ASC) USING BTREE,
1753 1738 INDEX `idx_create_time`(`create_time` ASC) USING BTREE
1754   -) ENGINE = InnoDB AUTO_INCREMENT = 5226 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
  1739 +) ENGINE = InnoDB AUTO_INCREMENT = 4697 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
1755 1740  
1756 1741 -- ----------------------------
1757 1742 -- Records of system_login_log
... ... @@ -2229,7 +2214,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
2229 2214 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2156, '查询项目', 'report:go-view-project:query', 3, 0, 2153, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2023-02-07 19:25:53', '1', '2023-02-07 19:25:53', b'0');
2230 2215 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2157, '使用 SQL 查询数据', 'report:go-view-data:get-by-sql', 3, 3, 2153, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2023-02-07 19:26:15', '1', '2023-02-07 19:26:15', b'0');
2231 2216 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2158, '使用 HTTP 查询数据', 'report:go-view-data:get-by-http', 3, 4, 2153, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2023-02-07 19:26:35', '1', '2023-02-07 19:26:35', b'0');
2232   -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2159, 'Boot 开发文档', '', 1, 1, 0, 'https://doc.iocoder.cn/', 'ep:document', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-02-10 22:46:28', '1', '2026-06-12 00:05:19', b'0');
  2217 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2159, 'Boot 开发文档', '', 1, 1, 0, 'https://doc.iocoder.cn/', 'ep:document', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-02-10 22:46:28', '1', '2026-01-05 19:31:07', b'0');
2233 2218 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2160, 'Cloud 开发文档', '', 1, 2, 0, 'https://cloud.iocoder.cn', 'ep:document-copy', NULL, NULL, 0, b'1', b'1', b'1', '1', '2023-02-10 22:47:07', '1', '2023-12-02 21:32:29', b'0');
2234 2219 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2161, '接入示例', '', 1, 99, 1117, 'demo', 'fa-solid:dragon', 'pay/demo/index', NULL, 0, b'1', b'1', b'1', '', '2023-02-11 14:21:42', '1', '2024-01-18 23:50:00', b'0');
2235 2220 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2162, '商品导出', 'product:spu:export', 3, 5, 2014, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', b'0');
... ... @@ -3453,7 +3438,7 @@ CREATE TABLE `system_oauth2_access_token` (
3453 3438 PRIMARY KEY (`id`) USING BTREE,
3454 3439 INDEX `idx_access_token`(`access_token` ASC) USING BTREE,
3455 3440 INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE
3456   -) ENGINE = InnoDB AUTO_INCREMENT = 107056 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
  3441 +) ENGINE = InnoDB AUTO_INCREMENT = 57395 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
3457 3442  
3458 3443 -- ----------------------------
3459 3444 -- Records of system_oauth2_access_token
... ... @@ -3526,7 +3511,7 @@ BEGIN;
3526 3511 INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 'default', 'admin123', '芋道源码', 'http://test.yudao.iocoder.cn/20250502/sort2_1746189740718.png', '我是描述', 0, 1800, 2592000, '[\"https://www.iocoder.cn\",\"https://doc.iocoder.cn\"]', '[\"password\",\"authorization_code\",\"implicit\",\"refresh_token\",\"client_credentials\"]', '[\"user.read\",\"user.write\"]', '[]', '[\"user.read\",\"user.write\"]', '[]', '{}', '1', '2022-05-11 21:47:12', '1', '2025-12-07 20:07:09', b'0');
3527 3512 INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (40, 'test', 'test2', 'biubiu', 'http://test.yudao.iocoder.cn/20251227/javayuanma_1766829882970.jpg', '啦啦啦啦', 0, 1800, 43200, '[\"https://www.iocoder.cn\"]', '[\"password\",\"authorization_code\",\"implicit\"]', '[\"user_info\",\"projects\"]', '[\"user_info\"]', '[]', '[]', '{}', '1', '2022-05-12 00:28:20', '1', '2025-12-27 18:04:44', b'0');
3528 3513 INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (41, 'yudao-sso-demo-by-code', 'test', '基于授权码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/it/20250502/sign_1746181948685.png', NULL, 0, 1800, 43200, '[\"http://127.0.0.1:18080\"]', '[\"authorization_code\",\"refresh_token\"]', '[\"user.read\",\"user.write\"]', '[]', '[]', '[]', NULL, '1', '2022-09-29 13:28:31', '1', '2025-05-02 18:32:30', b'0');
3529   -INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (42, 'yudao-sso-demo-by-password', 'test', '基于密码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/oauth2/20260615/iShot_2026-05-31_23.18.10.png', NULL, 0, 1800, 43200, '[\"http://127.0.0.1:18080\"]', '[\"password\",\"refresh_token\"]', '[\"user.read\",\"user.write\"]', '[]', '[]', '[]', NULL, '1', '2022-10-04 17:40:16', '1', '2026-06-15 18:58:30', b'0');
  3514 +INSERT INTO `system_oauth2_client` (`id`, `client_id`, `secret`, `name`, `logo`, `description`, `status`, `access_token_validity_seconds`, `refresh_token_validity_seconds`, `redirect_uris`, `authorized_grant_types`, `scopes`, `auto_approve_scopes`, `authorities`, `resource_ids`, `additional_information`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (42, 'yudao-sso-demo-by-password', 'test', '基于密码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/20251025/images (3)_1761360515810.jpeg', NULL, 0, 1800, 43200, '[\"http://127.0.0.1:18080\"]', '[\"password\",\"refresh_token\"]', '[\"user.read\",\"user.write\"]', '[]', '[]', '[]', NULL, '1', '2022-10-04 17:40:16', '1', '2025-10-25 10:49:40', b'0');
3530 3515 COMMIT;
3531 3516  
3532 3517 -- ----------------------------
... ... @@ -3579,7 +3564,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
3579 3564 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3580 3565 PRIMARY KEY (`id`) USING BTREE,
3581 3566 INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE
3582   -) ENGINE = InnoDB AUTO_INCREMENT = 3244 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
  3567 +) ENGINE = InnoDB AUTO_INCREMENT = 2728 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
3583 3568  
3584 3569 -- ----------------------------
3585 3570 -- Records of system_oauth2_refresh_token
... ... @@ -3615,7 +3600,7 @@ CREATE TABLE `system_operate_log` (
3615 3600 PRIMARY KEY (`id`) USING BTREE,
3616 3601 INDEX `idx_user_id`(`user_id` ASC) USING BTREE,
3617 3602 INDEX `idx_create_time`(`create_time` ASC) USING BTREE
3618   -) ENGINE = InnoDB AUTO_INCREMENT = 9207 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本';
  3603 +) ENGINE = InnoDB AUTO_INCREMENT = 9195 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本';
3619 3604  
3620 3605 -- ----------------------------
3621 3606 -- Records of system_operate_log
... ... @@ -3641,7 +3626,7 @@ CREATE TABLE `system_post` (
3641 3626 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
3642 3627 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3643 3628 PRIMARY KEY (`id`) USING BTREE
3644   -) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表';
  3629 +) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表';
3645 3630  
3646 3631 -- ----------------------------
3647 3632 -- Records of system_post
... ... @@ -3685,7 +3670,7 @@ INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_sco
3685 3670 INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 'CRM 管理员', 'crm_admin', 2, 1, '', 0, 1, 'CRM 专属角色', '1', '2024-02-24 10:51:13', '1', '2024-02-24 02:51:32', b'0', 1);
3686 3671 INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, '租户管理员', 'tenant_admin', 0, 1, '', 0, 1, '系统自动生成', '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', b'0', 121);
3687 3672 INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (111, '租户管理员', 'tenant_admin', 0, 1, '', 0, 1, '系统自动生成', '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0', 122);
3688   -INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (155, '测试数据权限12', 'test-dp', 4, 2, '[112,100,102,103,104,105,107,108]', 0, 2, '1111', '1', '2025-03-31 14:58:06', '1', '2026-06-07 01:37:53', b'0', 1);
  3673 +INSERT INTO `system_role` (`id`, `name`, `code`, `sort`, `data_scope`, `data_scope_dept_ids`, `status`, `type`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (155, '测试数据权限1', 'test-dp', 4, 2, '[112,100,102,103,104,105,107,108]', 0, 2, '1111', '1', '2025-03-31 14:58:06', '1', '2025-12-04 23:29:40', b'0', 1);
3689 3674 COMMIT;
3690 3675  
3691 3676 -- ----------------------------
... ... @@ -3704,7 +3689,7 @@ CREATE TABLE `system_role_menu` (
3704 3689 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
3705 3690 PRIMARY KEY (`id`) USING BTREE,
3706 3691 INDEX `idx_role_id`(`role_id` ASC) USING BTREE
3707   -) ENGINE = InnoDB AUTO_INCREMENT = 6692 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表';
  3692 +) ENGINE = InnoDB AUTO_INCREMENT = 6381 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表';
3708 3693  
3709 3694 -- ----------------------------
3710 3695 -- Records of system_role_menu
... ... @@ -3744,6 +3729,7 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
3744 3729 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (706, 2, 112, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0', 1);
3745 3730 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (707, 2, 113, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0', 1);
3746 3731 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1296, 110, 1, '110', '2022-02-23 00:23:55', '110', '2022-02-23 00:23:55', b'0', 121);
  3732 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1578, 111, 1, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0', 122);
3747 3733 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1729, 109, 100, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
3748 3734 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1730, 109, 101, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
3749 3735 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1731, 109, 1063, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
... ... @@ -3761,6 +3747,23 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
3761 3747 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1743, 109, 1010, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
3762 3748 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1744, 109, 1011, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
3763 3749 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1745, 109, 1012, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', b'0', 121);
  3750 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1746, 111, 100, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3751 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1747, 111, 101, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3752 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1748, 111, 1063, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3753 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1749, 111, 1064, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3754 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1750, 111, 1001, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3755 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1751, 111, 1065, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3756 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1752, 111, 1002, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3757 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1753, 111, 1003, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3758 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1754, 111, 1004, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3759 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1755, 111, 1005, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3760 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1756, 111, 1006, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3761 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1757, 111, 1007, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3762 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1758, 111, 1008, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3763 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1759, 111, 1009, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3764 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1760, 111, 1010, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3765 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1761, 111, 1011, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
  3766 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1762, 111, 1012, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', b'0', 122);
3764 3767 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1763, 109, 100, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', b'0', 121);
3765 3768 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1764, 109, 101, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', b'0', 121);
3766 3769 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1765, 109, 1063, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', b'0', 121);
... ... @@ -3778,6 +3781,23 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
3778 3781 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1777, 109, 1010, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', b'0', 121);
3779 3782 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1778, 109, 1011, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', b'0', 121);
3780 3783 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1779, 109, 1012, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', b'0', 121);
  3784 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1780, 111, 100, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3785 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1781, 111, 101, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3786 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1782, 111, 1063, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3787 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1783, 111, 1064, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3788 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1784, 111, 1001, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3789 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1785, 111, 1065, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3790 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1786, 111, 1002, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3791 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1787, 111, 1003, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3792 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1788, 111, 1004, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3793 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1789, 111, 1005, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3794 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1790, 111, 1006, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3795 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1791, 111, 1007, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3796 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1792, 111, 1008, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3797 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1793, 111, 1009, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3798 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1794, 111, 1010, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3799 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1795, 111, 1011, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
  3800 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1796, 111, 1012, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', b'0', 122);
3781 3801 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1797, 109, 100, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', b'0', 121);
3782 3802 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1798, 109, 101, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', b'0', 121);
3783 3803 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1799, 109, 1063, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', b'0', 121);
... ... @@ -3795,16 +3815,43 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
3795 3815 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1811, 109, 1010, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', b'0', 121);
3796 3816 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1812, 109, 1011, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', b'0', 121);
3797 3817 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1813, 109, 1012, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', b'0', 121);
  3818 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1814, 111, 100, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3819 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1815, 111, 101, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3820 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1816, 111, 1063, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3821 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1817, 111, 1064, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3822 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1818, 111, 1001, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3823 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1819, 111, 1065, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3824 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1820, 111, 1002, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3825 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1821, 111, 1003, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3826 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1822, 111, 1004, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3827 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1823, 111, 1005, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3828 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1824, 111, 1006, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3829 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1825, 111, 1007, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3830 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1826, 111, 1008, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3831 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1827, 111, 1009, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3832 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1828, 111, 1010, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3833 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1829, 111, 1011, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
  3834 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1830, 111, 1012, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', b'0', 122);
3798 3835 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1831, 109, 103, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', b'0', 121);
3799 3836 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1832, 109, 1017, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', b'0', 121);
3800 3837 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1833, 109, 1018, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', b'0', 121);
3801 3838 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1834, 109, 1019, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', b'0', 121);
3802 3839 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1835, 109, 1020, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', b'0', 121);
  3840 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1836, 111, 103, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', b'0', 122);
  3841 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1837, 111, 1017, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', b'0', 122);
  3842 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1838, 111, 1018, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', b'0', 122);
  3843 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1839, 111, 1019, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', b'0', 122);
  3844 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1840, 111, 1020, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', b'0', 122);
3803 3845 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1841, 109, 1036, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 121);
3804 3846 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1842, 109, 1037, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 121);
3805 3847 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1843, 109, 1038, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 121);
3806 3848 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1844, 109, 1039, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 121);
3807 3849 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1845, 109, 107, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 121);
  3850 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1846, 111, 1036, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 122);
  3851 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1847, 111, 1037, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 122);
  3852 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1848, 111, 1038, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 122);
  3853 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1849, 111, 1039, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 122);
  3854 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1850, 111, 107, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', b'0', 122);
3808 3855 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);
3809 3856 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);
3810 3857 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);
... ... @@ -3974,6 +4021,18 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
3974 4021 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2938, 109, 1141, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 121);
3975 4022 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2939, 109, 1142, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 121);
3976 4023 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2940, 109, 1143, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 121);
  4024 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2941, 111, 1224, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4025 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2942, 111, 1225, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4026 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2943, 111, 1226, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4027 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2944, 111, 1227, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4028 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2945, 111, 1228, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4029 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2946, 111, 1229, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4030 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2947, 111, 1138, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4031 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2948, 111, 1139, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4032 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2949, 111, 1140, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4033 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2950, 111, 1141, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4034 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2951, 111, 1142, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
  4035 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2952, 111, 1143, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', b'0', 122);
3977 4036 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2993, 109, 2, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 121);
3978 4037 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2994, 109, 1031, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 121);
3979 4038 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2995, 109, 1032, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 121);
... ... @@ -4049,11 +4108,91 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4049 4108 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3066, 109, 1258, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 121);
4050 4109 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3067, 109, 1259, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 121);
4051 4110 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3068, 109, 1260, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 121);
  4111 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3069, 111, 2, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4112 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3070, 111, 1031, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4113 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3071, 111, 1032, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4114 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3072, 111, 1033, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4115 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3073, 111, 1034, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4116 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3074, 111, 1035, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4117 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3075, 111, 1050, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4118 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3076, 111, 1051, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4119 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3077, 111, 1052, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4120 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3078, 111, 1053, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4121 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3079, 111, 1054, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4122 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3080, 111, 1056, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4123 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3081, 111, 1057, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4124 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3082, 111, 1058, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4125 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3083, 111, 1059, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4126 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3084, 111, 1060, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4127 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3085, 111, 1066, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4128 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3086, 111, 1067, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4129 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3087, 111, 1070, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4130 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3088, 111, 1075, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4131 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3090, 111, 1077, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4132 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3091, 111, 1078, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4133 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3092, 111, 1082, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4134 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3093, 111, 1083, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4135 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3094, 111, 1084, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4136 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3095, 111, 1085, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4137 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3096, 111, 1086, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4138 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3097, 111, 1087, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4139 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3098, 111, 1088, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4140 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3099, 111, 1089, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4141 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3100, 111, 1090, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4142 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3101, 111, 1091, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4143 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3102, 111, 1092, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4144 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3103, 111, 106, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4145 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3104, 111, 110, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4146 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3105, 111, 111, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4147 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3106, 111, 112, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4148 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3107, 111, 113, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4149 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3108, 111, 114, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4150 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3109, 111, 115, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4151 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3110, 111, 116, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4152 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3111, 111, 2472, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4153 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3112, 111, 2478, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4154 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3113, 111, 2479, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4155 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3114, 111, 2480, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4156 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3115, 111, 2481, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4157 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3116, 111, 2482, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4158 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3117, 111, 2483, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4159 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3118, 111, 2484, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4160 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3119, 111, 2485, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4161 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3120, 111, 2486, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4162 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3121, 111, 2487, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4163 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3122, 111, 2488, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4164 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3123, 111, 2489, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4165 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3124, 111, 2490, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4166 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3125, 111, 2491, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4167 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3126, 111, 2492, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4168 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3127, 111, 2493, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4169 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3128, 111, 2494, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4170 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3129, 111, 2495, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4171 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3130, 111, 2497, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4172 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3131, 111, 1237, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4173 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3132, 111, 1238, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4174 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3133, 111, 1239, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4175 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3134, 111, 1240, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4176 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3135, 111, 1241, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4177 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3136, 111, 1242, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4178 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3137, 111, 1243, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4179 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3138, 111, 2525, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4180 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3139, 111, 1255, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4181 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3140, 111, 1256, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4182 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3141, 111, 1257, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4183 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3142, 111, 1258, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4184 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3143, 111, 1259, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
  4185 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3144, 111, 1260, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', b'0', 122);
4052 4186 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3221, 109, 102, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 121);
4053 4187 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3222, 109, 1013, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 121);
4054 4188 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3223, 109, 1014, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 121);
4055 4189 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3224, 109, 1015, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 121);
4056 4190 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3225, 109, 1016, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 121);
  4191 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3226, 111, 102, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 122);
  4192 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3227, 111, 1013, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 122);
  4193 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3228, 111, 1014, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 122);
  4194 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3229, 111, 1015, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 122);
  4195 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3230, 111, 1016, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', b'0', 122);
4057 4196 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4163, 109, 5, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
4058 4197 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4164, 109, 1118, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
4059 4198 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4165, 109, 1119, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
... ... @@ -4112,6 +4251,64 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4112 4251 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4219, 109, 1220, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
4113 4252 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4220, 109, 1221, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
4114 4253 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4221, 109, 1222, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', b'0', 121);
  4254 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4222, 111, 5, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4255 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4223, 111, 1118, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4256 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4224, 111, 1119, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4257 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4225, 111, 1120, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4258 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4226, 111, 2713, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4259 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4227, 111, 2714, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4260 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4228, 111, 2715, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4261 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4229, 111, 2716, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4262 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4230, 111, 2717, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4263 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4231, 111, 2718, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4264 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4232, 111, 2720, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4265 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4233, 111, 1185, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4266 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4234, 111, 2721, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4267 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4235, 111, 1186, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4268 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4236, 111, 2722, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4269 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4237, 111, 1187, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4270 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4238, 111, 2723, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4271 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4239, 111, 1188, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4272 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4240, 111, 2724, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4273 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4241, 111, 1189, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4274 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4242, 111, 2725, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4275 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4243, 111, 1190, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4276 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4244, 111, 2726, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4277 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4245, 111, 1191, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4278 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4246, 111, 2727, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4279 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4247, 111, 1192, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4280 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4248, 111, 2728, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4281 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4249, 111, 1193, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4282 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4250, 111, 2729, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4283 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4251, 111, 1194, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4284 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4252, 111, 2730, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4285 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4253, 111, 1195, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4286 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4254, 111, 2731, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4287 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4256, 111, 2732, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4288 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4257, 111, 1197, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4289 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4258, 111, 2733, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4290 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4259, 111, 1198, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4291 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4260, 111, 2734, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4292 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4261, 111, 1199, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4293 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4262, 111, 2735, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4294 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4263, 111, 1200, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4295 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4264, 111, 1201, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4296 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4265, 111, 1202, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4297 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4266, 111, 1207, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4298 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4267, 111, 1208, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4299 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4268, 111, 1209, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4300 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4269, 111, 1210, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4301 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4270, 111, 1211, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4302 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4271, 111, 1212, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4303 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4272, 111, 1213, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4304 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4273, 111, 1215, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4305 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4274, 111, 1216, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4306 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4275, 111, 1217, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4307 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4276, 111, 1218, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4308 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4277, 111, 1219, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4309 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4278, 111, 1220, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4310 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4279, 111, 1221, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
  4311 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4280, 111, 1222, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', b'0', 122);
4115 4312 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5779, 2, 2739, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
4116 4313 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5780, 2, 2740, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
4117 4314 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5781, 2, 2758, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
... ... @@ -4121,6 +4318,8 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4121 4318 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5785, 2, 2030, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0', 1);
4122 4319 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5789, 109, 2739, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 121);
4123 4320 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5790, 109, 2740, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 121);
  4321 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5791, 111, 2739, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 122);
  4322 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5792, 111, 2740, '1', '2024-07-13 22:37:24', '1', '2024-07-13 22:37:24', b'0', 122);
4124 4323 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6053, 155, 4000, '1', '2025-04-01 13:48:26', '1', '2025-04-01 13:48:26', b'0', 1);
4125 4324 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6097, 155, 4050, '1', '2025-04-01 13:48:26', '1', '2025-04-01 13:48:26', b'0', 1);
4126 4325 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6104, 155, 4032, '1', '2025-04-01 13:49:30', '1', '2025-04-01 13:49:30', b'0', 1);
... ... @@ -4195,6 +4394,45 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4195 4394 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6175, 109, 2557, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 121);
4196 4395 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6176, 109, 2558, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 121);
4197 4396 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6177, 109, 2559, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 121);
  4397 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6178, 111, 1117, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4398 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6179, 111, 1126, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4399 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6180, 111, 1127, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4400 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6181, 111, 1128, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4401 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6182, 111, 1129, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4402 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6183, 111, 1130, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4403 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6184, 111, 1132, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4404 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6185, 111, 1133, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4405 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6186, 111, 1134, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4406 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6187, 111, 1135, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4407 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6188, 111, 1136, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4408 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6189, 111, 1137, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4409 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6190, 111, 2161, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4410 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6191, 111, 1150, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4411 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6192, 111, 1161, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4412 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6193, 111, 1162, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4413 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6194, 111, 1166, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4414 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6195, 111, 1173, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4415 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6196, 111, 1174, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4416 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6197, 111, 1178, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4417 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6198, 111, 2745, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4418 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6199, 111, 2746, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4419 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6200, 111, 2747, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4420 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6201, 111, 2748, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4421 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6202, 111, 2301, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4422 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6203, 111, 2302, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4423 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6204, 111, 5011, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4424 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6205, 111, 5012, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4425 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6206, 111, 2549, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4426 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6207, 111, 2550, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4427 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6208, 111, 2551, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4428 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6209, 111, 2552, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4429 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6210, 111, 2553, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4430 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6211, 111, 2554, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4431 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6212, 111, 2555, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4432 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6213, 111, 2556, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4433 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6214, 111, 2557, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4434 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6215, 111, 2558, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
  4435 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6216, 111, 2559, '1', '2025-09-06 20:52:12', '1', '2025-09-06 20:52:12', b'0', 122);
4198 4436 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6217, 109, 2756, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 121);
4199 4437 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6218, 109, 2757, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 121);
4200 4438 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6219, 109, 2262, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 121);
... ... @@ -4233,6 +4471,44 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4233 4471 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6252, 109, 2335, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 121);
4234 4472 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6253, 109, 2363, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 121);
4235 4473 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6254, 109, 2364, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 121);
  4474 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6255, 111, 2756, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4475 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6256, 111, 2757, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4476 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6257, 111, 2262, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4477 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6258, 111, 2275, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4478 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6259, 111, 2276, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4479 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6260, 111, 2277, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4480 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6261, 111, 2281, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4481 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6262, 111, 2282, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4482 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6263, 111, 2283, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4483 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6264, 111, 2284, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4484 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6265, 111, 2285, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4485 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6266, 111, 2287, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4486 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6267, 111, 2288, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4487 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6268, 111, 2293, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4488 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6269, 111, 2294, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4489 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6270, 111, 2297, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4490 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6271, 111, 2300, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4491 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6272, 111, 2317, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4492 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6273, 111, 2318, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4493 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6274, 111, 2319, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4494 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6275, 111, 2320, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4495 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6276, 111, 2321, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4496 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6277, 111, 2322, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4497 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6278, 111, 2323, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4498 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6279, 111, 2324, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4499 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6280, 111, 2325, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4500 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6281, 111, 2326, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4501 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6282, 111, 2327, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4502 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6283, 111, 2328, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4503 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6284, 111, 2329, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4504 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6285, 111, 2330, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4505 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6286, 111, 2331, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4506 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6287, 111, 2332, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4507 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6288, 111, 2333, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4508 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6289, 111, 2334, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4509 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6290, 111, 2335, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4510 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6291, 111, 2363, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
  4511 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6292, 111, 2364, '1', '2025-09-06 20:52:25', '1', '2025-09-06 20:52:25', b'0', 122);
4236 4512 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6293, 2, 5, '1', '2026-01-04 18:09:41', '1', '2026-01-04 18:09:41', b'0', 1);
4237 4513 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6294, 2, 1118, '1', '2026-01-04 18:09:41', '1', '2026-01-04 18:09:41', b'0', 1);
4238 4514 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6295, 2, 1119, '1', '2026-01-04 18:09:41', '1', '2026-01-04 18:09:41', b'0', 1);
... ... @@ -4303,6 +4579,7 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4303 4579 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6360, 2, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1);
4304 4580 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6361, 3, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1);
4305 4581 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6362, 109, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 121);
  4582 +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6363, 111, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 122);
4306 4583 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6364, 155, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1);
4307 4584 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6365, 2, 6400, '1', '2026-05-09 16:11:01', '1', '2026-05-09 16:11:01', b'0', 1);
4308 4585 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6366, 2, 6401, '1', '2026-05-09 16:11:01', '1', '2026-05-09 16:11:01', b'0', 1);
... ... @@ -4312,317 +4589,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
4312 4589 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6370, 2, 6405, '1', '2026-05-09 16:11:01', '1', '2026-05-09 16:11:01', b'0', 1);
4313 4590 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6371, 2, 6406, '1', '2026-05-09 16:11:01', '1', '2026-05-09 16:11:01', b'0', 1);
4314 4591 INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6380, 2, 6490, '1', '2026-05-14 09:36:12', '1', '2026-05-14 09:36:12', b'0', 1);
4315   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6381, 111, 1, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4316   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6382, 111, 2, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4317   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6383, 111, 5, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4318   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6384, 111, 1031, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4319   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6385, 111, 1032, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4320   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6386, 111, 1033, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4321   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6387, 111, 1034, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4322   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6388, 111, 1035, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4323   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6389, 111, 1036, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4324   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6390, 111, 1037, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4325   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6391, 111, 1038, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4326   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6392, 111, 1039, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4327   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6393, 111, 1050, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4328   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6394, 111, 1051, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4329   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6395, 111, 1052, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4330   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6396, 111, 1053, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4331   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6397, 111, 1054, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4332   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6398, 111, 1056, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4333   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6399, 111, 1057, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4334   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6400, 111, 1058, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4335   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6401, 111, 1059, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4336   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6402, 111, 1060, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4337   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6403, 111, 1063, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4338   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6404, 111, 1064, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4339   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6405, 111, 1065, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4340   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6406, 111, 1066, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4341   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6407, 111, 1067, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4342   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6408, 111, 1070, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4343   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6409, 111, 1075, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4344   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6410, 111, 1077, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4345   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6411, 111, 1078, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4346   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6412, 111, 1082, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4347   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6413, 111, 1083, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4348   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6414, 111, 1084, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4349   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6415, 111, 1085, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4350   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6416, 111, 1086, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4351   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6417, 111, 1087, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4352   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6418, 111, 1088, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4353   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6419, 111, 1089, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4354   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6420, 111, 1090, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4355   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6421, 111, 1091, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4356   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6422, 111, 1092, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4357   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6423, 111, 1117, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4358   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6424, 111, 1118, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4359   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6425, 111, 1119, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4360   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6426, 111, 1120, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4361   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6427, 111, 100, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4362   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6428, 111, 101, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4363   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6429, 111, 102, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4364   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6430, 111, 1126, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4365   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6431, 111, 103, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4366   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6432, 111, 1127, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4367   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6433, 111, 1128, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4368   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6434, 111, 1129, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4369   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6435, 111, 106, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4370   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6436, 111, 1130, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4371   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6437, 111, 107, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4372   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6438, 111, 1132, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4373   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6439, 111, 1133, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4374   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6440, 111, 110, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4375   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6441, 111, 1134, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4376   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6442, 111, 111, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4377   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6443, 111, 1135, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4378   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6444, 111, 112, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4379   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6445, 111, 1136, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4380   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6446, 111, 113, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4381   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6447, 111, 1137, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4382   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6448, 111, 2161, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4383   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6449, 111, 114, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4384   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6450, 111, 1138, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4385   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6451, 111, 1139, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4386   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6452, 111, 115, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4387   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6453, 111, 1140, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4388   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6454, 111, 116, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4389   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6455, 111, 1141, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4390   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6456, 111, 1142, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4391   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6457, 111, 1143, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4392   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6458, 111, 1150, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4393   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6459, 111, 1161, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4394   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6460, 111, 1162, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4395   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6461, 111, 1166, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4396   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6462, 111, 1173, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4397   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6463, 111, 1174, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4398   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6464, 111, 2713, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4399   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6465, 111, 2714, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4400   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6466, 111, 1178, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4401   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6467, 111, 2715, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4402   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6468, 111, 2716, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4403   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6469, 111, 2717, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4404   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6470, 111, 2718, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4405   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6471, 111, 2720, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4406   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6472, 111, 2721, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4407   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6473, 111, 1185, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4408   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6474, 111, 2722, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4409   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6475, 111, 1186, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4410   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6476, 111, 1187, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4411   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6477, 111, 2723, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4412   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6478, 111, 1188, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4413   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6479, 111, 2724, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4414   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6480, 111, 1189, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4415   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6481, 111, 2725, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4416   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6482, 111, 1190, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4417   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6483, 111, 2726, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4418   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6484, 111, 1191, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4419   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6485, 111, 2727, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4420   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6486, 111, 1192, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4421   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6487, 111, 2728, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4422   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6488, 111, 2729, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4423   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6489, 111, 1193, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4424   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6490, 111, 1194, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4425   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6491, 111, 2730, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4426   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6492, 111, 1195, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4427   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6493, 111, 2731, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4428   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6494, 111, 2732, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4429   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6495, 111, 1197, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4430   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6496, 111, 2733, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4431   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6497, 111, 1198, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4432   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6498, 111, 2734, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4433   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6499, 111, 1199, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4434   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6500, 111, 2735, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4435   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6501, 111, 1200, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4436   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6502, 111, 1201, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4437   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6503, 111, 1202, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4438   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6504, 111, 2739, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4439   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6505, 111, 2740, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4440   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6506, 111, 1207, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4441   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6507, 111, 1208, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4442   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6508, 111, 1209, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4443   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6509, 111, 2745, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4444   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6510, 111, 1210, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4445   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6511, 111, 2746, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4446   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6512, 111, 1211, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4447   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6513, 111, 2747, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4448   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6514, 111, 1212, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4449   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6515, 111, 2748, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4450   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6516, 111, 1213, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4451   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6517, 111, 1215, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4452   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6518, 111, 1216, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4453   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6519, 111, 1217, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4454   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6520, 111, 1218, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4455   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6521, 111, 1219, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4456   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6522, 111, 1220, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4457   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6523, 111, 2756, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4458   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6524, 111, 1221, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4459   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6525, 111, 2757, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4460   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6526, 111, 1222, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4461   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6527, 111, 1224, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4462   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6528, 111, 1225, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4463   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6529, 111, 1226, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4464   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6530, 111, 1227, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4465   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6531, 111, 1228, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4466   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6532, 111, 1229, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4467   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6533, 111, 1237, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4468   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6534, 111, 1238, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4469   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6535, 111, 2262, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4470   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6536, 111, 1239, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4471   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6537, 111, 1240, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4472   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6538, 111, 1241, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4473   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6539, 111, 1242, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4474   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6540, 111, 1243, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4475   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6541, 111, 2275, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4476   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6542, 111, 2276, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4477   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6543, 111, 2277, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4478   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6544, 111, 1255, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4479   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6545, 111, 1256, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4480   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6546, 111, 1257, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4481   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6547, 111, 2281, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4482   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6548, 111, 1258, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4483   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6549, 111, 2282, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4484   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6550, 111, 1259, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4485   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6551, 111, 2283, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4486   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6552, 111, 1260, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4487   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6553, 111, 2284, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4488   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6554, 111, 2285, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4489   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6555, 111, 2287, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4490   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6556, 111, 2288, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4491   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6557, 111, 2293, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4492   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6558, 111, 2294, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4493   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6559, 111, 2297, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4494   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6560, 111, 2300, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4495   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6561, 111, 2301, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4496   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6562, 111, 2302, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4497   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6563, 111, 2317, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4498   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6564, 111, 2318, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4499   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6565, 111, 2319, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4500   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6566, 111, 2320, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4501   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6567, 111, 2321, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4502   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6568, 111, 2322, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4503   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6569, 111, 2323, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4504   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6570, 111, 2324, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4505   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6571, 111, 2325, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4506   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6572, 111, 2326, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4507   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6573, 111, 2327, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4508   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6574, 111, 2328, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4509   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6575, 111, 2329, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4510   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6576, 111, 2330, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4511   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6577, 111, 2331, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4512   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6578, 111, 2332, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4513   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6579, 111, 2333, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4514   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6580, 111, 2334, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4515   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6581, 111, 2335, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4516   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6582, 111, 2363, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4517   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6583, 111, 2364, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4518   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6584, 111, 5011, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4519   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6585, 111, 5012, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4520   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6586, 111, 2472, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4521   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6587, 111, 2478, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4522   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6588, 111, 2479, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4523   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6589, 111, 2480, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4524   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6590, 111, 2481, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4525   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6591, 111, 2482, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4526   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6592, 111, 2483, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4527   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6593, 111, 2484, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4528   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6594, 111, 2485, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4529   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6595, 111, 2486, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4530   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6596, 111, 2487, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4531   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6597, 111, 2488, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4532   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6598, 111, 2489, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4533   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6599, 111, 2490, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4534   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6600, 111, 2491, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4535   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6601, 111, 2492, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4536   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6602, 111, 2493, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4537   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6603, 111, 2494, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4538   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6604, 111, 2495, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4539   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6605, 111, 2497, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4540   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6606, 111, 2525, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4541   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6607, 111, 1001, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4542   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6608, 111, 1002, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4543   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6609, 111, 1003, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4544   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6610, 111, 1004, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4545   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6611, 111, 1005, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4546   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6612, 111, 1006, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4547   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6613, 111, 1007, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4548   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6614, 111, 1008, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4549   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6615, 111, 1009, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4550   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6616, 111, 1010, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4551   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6617, 111, 1011, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4552   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6618, 111, 1012, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4553   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6619, 111, 1013, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4554   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6620, 111, 2549, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4555   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6621, 111, 1014, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4556   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6622, 111, 2550, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4557   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6623, 111, 1015, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4558   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6624, 111, 2551, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4559   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6625, 111, 1016, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4560   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6626, 111, 2552, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4561   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6627, 111, 1017, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4562   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6628, 111, 2553, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4563   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6629, 111, 1018, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4564   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6630, 111, 2554, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4565   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6631, 111, 1019, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4566   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6632, 111, 2555, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4567   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6633, 111, 1020, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4568   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6634, 111, 2556, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4569   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6635, 111, 2557, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4570   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6636, 111, 2558, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4571   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6637, 111, 2559, '1', '2026-06-01 23:29:35', '1', '2026-06-01 23:29:35', b'0', 122);
4572   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6638, 155, 5780, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4573   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6639, 155, 2084, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4574   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6640, 155, 2085, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4575   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6641, 155, 2086, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4576   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6642, 155, 2087, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4577   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6643, 155, 2088, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4578   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6644, 155, 2089, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4579   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6645, 155, 2090, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4580   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6646, 155, 2091, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4581   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6647, 155, 2092, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4582   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6648, 155, 2093, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4583   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6649, 155, 5805, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4584   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6650, 155, 2094, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4585   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6651, 155, 2095, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4586   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6652, 155, 2096, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4587   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6653, 155, 2097, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4588   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6654, 155, 2098, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4589   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6655, 155, 5042, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4590   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6656, 155, 2099, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4591   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6657, 155, 5043, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4592   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6658, 155, 2100, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4593   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6659, 155, 5044, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4594   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6660, 155, 2101, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4595   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6661, 155, 5045, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4596   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6662, 155, 2102, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4597   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6663, 155, 5046, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4598   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6664, 155, 2103, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4599   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6665, 155, 2104, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4600   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6666, 155, 2105, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4601   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6667, 155, 2106, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4602   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6668, 155, 2107, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4603   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6669, 155, 2108, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4604   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6670, 155, 2109, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4605   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6671, 155, 2110, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4606   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6672, 155, 2111, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4607   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6673, 155, 2112, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4608   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6674, 155, 2113, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4609   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6675, 155, 2114, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4610   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6676, 155, 2115, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4611   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6677, 155, 2116, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4612   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6678, 155, 2117, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4613   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6679, 155, 2118, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4614   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6680, 155, 2119, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4615   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6681, 155, 2120, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4616   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6682, 155, 2121, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4617   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6683, 155, 2122, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4618   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6684, 155, 2123, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4619   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6685, 155, 2124, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4620   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6686, 155, 2125, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4621   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6687, 155, 2126, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4622   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6688, 155, 2127, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4623   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6689, 155, 2128, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4624   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6690, 155, 2129, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4625   -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6691, 155, 5100, '1', '2026-06-10 09:04:18', '1', '2026-06-10 09:04:18', b'0', 1);
4626 4592 COMMIT;
4627 4593  
4628 4594 -- ----------------------------
... ... @@ -4677,7 +4643,7 @@ CREATE TABLE `system_sms_code` (
4677 4643 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
4678 4644 PRIMARY KEY (`id`) USING BTREE,
4679 4645 INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
4680   -) ENGINE = InnoDB AUTO_INCREMENT = 694 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
  4646 +) ENGINE = InnoDB AUTO_INCREMENT = 690 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
4681 4647  
4682 4648 -- ----------------------------
4683 4649 -- Records of system_sms_code
... ... @@ -4718,7 +4684,7 @@ CREATE TABLE `system_sms_log` (
4718 4684 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
4719 4685 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
4720 4686 PRIMARY KEY (`id`) USING BTREE
4721   -) ENGINE = InnoDB AUTO_INCREMENT = 1568 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
  4687 +) ENGINE = InnoDB AUTO_INCREMENT = 1553 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
4722 4688  
4723 4689 -- ----------------------------
4724 4690 -- Records of system_sms_log
... ... @@ -4895,7 +4861,7 @@ CREATE TABLE `system_tenant` (
4895 4861 BEGIN;
4896 4862 INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn,127.0.0.1:3000,wxc4598c446f8a9cb3', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2025-08-19 05:18:41', b'0');
4897 4863 INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn,123321', 111, '2026-07-10 00:00:00', 30, '1', '2022-02-22 00:56:14', '1', '2025-08-19 21:19:29', b'0');
4898   -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn,222,333', 111, '2023-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2026-06-01 23:29:35', b'0');
  4864 +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `websites`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn,222,333', 111, '2023-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2025-12-21 09:50:00', b'0');
4899 4865 COMMIT;
4900 4866  
4901 4867 -- ----------------------------
... ... @@ -4914,14 +4880,13 @@ CREATE TABLE `system_tenant_package` (
4914 4880 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
4915 4881 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
4916 4882 PRIMARY KEY (`id`) USING BTREE
4917   -) ENGINE = InnoDB AUTO_INCREMENT = 114 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '租户套餐表';
  4883 +) ENGINE = InnoDB AUTO_INCREMENT = 113 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '租户套餐表';
4918 4884  
4919 4885 -- ----------------------------
4920 4886 -- Records of system_tenant_package
4921 4887 -- ----------------------------
4922 4888 BEGIN;
4923 4889 INSERT INTO `system_tenant_package` (`id`, `name`, `status`, `remark`, `menu_ids`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (111, '普通套餐', 0, '小功能', '[1,2,5,1031,1032,1033,1034,1035,1036,1037,1038,1039,1050,1051,1052,1053,1054,1056,1057,1058,1059,1060,1063,1064,1065,1066,1067,1070,1075,1077,1078,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1117,1118,1119,1120,100,101,102,1126,103,1127,1128,1129,106,1130,107,1132,1133,110,1134,111,1135,112,1136,113,1137,2161,114,1138,1139,115,1140,116,1141,1142,1143,1150,1161,1162,1166,1173,1174,2713,2714,1178,2715,2716,2717,2718,2720,2721,1185,2722,1186,1187,2723,1188,2724,1189,2725,1190,2726,1191,2727,1192,2728,2729,1193,1194,2730,1195,2731,2732,1197,2733,1198,2734,1199,2735,1200,1201,1202,2739,2740,1207,1208,1209,2745,1210,2746,1211,2747,1212,2748,1213,1215,1216,1217,1218,1219,1220,2756,1221,2757,1222,1224,1225,1226,1227,1228,1229,1237,1238,2262,1239,1240,1241,1242,1243,2275,2276,2277,1255,1256,1257,2281,1258,2282,1259,2283,1260,2284,2285,2287,2288,2293,2294,2297,2300,2301,2302,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2363,2364,5011,5012,2472,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2497,2525,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,2549,1014,2550,1015,2551,1016,2552,1017,2553,1018,2554,1019,2555,1020,2556,2557,2558,2559]', '1', '2022-02-22 00:54:00', '1', '2025-09-06 20:52:25', b'0');
4924   -INSERT INTO `system_tenant_package` (`id`, `name`, `status`, `remark`, `menu_ids`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (113, '测试套餐(啥都没有)', 0, '', '[2160,1254,2159]', '1', '2026-06-01 23:22:39', '1', '2026-06-09 14:44:00', b'0');
4925 4890 COMMIT;
4926 4891  
4927 4892 -- ----------------------------
... ... @@ -5039,26 +5004,26 @@ CREATE TABLE `system_users` (
5039 5004 -- Records of system_users
5040 5005 -- ----------------------------
5041 5006 BEGIN;
5042   -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$04$.vd8nPeLwxt6hnSzmAoAyul8BOLX7Cib6QhcxRe30rfvrIPQHH1OG', '芋道源码', '管理员', 103, '[1,2]', '13aoteman@126.com', '18818260272', 1, 'http://test.yudao.iocoder.cn/20260517/blob_1778998103688.png', 0, '0:0:0:0:0:0:0:1', '2026-06-19 18:38:00', 'admin', '2021-01-05 17:03:47', NULL, '2026-06-19 18:38:00', b'0', 1);
5043   -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$04$.vd8nPeLwxt6hnSzmAoAyul8BOLX7Cib6QhcxRe30rfvrIPQHH1OG', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, NULL, 0, '127.0.0.1', '2026-06-17 09:37:17', '', '2021-01-07 09:07:17', NULL, '2026-06-17 09:37:17', b'0', 1);
  5007 +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$04$.vd8nPeLwxt6hnSzmAoAyul8BOLX7Cib6QhcxRe30rfvrIPQHH1OG', '芋道源码', '管理员', 103, '[1,2]', '13aoteman@126.com', '18818260272', 1, 'http://test.yudao.iocoder.cn/20260517/blob_1778998103688.png', 0, '0:0:0:0:0:0:0:1', '2026-05-31 21:54:49', 'admin', '2021-01-05 17:03:47', NULL, '2026-05-31 21:54:49', b'0', 1);
  5008 +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$04$.vd8nPeLwxt6hnSzmAoAyul8BOLX7Cib6QhcxRe30rfvrIPQHH1OG', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2026-04-19 17:40:55', '', '2021-01-07 09:07:17', NULL, '2026-04-19 17:40:55', b'0', 1);
5044 5009 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$04$k/d6mc0nySN0i2udwcI8Ee8V5aM5OHixBRbQfXmPuFTUl3Zf/DBs.', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2026-04-27 13:19:27', '', '2021-01-13 23:50:35', NULL, '2026-04-27 13:19:27', b'0', 1);
5045   -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$04$BrwaYn303hjA/6TnXqdGoOLhyHOAA0bVrAFu6.1dJKycqKUnIoRz2', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2026-06-16 11:37:56', '', '2021-01-21 02:13:53', NULL, '2026-06-16 11:37:56', b'0', 1);
  5010 +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$04$BrwaYn303hjA/6TnXqdGoOLhyHOAA0bVrAFu6.1dJKycqKUnIoRz2', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2026-05-20 23:37:11', '', '2021-01-21 02:13:53', NULL, '2026-05-20 23:37:11', b'0', 1);
5046 5011 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (107, 'admin107', '$2a$10$dYOOBKMO93v/.ReCqzyFg.o67Tqk.bbc2bhrpyBGkIw9aypCtr2pm', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, NULL, 0, '', NULL, '1', '2022-02-20 22:59:33', '1', '2025-04-21 14:23:08', b'0', 118);
5047 5012 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (108, 'admin108', '$2a$10$y6mfvKoNYL1GXWak8nYwVOH.kCWqjactkzdoIDgiKl93WN3Ejg.Lu', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, NULL, 0, '', NULL, '1', '2022-02-20 23:00:50', '1', '2025-04-21 14:23:08', b'0', 119);
5048 5013 INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, 'admin109', '$2a$10$JAqvH0tEc0I7dfDVBI7zyuB4E3j.uH6daIjV53.vUS6PknFkDJkuK', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, NULL, 0, '', NULL, '1', '2022-02-20 23:11:50', '1', '2025-04-21 14:23:08', b'0', 120);
5049 5014 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 (110, 'admin110', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '小王', NULL, NULL, NULL, '', '15601691300', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2024-07-20 22:23:17', '1', '2022-02-22 00:56:14', NULL, '2025-04-21 14:23:08', b'0', 121);
5050 5015 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 (111, 'test', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '测试用户', NULL, NULL, '[]', '', '', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2023-12-30 11:42:17', '110', '2022-02-23 13:14:33', NULL, '2025-04-21 14:23:08', b'0', 121);
5051   -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 (112, 'newobject', '$2a$04$dB0z8Q819fJWz0hbaLe6B.VfHCjYgWx6LFfET5lyz3JwcqlyCkQ4C', '新对象', NULL, 100, '[]', '', '15601691235', 1, NULL, 0, '127.0.0.1', '2026-06-17 09:07:20', '1', '2022-02-23 19:08:03', NULL, '2026-06-17 09:07:20', b'0', 1);
  5016 +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 (112, 'newobject', '$2a$04$dB0z8Q819fJWz0hbaLe6B.VfHCjYgWx6LFfET5lyz3JwcqlyCkQ4C', '新对象', NULL, 100, '[]', '', '15601691235', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-03-16 23:11:38', '1', '2022-02-23 19:08:03', NULL, '2025-04-21 14:23:08', b'0', 1);
5052 5017 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 (113, 'aoteman', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道1', NULL, NULL, NULL, '', '15601691300', 0, NULL, 0, '127.0.0.1', '2022-03-19 18:38:51', '1', '2022-03-07 21:37:58', '1', '2025-05-05 15:30:53', b'0', 122);
5053 5018 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 (114, 'hrmgr', '$2a$10$TR4eybBioGRhBmDBWkqWLO6NIh3mzYa8KBKDDB5woiGYFVlRAi.fu', 'hr 小姐姐', NULL, NULL, '[5]', '', '15601691236', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2026-01-04 18:16:01', '1', '2022-03-19 21:50:58', NULL, '2026-01-04 18:16:01', b'0', 1);
5054 5019 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 (115, 'aotemane', '$2a$04$GcyP0Vyzb2F2Yni5PuIK9ueGxM0tkZGMtDwVRwrNbtMvorzbpNsV2', '阿呆', '11222', 102, '[1,2]', '7648@qq.com', '15601691229', 2, NULL, 0, '', NULL, '1', '2022-04-30 02:55:43', '1', '2025-04-21 14:23:08', b'0', 1);
5055 5020 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 (117, 'admin123', '$2a$04$sEtimsHu9YCkYY4/oqElHem2Ijc9ld20eYO6lN.g/21NfLUTDLB9W', '测试号02', '1111', 100, '[2]', '', '15601691234', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-10-02 10:16:20', '1', '2022-07-09 17:40:26', '1', '2025-05-14 09:56:04', b'0', 1);
5056 5021 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 (118, 'goudan', '$2a$04$3suGZjnA6rM5bErf38u1felbgqbsPHGdRG3l9NkxPCEt2ah9Y6aJi', '狗蛋', NULL, 103, '[1]', '', '15601691239', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2025-11-23 15:28:25', '1', '2022-07-09 17:44:43', NULL, '2025-11-23 15:28:25', b'0', 1);
5057 5022 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 (139, 'wwbwwb', '$2a$04$FJLIyg8lbPytP29pbZaiU.LesJvCsYfEaHqQfB0pGQhK3e9BeZmLy', '小秃头', '123', 108, '[2,4]', '', '', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2024-09-10 21:03:58', NULL, '2024-09-10 21:03:58', '1', '2025-12-15 22:38:15', b'0', 1);
5058   -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 (141, 'admin1', '$2a$04$oj6F6d7HrZ70kYVD3TNzEu.m3TPUzajOVuC66zdKna8KRerK1FmVa', '新用户', NULL, NULL, NULL, '', '', 0, '', 0, '127.0.0.1', '2026-06-17 09:37:18', '1', '2025-04-08 13:09:07', NULL, '2026-06-17 09:37:18', b'0', 1);
5059   -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 (142, 'test01', '$2a$04$4bCYWZkjxxOC4QE0LY2M9uEEKWeJbLfs489NFtQoyidL5I0FndRaO', 'test01', '', NULL, '[]', '', '19021719925', 1, '', 0, '0:0:0:0:0:0:0:1', '2026-06-17 10:44:58', '1', '2025-07-09 21:07:10', NULL, '2026-06-17 10:44:58', b'0', 1);
  5023 +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 (141, 'admin1', '$2a$04$oj6F6d7HrZ70kYVD3TNzEu.m3TPUzajOVuC66zdKna8KRerK1FmVa', '新用户', NULL, NULL, NULL, '', '', 0, '', 0, '0:0:0:0:0:0:0:1', '2025-04-08 13:09:07', '1', '2025-04-08 13:09:07', '1', '2025-05-14 19:11:48', b'0', 1);
  5024 +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 (142, 'test01', '$2a$04$4bCYWZkjxxOC4QE0LY2M9uEEKWeJbLfs489NFtQoyidL5I0FndRaO', 'test01', '', NULL, '[]', '', '19021719925', 1, '', 0, '0:0:0:0:0:0:0:1', '2025-07-29 19:47:17', '1', '2025-07-09 21:07:10', NULL, '2025-12-02 13:23:11', b'0', 1);
5060 5025 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 (143, 'a00001', '$2a$04$GhVHFviOw/SsTmiQtifHJesDYFlHMeGK7OWh7aGCCjGGVCmbHVAwa', 'a00001', NULL, 104, NULL, '', '', 0, '', 0, '0:0:0:0:0:0:0:1', '2025-12-01 16:10:13', NULL, '2025-12-01 16:10:13', '1', '2025-12-05 21:34:05', b'0', 1);
5061   -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 (144, 'aoteman001', '$2a$04$omQOmhz8OyUFBKw77nr8KOtMp6xdvoQ1gWStjk9r8.OYT3Bv6oEYe', 'aoteman00112', NULL, 104, NULL, '', '', 0, '', 1, '0:0:0:0:0:0:0:1', '2025-12-01 17:05:27', '1', '2025-12-01 17:05:27', '1', '2026-06-15 18:58:56', b'0', 1);
  5026 +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 (144, 'aoteman001', '$2a$04$omQOmhz8OyUFBKw77nr8KOtMp6xdvoQ1gWStjk9r8.OYT3Bv6oEYe', 'aoteman001', NULL, 104, NULL, '', '', 0, '', 1, '0:0:0:0:0:0:0:1', '2025-12-01 17:05:27', '1', '2025-12-01 17:05:27', '1', '2026-05-31 21:52:48', b'0', 1);
5062 5027 COMMIT;
5063 5028  
5064 5029 -- ----------------------------
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationReadController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.controller.admin.conversation;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationReadRespVO;
  6 +import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationReadDO;
  7 +import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
  8 +import io.swagger.v3.oas.annotations.Operation;
  9 +import io.swagger.v3.oas.annotations.Parameter;
  10 +import io.swagger.v3.oas.annotations.Parameters;
  11 +import io.swagger.v3.oas.annotations.tags.Tag;
  12 +import jakarta.annotation.Resource;
  13 +import jakarta.validation.constraints.Max;
  14 +import jakarta.validation.constraints.Min;
  15 +import org.springframework.validation.annotation.Validated;
  16 +import org.springframework.web.bind.annotation.GetMapping;
  17 +import org.springframework.web.bind.annotation.RequestMapping;
  18 +import org.springframework.web.bind.annotation.RequestParam;
  19 +import org.springframework.web.bind.annotation.RestController;
  20 +
  21 +import java.util.List;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
  25 +
  26 +@Tag(name = "管理后台 - IM 会话读位置")
  27 +@RestController
  28 +@RequestMapping("/im/conversation-read")
  29 +@Validated
  30 +public class ImConversationReadController {
  31 +
  32 + @Resource
  33 + private ImConversationReadService conversationReadService;
  34 +
  35 + @GetMapping("/pull")
  36 + @Operation(summary = "增量拉取当前用户的会话读位置(重连 / 离线补偿)")
  37 + @Parameters({
  38 + @Parameter(name = "lastUpdateTime", description = "上次拉取到的最新更新时间(毫秒时间戳);首次拉取不传"),
  39 + @Parameter(name = "lastId", description = "上次拉取到的最后一条记录 id;首次拉取不传"),
  40 + @Parameter(name = "limit", description = "单次拉取条数", required = true)
  41 + })
  42 + public CommonResult<List<ImConversationReadRespVO>> pullMyConversationRead(
  43 + @RequestParam(value = "lastUpdateTime", required = false) Long lastUpdateTime,
  44 + @RequestParam(value = "lastId", required = false) Long lastId,
  45 + @RequestParam("limit") @Min(1) @Max(200) Integer limit) {
  46 + List<ImConversationReadDO> list = conversationReadService.pullConversationReadList(
  47 + getLoginUserId(), lastUpdateTime, lastId, limit);
  48 + return success(BeanUtils.toBean(list, ImConversationReadRespVO.class));
  49 + }
  50 +
  51 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationReadRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.controller.admin.conversation.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * IM 会话读位置 Response VO
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Schema(description = "管理后台 - IM 会话读位置 Response VO")
  14 +@Data
  15 +public class ImConversationReadRespVO {
  16 +
  17 + @Schema(description = "读位置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  18 + private Long id;
  19 +
  20 + @Schema(description = "会话类型", example = "1")
  21 + private Integer conversationType; // 参见 ImConversationTypeEnum 枚举
  22 +
  23 + @Schema(description = "目标编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
  24 + private Long targetId;
  25 +
  26 + @Schema(description = "最大已读消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
  27 + private Long messageId;
  28 +
  29 + @Schema(description = "最近更新时间(增量拉取游标用)")
  30 + private LocalDateTime updateTime;
  31 +
  32 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java
... ... @@ -17,6 +17,8 @@ import io.swagger.v3.oas.annotations.Parameters;
17 17 import io.swagger.v3.oas.annotations.tags.Tag;
18 18 import jakarta.annotation.Resource;
19 19 import jakarta.validation.Valid;
  20 +import jakarta.validation.constraints.Max;
  21 +import jakarta.validation.constraints.Min;
20 22 import jakarta.validation.constraints.NotNull;
21 23 import org.springframework.validation.annotation.Validated;
22 24 import org.springframework.web.bind.annotation.*;
... ... @@ -46,11 +48,25 @@ public class ImFriendController {
46 48 @GetMapping("/list")
47 49 @Operation(summary = "获得当前登录用户的好友列表")
48 50 public CommonResult<List<ImFriendRespVO>> getMyFriendList() {
49   - // 含 DISABLE 历史好友:保留给前端展示「已删除好友」的历史对话信息;前端按 status 决定会话级联清理
50 51 List<ImFriendDO> friends = friendService.getFriendList(getLoginUserId());
51 52 return success(buildFriendRespVOList(friends));
52 53 }
53 54  
  55 + @GetMapping("/pull")
  56 + @Operation(summary = "增量拉取当前用户的好友关系(重连 / 离线补偿)")
  57 + @Parameters({
  58 + @Parameter(name = "lastUpdateTime", description = "上次拉取到的最新更新时间(毫秒时间戳);首次拉取不传"),
  59 + @Parameter(name = "lastId", description = "上次拉取到的最后一条记录 id;首次拉取不传"),
  60 + @Parameter(name = "limit", description = "单次拉取条数", required = true)
  61 + })
  62 + public CommonResult<List<ImFriendRespVO>> pullMyFriendList(
  63 + @RequestParam(value = "lastUpdateTime", required = false) Long lastUpdateTime,
  64 + @RequestParam(value = "lastId", required = false) Long lastId,
  65 + @RequestParam("limit") @Min(1) @Max(200) Integer limit) {
  66 + List<ImFriendDO> list = friendService.pullFriendList(getLoginUserId(), lastUpdateTime, lastId, limit);
  67 + return success(buildFriendRespVOList(list));
  68 + }
  69 +
54 70 @GetMapping("/get")
55 71 @Operation(summary = "获得好友详情")
56 72 @Parameter(name = "friendUserId", description = "好友的用户编号", required = true, example = "2048")
... ... @@ -62,8 +78,8 @@ public class ImFriendController {
62 78 @DeleteMapping("/delete")
63 79 @Operation(summary = "删除好友(单向软删除)")
64 80 @Parameters({
65   - @Parameter(description = "好友的用户编号", required = true, example = "2048"),
66   - @Parameter(description = "是否级联清理本端相关数据(如私聊会话)")
  81 + @Parameter(name = "friendUserId", description = "好友的用户编号", required = true, example = "2048"),
  82 + @Parameter(name = "clear", description = "是否级联清理本端相关数据(如私聊会话)")
67 83 })
68 84 public CommonResult<Boolean> deleteFriend(
69 85 @RequestParam("friendUserId") @NotNull(message = "好友用户编号不能为空") Long friendUserId,
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java
... ... @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
13 13 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
14 14 import io.swagger.v3.oas.annotations.Operation;
15 15 import io.swagger.v3.oas.annotations.Parameter;
  16 +import io.swagger.v3.oas.annotations.Parameters;
16 17 import io.swagger.v3.oas.annotations.tags.Tag;
17 18 import jakarta.annotation.Resource;
18 19 import jakarta.validation.Valid;
... ... @@ -79,15 +80,32 @@ public class ImFriendRequestController {
79 80  
80 81 @GetMapping("/list")
81 82 @Operation(summary = "查询「我相关」的好友申请列表(游标分页:传 maxId 加载更多)")
  83 + @Parameters({
  84 + @Parameter(name = "maxId", description = "当前列表最旧记录的 id;首页不传"),
  85 + @Parameter(name = "limit", description = "单次拉取条数", required = true)
  86 + })
82 87 public CommonResult<List<ImFriendRequestRespVO>> getMyFriendRequestList(
83   - @Parameter(description = "当前列表最旧记录的 id;首页不传")
84 88 @RequestParam(value = "maxId", required = false) Long maxId,
85   - @Parameter(description = "单次拉取条数", required = true)
86 89 @RequestParam("limit") @Min(1) @Max(200) Integer limit) {
87 90 List<ImFriendRequestDO> list = friendRequestService.getMyFriendRequestList(getLoginUserId(), maxId, limit);
88 91 return success(buildList(list));
89 92 }
90 93  
  94 + @GetMapping("/pull")
  95 + @Operation(summary = "增量拉取「我相关」的好友申请(重连 / 离线补偿)")
  96 + @Parameters({
  97 + @Parameter(name = "lastUpdateTime", description = "上次拉取到的最新更新时间(毫秒时间戳);首次拉取不传"),
  98 + @Parameter(name = "lastId", description = "上次拉取到的最后一条记录 id;首次拉取不传"),
  99 + @Parameter(name = "limit", description = "单次拉取条数", required = true)
  100 + })
  101 + public CommonResult<List<ImFriendRequestRespVO>> pullMyFriendRequestList(
  102 + @RequestParam(value = "lastUpdateTime", required = false) Long lastUpdateTime,
  103 + @RequestParam(value = "lastId", required = false) Long lastId,
  104 + @RequestParam("limit") @Min(1) @Max(200) Integer limit) {
  105 + List<ImFriendRequestDO> list = friendRequestService.pullFriendRequestList(getLoginUserId(), lastUpdateTime, lastId, limit);
  106 + return success(buildList(list));
  107 + }
  108 +
91 109 @GetMapping("/get")
92 110 @Operation(summary = "按 id 单查「我相关」的申请记录(带越权过滤;WebSocket 通知到达后用)")
93 111 @Parameter(name = "id", description = "申请记录编号", required = true)
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendRespVO.java
... ... @@ -47,6 +47,9 @@ public class ImFriendRespVO {
47 47 @Schema(description = "删除好友时间")
48 48 private LocalDateTime deleteTime;
49 49  
  50 + @Schema(description = "最近更新时间(增量拉取游标用)")
  51 + private LocalDateTime updateTime;
  52 +
50 53 // ========== 下面是聚合字段,方便前端显示 ==========
51 54  
52 55 @Schema(description = "好友昵称(实时聚合自 AdminUser)", example = "芋道")
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/request/ImFriendRequestRespVO.java
... ... @@ -41,6 +41,9 @@ public class ImFriendRequestRespVO {
41 41 @Schema(description = "申请创建时间")
42 42 private LocalDateTime createTime;
43 43  
  44 + @Schema(description = "最近更新时间(增量拉取游标用)")
  45 + private LocalDateTime updateTime;
  46 +
44 47 // ========== 下面是聚合字段,方便前端显示 ==========
45 48  
46 49 @Schema(description = "发起方昵称(实时聚合自 AdminUser)", example = "芋道")
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.im.controller.admin.group;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
6 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 8 import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
8 9 import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO;
... ... @@ -187,8 +188,10 @@ public class ImGroupController {
187 188 return Collections.emptyList();
188 189 }
189 190 // 仅当前用户是有效成员的群才允许回填置顶消息
190   - Set<Long> activeGroupIds = convertSet(
191   - groupMemberService.getActiveGroupMemberListByUserId(loginUserId), ImGroupMemberDO::getGroupId);
  191 + Map<Long, ImGroupMemberDO> memberMap = convertMap(
  192 + groupMemberService.getGroupMemberListByUserId(loginUserId), ImGroupMemberDO::getGroupId);
  193 + Set<Long> activeGroupIds = convertSet(memberMap.values(), ImGroupMemberDO::getGroupId,
  194 + member -> CommonStatusEnum.ENABLE.getStatus().equals(member.getStatus()));
192 195 Set<Long> allMessageIds = convertSetByFlatMap(groups, group -> activeGroupIds.contains(group.getId())
193 196 ? CollUtil.emptyIfNull(group.getPinnedMessageIds()).stream() : Stream.empty());
194 197 Map<Long, ImGroupMessageDO> messageMap = groupMessageService.getGroupMessageMap(allMessageIds);
... ... @@ -198,6 +201,8 @@ public class ImGroupController {
198 201 // 标记登录用户在该群的成员状态,供前端区分当前群与历史退群
199 202 boolean joined = activeGroupIds.contains(group.getId());
200 203 groupVO.setJoinStatus(joined ? CommonStatusEnum.ENABLE.getStatus() : CommonStatusEnum.DISABLE.getStatus());
  204 + MapUtils.findAndThen(memberMap, group.getId(), member ->
  205 + groupVO.setGroupRemark(member.getGroupRemark()).setSilent(Boolean.TRUE.equals(member.getSilent())));
201 206 if (!joined || CollUtil.isEmpty(group.getPinnedMessageIds())) {
202 207 return groupVO;
203 208 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupMemberController.java
... ... @@ -21,6 +21,7 @@ import jakarta.validation.Valid;
21 21 import org.springframework.validation.annotation.Validated;
22 22 import org.springframework.web.bind.annotation.*;
23 23  
  24 +import java.util.Collections;
24 25 import java.util.List;
25 26 import java.util.Map;
26 27  
... ... @@ -88,7 +89,7 @@ public class ImGroupMemberController {
88 89 }
89 90  
90 91 @GetMapping("/list")
91   - @Operation(summary = "获得指定群的成员列表")
  92 + @Operation(summary = "获得指定群的成员列表(按群全量拉取,作为前端本地成员 cache 的完整基线)")
92 93 @Parameter(name = "groupId", description = "群编号", required = true, example = "1024")
93 94 public CommonResult<List<ImGroupMemberRespVO>> getGroupMemberList(@RequestParam("groupId") Long groupId) {
94 95 // 1.1 查询群成员列表(包含 DISABLE 已退群的成员,不按时间过滤)
... ... @@ -101,16 +102,30 @@ public class ImGroupMemberController {
101 102 throw exception(GROUP_MEMBER_NOT_IN_GROUP);
102 103 }
103 104  
104   - // 2.批量聚合 AdminUser 信息(昵称 / 头像)
  105 + // 2. 批量聚合昵称 / 头像,并对非本人置空私人字段
  106 + return success(buildGroupMemberRespVOList(members));
  107 + }
  108 +
  109 + // ========== 私有方法:VO 组装 ==========
  110 +
  111 + /**
  112 + * 群成员列表批量转 VO + 关联回填昵称 / 头像,并对非本人置空私人字段
  113 + */
  114 + private List<ImGroupMemberRespVO> buildGroupMemberRespVOList(List<ImGroupMemberDO> members) {
  115 + if (CollUtil.isEmpty(members)) {
  116 + return Collections.emptyList();
  117 + }
  118 + Long loginUserId = getLoginUserId();
  119 + // 批量聚合 AdminUser 信息(昵称 / 头像),避免 N+1
105 120 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
106 121 convertList(members, ImGroupMemberDO::getUserId));
107   - return success(convertList(members, m -> {
108   - ImGroupMemberRespVO vo = BeanUtils.toBean(m, ImGroupMemberRespVO.class);
109   - MapUtils.findAndThen(userMap, m.getUserId(), user ->
  122 + return convertList(members, member -> {
  123 + ImGroupMemberRespVO vo = BeanUtils.toBean(member, ImGroupMemberRespVO.class);
  124 + MapUtils.findAndThen(userMap, member.getUserId(), user ->
110 125 vo.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
111   - hidePrivateFieldsIfNotSelf(vo, m.getUserId(), loginUserId);
  126 + hidePrivateFieldsIfNotSelf(vo, member.getUserId(), loginUserId);
112 127 return vo;
113   - }));
  128 + });
114 129 }
115 130  
116 131 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupRequestController.java
... ... @@ -19,9 +19,12 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
19 19 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
20 20 import io.swagger.v3.oas.annotations.Operation;
21 21 import io.swagger.v3.oas.annotations.Parameter;
  22 +import io.swagger.v3.oas.annotations.Parameters;
22 23 import io.swagger.v3.oas.annotations.tags.Tag;
23 24 import jakarta.annotation.Resource;
24 25 import jakarta.validation.Valid;
  26 +import jakarta.validation.constraints.Max;
  27 +import jakarta.validation.constraints.Min;
25 28 import jakarta.validation.constraints.NotNull;
26 29 import jakarta.validation.constraints.Size;
27 30 import org.springframework.validation.annotation.Validated;
... ... @@ -88,6 +91,22 @@ public class ImGroupRequestController {
88 91 return success(buildVOList(list));
89 92 }
90 93  
  94 + @GetMapping("/pull")
  95 + @Operation(summary = "增量拉取「我管理的群」下的加群申请(重连 / 离线补偿)")
  96 + @Parameters({
  97 + @Parameter(name = "lastUpdateTime", description = "上次拉取到的最新更新时间(毫秒时间戳);首次拉取不传"),
  98 + @Parameter(name = "lastId", description = "上次拉取到的最后一条记录 id;首次拉取不传"),
  99 + @Parameter(name = "limit", description = "单次拉取条数", required = true)
  100 + })
  101 + public CommonResult<List<ImGroupRequestRespVO>> pullMyGroupRequestList(
  102 + @RequestParam(value = "lastUpdateTime", required = false) Long lastUpdateTime,
  103 + @RequestParam(value = "lastId", required = false) Long lastId,
  104 + @RequestParam("limit") @Min(1) @Max(200) Integer limit) {
  105 + List<ImGroupRequestDO> list = groupRequestService.pullGroupRequestList(
  106 + getLoginUserId(), lastUpdateTime, lastId, limit);
  107 + return success(buildVOList(list));
  108 + }
  109 +
91 110 @GetMapping("/list-by-group")
92 111 @Operation(summary = "查询指定群下的全部加群申请(含已处理);仅群主 / 管理员可查")
93 112 @Parameter(name = "groupId", description = "群编号", required = true, example = "1024")
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupRespVO.java
... ... @@ -50,6 +50,12 @@ public class ImGroupRespVO {
50 50 @Schema(description = "当前登录用户在该群的成员状态:在群 / 已退群(历史退群群仍返回,供前端展示离线消息的群名 / 头像)")
51 51 private Integer joinStatus; // 参见 CommonStatusEnum 枚举
52 52  
  53 + @Schema(description = "当前登录用户对该群的备注")
  54 + private String groupRemark;
  55 +
  56 + @Schema(description = "当前登录用户是否免打扰")
  57 + private Boolean silent;
  58 +
53 59 @Schema(description = "群置顶消息列表,按 pin 顺序(最先置顶的在前);非该群有效成员时为空")
54 60 private List<ImGroupMessageRespVO> pinnedMessages;
55 61  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/request/ImGroupRequestRespVO.java
... ... @@ -42,6 +42,9 @@ public class ImGroupRequestRespVO {
42 42 @Schema(description = "申请创建时间")
43 43 private LocalDateTime createTime;
44 44  
  45 + @Schema(description = "申请更新时间;增量拉取游标")
  46 + private LocalDateTime updateTime;
  47 +
45 48 // ========== 下面是聚合字段,方便前端显示 ==========
46 49  
47 50 @Schema(description = "申请人 / 被邀请人昵称(实时聚合自 AdminUser)", example = "芋道")
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/channel/ImChannelManagerController.java
... ... @@ -75,7 +75,6 @@ public class ImChannelManagerController {
75 75 @GetMapping("/simple-list")
76 76 @Operation(summary = "获得启用的频道精简列表;前端表单选择频道时调用")
77 77 public CommonResult<List<ImChannelRespVO>> getSimpleChannelList() {
78   - // TODO DONE @AI:getChannelListByStatus 统一命名
79 78 List<ImChannelDO> list = channelService.getChannelListByStatus(CommonStatusEnum.ENABLE.getStatus());
80 79 return success(BeanUtils.toBean(list, ImChannelRespVO.class));
81 80 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/channel/ImChannelMessageRespVO.java
... ... @@ -29,7 +29,7 @@ public class ImChannelMessageRespVO {
29 29 private String materialCoverUrl;
30 30  
31 31 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "125")
32   - private Integer type; // 参见 ImMessageTypeEnum 枚举类
  32 + private Integer type; // 参见 ImContentTypeEnum 枚举类
33 33  
34 34 @Schema(description = "消息内容;payload JSON 快照")
35 35 private String content;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java
... ... @@ -22,7 +22,7 @@ public class ImGroupMessageManagerPageReqVO extends PageParam {
22 22 private Long senderId;
23 23  
24 24 @Schema(description = "消息类型", example = "1")
25   - private Integer type; // 参见 ImMessageTypeEnum 枚举类
  25 + private Integer type; // 参见 ImContentTypeEnum 枚举类
26 26  
27 27 @Schema(description = "消息内容", example = "你好")
28 28 private String content;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerRespVO.java
... ... @@ -29,7 +29,7 @@ public class ImGroupMessageManagerRespVO {
29 29 private String senderNickname;
30 30  
31 31 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
32   - private Integer type; // 参见 ImMessageTypeEnum 枚举类
  32 + private Integer type; // 参见 ImContentTypeEnum 枚举类
33 33  
34 34 @Schema(description = "消息内容(JSON 格式)", requiredMode = Schema.RequiredMode.REQUIRED)
35 35 private String content;
... ... @@ -43,7 +43,7 @@ public class ImGroupMessageManagerRespVO {
43 43 private List<String> atUserNicknames;
44 44  
45 45 @Schema(description = "回执状态", example = "0")
46   - private Integer receiptStatus; // 参见 ImGroupMessageReceiptStatusEnum 枚举类
  46 + private Integer receiptStatus; // 参见 ImMessageReceiptStatusEnum 枚举类
47 47  
48 48 @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
49 49 private LocalDateTime sendTime;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java
... ... @@ -22,7 +22,7 @@ public class ImPrivateMessageManagerPageReqVO extends PageParam {
22 22 private Long receiverId;
23 23  
24 24 @Schema(description = "消息类型", example = "1")
25   - private Integer type; // 参见 ImMessageTypeEnum 枚举类
  25 + private Integer type; // 参见 ImContentTypeEnum 枚举类
26 26  
27 27 @Schema(description = "消息内容", example = "你好")
28 28 private String content;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerRespVO.java
... ... @@ -28,7 +28,7 @@ public class ImPrivateMessageManagerRespVO {
28 28 private String receiverNickname;
29 29  
30 30 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
31   - private Integer type; // 参见 ImMessageTypeEnum 枚举类
  31 + private Integer type; // 参见 ImContentTypeEnum 枚举类
32 32  
33 33 @Schema(description = "消息内容(JSON 格式)", requiredMode = Schema.RequiredMode.REQUIRED)
34 34 private String content;
... ... @@ -36,6 +36,9 @@ public class ImPrivateMessageManagerRespVO {
36 36 @Schema(description = "消息状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
37 37 private Integer status; // 参见 ImMessageStatusEnum 枚举类
38 38  
  39 + @Schema(description = "回执状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
  40 + private Integer receiptStatus; // 参见 ImMessageReceiptStatusEnum 枚举类
  41 +
39 42 @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
40 43 private LocalDateTime sendTime;
41 44  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/ImStatisticsManagerController.java
... ... @@ -112,7 +112,7 @@ public class ImStatisticsManagerController {
112 112 }
113 113  
114 114 @GetMapping("/message-type-distribution")
115   - @Operation(summary = "获得消息类型分布(最近 30 天)")
  115 + @Operation(summary = "获得内容类型分布(最近 30 天)")
116 116 @PreAuthorize("@ss.hasPermission('im:manager:statistics:query')")
117 117 public CommonResult<List<ImStatisticsManagerMessageTypeRespVO>> getMessageTypeDistribution() {
118 118 LocalDateTime endTime = LocalDate.now().plusDays(1).atStartOfDay();
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/vo/ImStatisticsManagerMessageTypeRespVO.java
... ... @@ -3,12 +3,12 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.statistics.vo;
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
5 5  
6   -@Schema(description = "管理后台 - IM 数据看板消息类型分布项 Response VO")
  6 +@Schema(description = "管理后台 - IM 数据看板内容类型分布项 Response VO")
7 7 @Data
8 8 public class ImStatisticsManagerMessageTypeRespVO {
9 9  
10 10 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
11   - private Integer type; // 参见 ImMessageTypeEnum 枚举类
  11 + private Integer type; // 参见 ImContentTypeEnum 枚举类
12 12  
13 13 @Schema(description = "消息数", requiredMode = Schema.RequiredMode.REQUIRED, example = "8000")
14 14 private Long value;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImChannelMessageController.java
... ... @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 6 import cn.iocoder.yudao.module.im.controller.admin.message.vo.channel.ImChannelMessagePullRespVO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO;
8   -import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
  8 +import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
9 9 import cn.iocoder.yudao.module.im.service.message.ImChannelMessageService;
10 10 import io.swagger.v3.oas.annotations.Operation;
11 11 import io.swagger.v3.oas.annotations.Parameter;
... ... @@ -40,25 +40,25 @@ public class ImChannelMessageController {
40 40  
41 41 @GetMapping("/pull")
42 42 @Operation(summary = "拉取频道消息(离线增量);按 minId 游标分页")
43   - public CommonResult<List<ImChannelMessagePullRespVO>> pull(
  43 + public CommonResult<List<ImChannelMessagePullRespVO>> pullChannelMessageList(
44 44 @RequestParam(value = "minId", defaultValue = "0") @PositiveOrZero(message = "minId 不能小于 0") Long minId,
45 45 @RequestParam(value = "size", defaultValue = "100")
46 46 @Min(value = 1, message = "size 必须大于 0")
47 47 @Max(value = 200, message = "size 一次最多 200 条") Integer size) {
48 48 // 1. 拉取消息列表
49 49 Long userId = getLoginUserId();
50   - List<ImChannelMessageDO> list = channelMessageService.getMessageListForPull(userId, minId, size);
  50 + List<ImChannelMessageDO> list = channelMessageService.pullChannelMessageList(userId, minId, size);
51 51 if (CollUtil.isEmpty(list)) {
52 52 return success(Collections.emptyList());
53 53 }
54   - // 2. 按 Redis 已读游标补 status;device A 已读后 device B 拉到这条不再算入未读
  54 + // 2. 按已读游标补 receiptStatus(已读 DONE / 未读 PENDING)
55 55 Map<Long, Long> readMaxByChannel = channelMessageService.getChannelReadMaxMessageIdMap(
56 56 userId, convertSet(list, ImChannelMessageDO::getChannelId));
57 57 return success(BeanUtils.toBean(list, ImChannelMessagePullRespVO.class, vo -> {
58 58 Long readMax = readMaxByChannel.get(vo.getChannelId());
59   - vo.setStatus(readMax != null && readMax >= vo.getId()
60   - ? ImMessageStatusEnum.READ.getStatus()
61   - : ImMessageStatusEnum.UNREAD.getStatus());
  59 + vo.setReceiptStatus(readMax != null && readMax >= vo.getId()
  60 + ? ImMessageReceiptStatusEnum.DONE.getStatus()
  61 + : ImMessageReceiptStatusEnum.PENDING.getStatus());
62 62 }));
63 63 }
64 64  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImPrivateMessageController.java
... ... @@ -61,7 +61,7 @@ public class ImPrivateMessageController {
61 61  
62 62 @GetMapping("/max-read-message-id")
63 63 @Operation(summary = "查询对方已读到我发的最大消息 id",
64   - description = "用于多端 / 离线场景下的已读位置补齐:进入会话或断线重连后调用,结果用于翻转本地自发消息状态")
  64 + description = "用于多端 / 离线场景下的已读位置补齐:进入会话或断线重连后调用,据此把本地自发消息更新为已读")
65 65 @Parameter(name = "peerId", description = "对方用户编号", required = true, example = "2")
66 66 public CommonResult<Long> getMaxReadMessageId(@RequestParam("peerId") Long peerId) {
67 67 return success(privateMessageService.getMaxReadMessageId(getLoginUserId(), peerId));
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/channel/ImChannelMessagePullRespVO.java
... ... @@ -24,8 +24,8 @@ public class ImChannelMessagePullRespVO {
24 24 @Schema(description = "消息内容;payload JSON 快照", requiredMode = Schema.RequiredMode.REQUIRED)
25 25 private String content;
26 26  
27   - @Schema(description = "当前用户的已读态;按 Redis 游标计算填充", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
28   - private Integer status; // 参见 ImMessageStatusEnum 枚举类
  27 + @Schema(description = "当前用户回执 / 已读态;按 Redis 读位置计算(已读 DONE,未读 PENDING)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  28 + private Integer receiptStatus; // 参见 ImMessageReceiptStatusEnum 枚举类
29 29  
30 30 @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
31 31 private LocalDateTime sendTime;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/group/ImGroupMessageSendReqVO.java
1 1 package cn.iocoder.yudao.module.im.controller.admin.message.vo.group;
2 2  
3 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  4 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
5 5 import com.fasterxml.jackson.annotation.JsonIgnore;
6 6 import io.swagger.v3.oas.annotations.media.Schema;
7 7 import jakarta.validation.constraints.AssertTrue;
... ... @@ -28,7 +28,7 @@ public class ImGroupMessageSendReqVO {
28 28  
29 29 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
30 30 @NotNull(message = "消息类型不能为空")
31   - @InEnum(ImMessageTypeEnum.class)
  31 + @InEnum(ImContentTypeEnum.class)
32 32 private Integer type;
33 33  
34 34 @Schema(description = "消息内容,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"content\":\"你好\"}")
... ... @@ -47,7 +47,7 @@ public class ImGroupMessageSendReqVO {
47 47 @AssertTrue(message = "消息类型不允许")
48 48 @JsonIgnore
49 49 public boolean isTypeNormal() {
50   - return type == null || ImMessageTypeEnum.validate(type).isNormal();
  50 + return type == null || ImContentTypeEnum.validate(type).isNormal();
51 51 }
52 52  
53 53 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageRespVO.java
... ... @@ -31,7 +31,10 @@ public class ImPrivateMessageRespVO {
31 31 private String content;
32 32  
33 33 @Schema(description = "消息状态", example = "0")
34   - private Integer status;
  34 + private Integer status; // 参见 ImMessageStatusEnum 枚举类
  35 +
  36 + @Schema(description = "回执状态", example = "0")
  37 + private Integer receiptStatus; // 参见 ImMessageReceiptStatusEnum 枚举类
35 38  
36 39 @Schema(description = "发送时间")
37 40 private LocalDateTime sendTime;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageSendReqVO.java
1 1 package cn.iocoder.yudao.module.im.controller.admin.message.vo.privates;
2 2  
3 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  4 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
5 5 import com.fasterxml.jackson.annotation.JsonIgnore;
6 6 import io.swagger.v3.oas.annotations.media.Schema;
7 7 import jakarta.validation.constraints.AssertTrue;
... ... @@ -26,20 +26,23 @@ public class ImPrivateMessageSendReqVO {
26 26  
27 27 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
28 28 @NotNull(message = "消息类型不能为空")
29   - @InEnum(ImMessageTypeEnum.class)
  29 + @InEnum(ImContentTypeEnum.class)
30 30 private Integer type;
31 31  
32 32 @Schema(description = "消息内容,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"content\":\"你好\"}")
33 33 @NotEmpty(message = "消息内容不能为空")
34 34 private String content;
35 35  
  36 + @Schema(description = "是否需要回执", example = "false")
  37 + private Boolean receipt;
  38 +
36 39 /**
37 40 * 仅允许用户消息(normal)类型
38 41 */
39 42 @AssertTrue(message = "消息类型不允许")
40 43 @JsonIgnore
41 44 public boolean isTypeNormal() {
42   - return type == null || ImMessageTypeEnum.validate(type).isNormal();
  45 + return type == null || ImContentTypeEnum.validate(type).isNormal();
43 46 }
44 47  
45 48 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ImConversationReadDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.conversation;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelDO;
  5 +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
  6 +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO;
  7 +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
  8 +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
  9 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
  10 +import com.baomidou.mybatisplus.annotation.KeySequence;
  11 +import com.baomidou.mybatisplus.annotation.TableId;
  12 +import com.baomidou.mybatisplus.annotation.TableName;
  13 +import lombok.*;
  14 +
  15 +import java.time.LocalDateTime;
  16 +
  17 +/**
  18 + * IM 会话读位置 DO
  19 + * <p>
  20 + * 只表达「用户在某个会话的最大已读位置」,私聊 / 群聊 / 频道统一落这张表,是读位置的唯一权威。
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@TableName("im_conversation_read")
  25 +@KeySequence("im_conversation_read_seq")
  26 +@Data
  27 +@EqualsAndHashCode(callSuper = true)
  28 +@ToString(callSuper = true)
  29 +@Builder
  30 +@NoArgsConstructor
  31 +@AllArgsConstructor
  32 +public class ImConversationReadDO extends BaseDO {
  33 +
  34 + /**
  35 + * 编号
  36 + */
  37 + @TableId
  38 + private Long id;
  39 + /**
  40 + * 用户编号
  41 + *
  42 + * 关联 AdminUserDO 的 id 字段
  43 + */
  44 + private Long userId;
  45 + /**
  46 + * 会话类型
  47 + * <p>
  48 + * 枚举 {@link ImConversationTypeEnum}
  49 + */
  50 + private Integer conversationType;
  51 + /**
  52 + * 目标编号
  53 + * <p>
  54 + * 私聊关联 AdminUserDO 的 id;群聊关联 {@link ImGroupDO#getId()};频道关联 {@link ImChannelDO#getId()}
  55 + */
  56 + private Long targetId;
  57 + /**
  58 + * 最大已读消息编号
  59 + * <p>
  60 + * 关联 {@link ImPrivateMessageDO#getId()}、{@link ImGroupMessageDO#getId()}、{@link ImChannelMessageDO#getId()}
  61 + */
  62 + private Long messageId;
  63 + /**
  64 + * 最近已读时间
  65 + */
  66 + private LocalDateTime readTime;
  67 +
  68 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImChannelMessageDO.java
... ... @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 4 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
5 5 import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelDO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelMaterialDO;
7   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  7 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
8 8 import com.baomidou.mybatisplus.annotation.KeySequence;
9 9 import com.baomidou.mybatisplus.annotation.TableField;
10 10 import com.baomidou.mybatisplus.annotation.TableId;
... ... @@ -54,7 +54,7 @@ public class ImChannelMessageDO extends BaseDO {
54 54 /**
55 55 * 消息类型
56 56 * <p>
57   - * 枚举 {@link ImMessageTypeEnum}
  57 + * 枚举 {@link ImContentTypeEnum}
58 58 */
59 59 private Integer type;
60 60 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImGroupMessageDO.java
... ... @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.im.dal.dataobject.message;
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 4 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
5 5 import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
6   -import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum;
  6 +import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
7 7 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
8   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  8 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
9 9 import com.baomidou.mybatisplus.annotation.KeySequence;
10 10 import com.baomidou.mybatisplus.annotation.TableField;
11 11 import com.baomidou.mybatisplus.annotation.TableId;
... ... @@ -54,7 +54,7 @@ public class ImGroupMessageDO extends BaseDO {
54 54 /**
55 55 * 消息类型
56 56 * <p>
57   - * 枚举 {@link ImMessageTypeEnum}
  57 + * 枚举 {@link ImContentTypeEnum}
58 58 */
59 59 private Integer type;
60 60 /**
... ... @@ -67,8 +67,6 @@ public class ImGroupMessageDO extends BaseDO {
67 67 * 消息状态
68 68 * <p>
69 69 * 枚举 {@link ImMessageStatusEnum}
70   - *
71   - * 为什么没有 READ 状态?与单聊的差异:单聊用 UNREAD/READ 跟踪每条消息状态,群聊用 Redis 存储每个成员的已读位置(游标模型)
72 70 */
73 71 private Integer status;
74 72 /**
... ... @@ -94,7 +92,7 @@ public class ImGroupMessageDO extends BaseDO {
94 92 /**
95 93 * 回执状态
96 94 * <p>
97   - * 枚举 {@link ImGroupMessageReceiptStatusEnum}
  95 + * 枚举 {@link ImMessageReceiptStatusEnum}
98 96 */
99 97 private Integer receiptStatus;
100 98  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImPrivateMessageDO.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
4 5 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
5   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  6 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
6 7 import com.baomidou.mybatisplus.annotation.KeySequence;
7 8 import com.baomidou.mybatisplus.annotation.TableId;
8 9 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -49,7 +50,7 @@ public class ImPrivateMessageDO extends BaseDO {
49 50 /**
50 51 * 消息类型
51 52 * <p>
52   - * 枚举 {@link ImMessageTypeEnum}
  53 + * 枚举 {@link ImContentTypeEnum}
53 54 */
54 55 private Integer type;
55 56 /**
... ... @@ -65,6 +66,12 @@ public class ImPrivateMessageDO extends BaseDO {
65 66 */
66 67 private Integer status;
67 68 /**
  69 + * 回执状态
  70 + * <p>
  71 + * 枚举 {@link ImMessageReceiptStatusEnum}
  72 + */
  73 + private Integer receiptStatus;
  74 + /**
68 75 * 发送时间
69 76 */
70 77 private LocalDateTime sendTime;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/AudioMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/CardMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FaceMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FileMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/ImageMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/LocationMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MaterialMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MaterialMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4 import lombok.experimental.Accessors;
... ... @@ -6,7 +6,7 @@ import lombok.experimental.Accessors;
6 6 /**
7 7 * 频道素材消息 payload
8 8 * <p>
9   - * 对应 {@link cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum#MATERIAL}(type=125)。
  9 + * 对应 {@link cn.iocoder.yudao.module.im.enums.ImContentTypeEnum#MATERIAL}(type=125)。
10 10 * 客户端按本字段集渲染图文卡片;
11 11 * 富文本正文不在本 payload 中传递,点击详情时另调 /im/channel/material/get-content?id= 按需拉取。
12 12 */
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MergeMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MergeMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  3 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
4 4 import lombok.Data;
5 5  
6 6 import java.util.List;
... ... @@ -47,7 +47,7 @@ public class MergeMessage {
47 47 /**
48 48 * 消息类型
49 49 * <p>
50   - * 枚举 {@link ImMessageTypeEnum}
  50 + * 枚举 {@link ImContentTypeEnum}
51 51 */
52 52 private Integer type;
53 53 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/QuoteMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/QuoteMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  3 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
4 4 import lombok.Data;
5 5 import lombok.experimental.Accessors;
6 6  
... ... @@ -39,7 +39,7 @@ public class QuoteMessage {
39 39 /**
40 40 * 被引用消息类型
41 41 * <p>
42   - * 枚举 {@link ImMessageTypeEnum}
  42 + * 枚举 {@link ImContentTypeEnum}
43 43 */
44 44 private Integer type;
45 45 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/RecallMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/RecallMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4 import lombok.experimental.Accessors;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/TextMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/VideoMessage.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.message;
  1 +package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationReadMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.dal.mysql.conversation;
  2 +
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
  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.im.dal.dataobject.conversation.ImConversationReadDO;
  7 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.time.LocalDateTime;
  11 +import java.util.Collection;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * IM 会话读位置 Mapper
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +@Mapper
  20 +public interface ImConversationReadMapper extends BaseMapperX<ImConversationReadDO> {
  21 +
  22 + default ImConversationReadDO selectByUserIdAndConversation(Long userId, Integer conversationType, Long conversationId) {
  23 + return selectOne(new LambdaQueryWrapperX<ImConversationReadDO>()
  24 + .eq(ImConversationReadDO::getUserId, userId)
  25 + .eq(ImConversationReadDO::getConversationType, conversationType)
  26 + .eq(ImConversationReadDO::getTargetId, conversationId));
  27 + }
  28 +
  29 + default List<ImConversationReadDO> selectListByConversation(Integer conversationType, Long conversationId) {
  30 + return selectList(new LambdaQueryWrapperX<ImConversationReadDO>()
  31 + .eq(ImConversationReadDO::getConversationType, conversationType)
  32 + .eq(ImConversationReadDO::getTargetId, conversationId));
  33 + }
  34 +
  35 + default List<ImConversationReadDO> selectListByUserIdAndConversations(Long userId, Integer conversationType,
  36 + Collection<Long> conversationIds) {
  37 + return selectList(new LambdaQueryWrapperX<ImConversationReadDO>()
  38 + .eq(ImConversationReadDO::getUserId, userId)
  39 + .eq(ImConversationReadDO::getConversationType, conversationType)
  40 + .in(ImConversationReadDO::getTargetId, conversationIds));
  41 + }
  42 +
  43 + /**
  44 + * 增量拉取当前用户的会话读位置(按 update_time + id 正向游标)
  45 + *
  46 + * @param userId 当前用户编号
  47 + * @param lastUpdateTime 上次拉取到的更新时间;首次拉取传 null
  48 + * @param lastId 上次拉取到的记录编号;首次拉取传 null
  49 + * @param limit 拉取数量
  50 + * @return 会话读位置列表
  51 + */
  52 + default List<ImConversationReadDO> selectPullListByUserId(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  53 + LambdaQueryWrapperX<ImConversationReadDO> query = new LambdaQueryWrapperX<ImConversationReadDO>()
  54 + .eq(ImConversationReadDO::getUserId, userId);
  55 + if (lastUpdateTime != null && lastId != null) {
  56 + LocalDateTime lastTime = LocalDateTimeUtil.of(lastUpdateTime);
  57 + query.and(w -> w.gt(ImConversationReadDO::getUpdateTime, lastTime)
  58 + .or(n -> n.eq(ImConversationReadDO::getUpdateTime, lastTime).gt(ImConversationReadDO::getId, lastId)));
  59 + }
  60 + return selectList(query.orderByAsc(ImConversationReadDO::getUpdateTime).orderByAsc(ImConversationReadDO::getId)
  61 + .last("LIMIT " + limit));
  62 + }
  63 +
  64 + /**
  65 + * 单调递增更新读位置:仅当新位置更大时才更新
  66 + * <p>
  67 + * 通过 {@code read_message_id < messageId} 的 CAS 条件,保证乱序 / 并发上报时读位置不会回退。
  68 + *
  69 + * @param id 记录编号
  70 + * @param messageId 新的最大已读消息编号
  71 + * @param readTime 已读时间
  72 + * @return 影响行数;0 表示新位置不大于已有位置,未更新
  73 + */
  74 + default int updateReadMessageIdToLarger(Long id, Long messageId, LocalDateTime readTime) {
  75 + return update(null, Wrappers.<ImConversationReadDO>lambdaUpdate()
  76 + .set(ImConversationReadDO::getMessageId, messageId)
  77 + .set(ImConversationReadDO::getReadTime, readTime)
  78 + .set(ImConversationReadDO::getUpdateTime, readTime)
  79 + .eq(ImConversationReadDO::getId, id)
  80 + .lt(ImConversationReadDO::getMessageId, messageId));
  81 + }
  82 +
  83 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/friend/ImFriendMapper.java
1 1 package cn.iocoder.yudao.module.im.dal.mysql.friend;
2 2  
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
... ... @@ -31,6 +32,28 @@ public interface ImFriendMapper extends BaseMapperX&lt;ImFriendDO&gt; {
31 32 .eq(ImFriendDO::getUserId, userId)
32 33 .orderByDesc(ImFriendDO::getId));
33 34 }
  35 +
  36 + /**
  37 + * 增量拉取当前用户的好友关系(含已删除,按 update_time + id 正向游标)
  38 + *
  39 + * @param userId 当前用户编号
  40 + * @param lastUpdateTime 上次拉取到的更新时间;首次拉取传 null
  41 + * @param lastId 上次拉取到的记录编号;首次拉取传 null
  42 + * @param limit 拉取数量
  43 + * @return 好友关系列表
  44 + */
  45 + default List<ImFriendDO> selectPullListByUserId(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  46 + LambdaQueryWrapperX<ImFriendDO> query = new LambdaQueryWrapperX<ImFriendDO>()
  47 + .eq(ImFriendDO::getUserId, userId);
  48 + if (lastUpdateTime != null && lastId != null) {
  49 + LocalDateTime lastTime = LocalDateTimeUtil.of(lastUpdateTime);
  50 + query.and(w -> w.gt(ImFriendDO::getUpdateTime, lastTime)
  51 + .or(n -> n.eq(ImFriendDO::getUpdateTime, lastTime).gt(ImFriendDO::getId, lastId)));
  52 + }
  53 + return selectList(query.orderByAsc(ImFriendDO::getUpdateTime).orderByAsc(ImFriendDO::getId)
  54 + .last("LIMIT " + limit));
  55 + }
  56 +
34 57 default List<ImFriendDO> selectListByUserIdAndStatus(Long userId, Integer status) {
35 58 return selectList(new LambdaQueryWrapperX<ImFriendDO>()
36 59 .eq(ImFriendDO::getUserId, userId)
... ... @@ -68,12 +91,14 @@ public interface ImFriendMapper extends BaseMapperX&lt;ImFriendDO&gt; {
68 91  
69 92 @SuppressWarnings("UnusedReturnValue")
70 93 default int updateReAddFields(Long id, Integer status, LocalDateTime addTime,
  94 + LocalDateTime updateTime,
71 95 Boolean silent, Boolean pinned, Boolean blocked,
72 96 String displayName, Integer addSource) {
73 97 return update(null, Wrappers.<ImFriendDO>lambdaUpdate()
74 98 .eq(ImFriendDO::getId, id)
75 99 .set(ImFriendDO::getStatus, status)
76 100 .set(ImFriendDO::getAddTime, addTime)
  101 + .set(ImFriendDO::getUpdateTime, updateTime)
77 102 .set(ImFriendDO::getSilent, silent)
78 103 .set(ImFriendDO::getPinned, pinned)
79 104 .set(ImFriendDO::getBlocked, blocked)
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/friend/ImFriendRequestMapper.java
1 1 package cn.iocoder.yudao.module.im.dal.mysql.friend;
2 2  
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
... ... @@ -28,6 +29,12 @@ public interface ImFriendRequestMapper extends BaseMapperX&lt;ImFriendRequestDO&gt; {
28 29  
29 30 /**
30 31 * 拉取「我相关」的好友申请列表
  32 + *
  33 + * @param userId 当前用户编号
  34 + * @param maxRequestUpdateTime 起始更新时间;首次拉取传 null
  35 + * @param maxId 起始记录编号;首次拉取传 null
  36 + * @param limit 拉取数量
  37 + * @return 好友申请列表
31 38 */
32 39 default List<ImFriendRequestDO> selectMyList(Long userId, LocalDateTime maxRequestUpdateTime,
33 40 Long maxId, int limit) {
... ... @@ -45,6 +52,28 @@ public interface ImFriendRequestMapper extends BaseMapperX&lt;ImFriendRequestDO&gt; {
45 52 return selectList(wrapper);
46 53 }
47 54  
  55 + /**
  56 + * 增量拉取「我相关」的好友申请(双向 OR,按 update_time + id 正向游标)
  57 + *
  58 + * @param userId 当前用户编号
  59 + * @param lastUpdateTime 上次拉取到的更新时间;首次拉取传 null
  60 + * @param lastId 上次拉取到的记录编号;首次拉取传 null
  61 + * @param limit 拉取数量
  62 + * @return 好友申请列表
  63 + */
  64 + default List<ImFriendRequestDO> selectPullListByUserId(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  65 + LambdaQueryWrapperX<ImFriendRequestDO> query = new LambdaQueryWrapperX<>();
  66 + query.and(w -> w.eq(ImFriendRequestDO::getFromUserId, userId)
  67 + .or().eq(ImFriendRequestDO::getToUserId, userId));
  68 + if (lastUpdateTime != null && lastId != null) {
  69 + LocalDateTime lastTime = LocalDateTimeUtil.of(lastUpdateTime);
  70 + query.and(w -> w.gt(ImFriendRequestDO::getUpdateTime, lastTime)
  71 + .or(n -> n.eq(ImFriendRequestDO::getUpdateTime, lastTime).gt(ImFriendRequestDO::getId, lastId)));
  72 + }
  73 + return selectList(query.orderByAsc(ImFriendRequestDO::getUpdateTime).orderByAsc(ImFriendRequestDO::getId)
  74 + .last("LIMIT " + limit));
  75 + }
  76 +
48 77 default int updateByIdAndHandleResult(Long id, Integer handleResult, ImFriendRequestDO updateObj) {
49 78 return update(updateObj, new LambdaUpdateWrapper<ImFriendRequestDO>()
50 79 .eq(ImFriendRequestDO::getId, id).eq(ImFriendRequestDO::getHandleResult, handleResult));
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMemberMapper.java
1 1 package cn.iocoder.yudao.module.im.dal.mysql.group;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 6 import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
... ... @@ -59,20 +58,8 @@ public interface ImGroupMemberMapper extends BaseMapperX&lt;ImGroupMemberDO&gt; {
59 58 .eq(ImGroupMemberDO::getStatus, status));
60 59 }
61 60  
62   - /**
63   - * 查询用户已退群的成员记录
64   - * <p>
65   - * 当 {@code minQuitTime} 非空时额外按 {@code quitTime ≥ minQuitTime} 过滤。
66   - *
67   - * @param userId 用户编号
68   - * @param minQuitTime 最早退群时间(含),可空
69   - * @return 已退群成员记录列表
70   - */
71   - default List<ImGroupMemberDO> selectQuitListByUserId(Long userId, LocalDateTime minQuitTime) {
72   - return selectList(new LambdaQueryWrapperX<ImGroupMemberDO>()
73   - .eq(ImGroupMemberDO::getUserId, userId)
74   - .eq(ImGroupMemberDO::getStatus, CommonStatusEnum.DISABLE.getStatus())
75   - .geIfPresent(ImGroupMemberDO::getQuitTime, minQuitTime));
  61 + default List<ImGroupMemberDO> selectListByUserId(Long userId) {
  62 + return selectList(ImGroupMemberDO::getUserId, userId);
76 63 }
77 64  
78 65 @SuppressWarnings("UnusedReturnValue")
... ... @@ -143,7 +130,8 @@ public interface ImGroupMemberMapper extends BaseMapperX&lt;ImGroupMemberDO&gt; {
143 130 .set(ImGroupMemberDO::getAddSource, addSource)
144 131 .set(ImGroupMemberDO::getInviterUserId, inviterUserId)
145 132 .set(ImGroupMemberDO::getQuitTime, null)
146   - .set(ImGroupMemberDO::getMuteEndTime, null));
  133 + .set(ImGroupMemberDO::getMuteEndTime, null)
  134 + .set(ImGroupMemberDO::getUpdateTime, joinTime));
147 135 }
148 136  
149 137 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupRequestMapper.java
1 1 package cn.iocoder.yudao.module.im.dal.mysql.group;
2 2  
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
... ... @@ -43,6 +44,28 @@ public interface ImGroupRequestMapper extends BaseMapperX&lt;ImGroupRequestDO&gt; {
43 44 .orderByDesc(ImGroupRequestDO::getId));
44 45 }
45 46  
  47 + /**
  48 + * 增量拉取「我管理的群」下的加群申请(含已处理,按 update_time + id 正向游标)
  49 + *
  50 + * @param groupIds 群编号集合
  51 + * @param lastUpdateTime 上次拉取到的更新时间;首次拉取传 null
  52 + * @param lastId 上次拉取到的记录编号;首次拉取传 null
  53 + * @param limit 拉取数量
  54 + * @return 加群申请列表
  55 + */
  56 + default List<ImGroupRequestDO> selectPullListByGroupIds(Collection<Long> groupIds, Long lastUpdateTime,
  57 + Long lastId, Integer limit) {
  58 + LambdaQueryWrapperX<ImGroupRequestDO> query = new LambdaQueryWrapperX<ImGroupRequestDO>()
  59 + .in(ImGroupRequestDO::getGroupId, groupIds);
  60 + if (lastUpdateTime != null && lastId != null) {
  61 + LocalDateTime lastTime = LocalDateTimeUtil.of(lastUpdateTime);
  62 + query.and(w -> w.gt(ImGroupRequestDO::getUpdateTime, lastTime)
  63 + .or(n -> n.eq(ImGroupRequestDO::getUpdateTime, lastTime).gt(ImGroupRequestDO::getId, lastId)));
  64 + }
  65 + return selectList(query.orderByAsc(ImGroupRequestDO::getUpdateTime).orderByAsc(ImGroupRequestDO::getId)
  66 + .last("LIMIT " + limit));
  67 + }
  68 +
46 69 default int updateByIdAndHandleResult(Long id, Integer expectedHandleResult, ImGroupRequestDO updateObj) {
47 70 return update(updateObj, new LambdaUpdateWrapper<ImGroupRequestDO>()
48 71 .eq(ImGroupRequestDO::getId, id).eq(ImGroupRequestDO::getHandleResult, expectedHandleResult));
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImGroupMessageMapper.java
... ... @@ -4,13 +4,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
7 8 import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerPageReqVO;
8 9 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
9   -import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum;
  10 +import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
10 11 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
11 12 import org.apache.ibatis.annotations.Mapper;
12 13  
13 14 import java.time.LocalDateTime;
  15 +import java.util.Collection;
14 16 import java.util.List;
15 17  
16 18 /**
... ... @@ -22,48 +24,22 @@ import java.util.List;
22 24 public interface ImGroupMessageMapper extends BaseMapperX<ImGroupMessageDO> {
23 25  
24 26 /**
25   - * 根据 minId + 时间窗口增量拉取群聊消息(在群成员使用)
  27 + * 根据 minId + 时间窗口增量拉取群聊消息
26 28 *
27   - * @param groupIds 用户当前仍在群内的群编号列表
  29 + * @param userId 当前用户编号
  30 + * @param groupIds 候选群编号集合(当前在群 ∪ 窗口内退群),不能为空
28 31 * @param minId 最小消息 id(不含)
29 32 * @param minSendTime 最早发送时间(不含),限制离线消息时间窗口
30 33 * @param size 拉取数量
31 34 * @return 消息列表(按 id 升序)
32 35 */
33   - default List<ImGroupMessageDO> selectListByMinId(List<Long> groupIds, Long minId,
  36 + default List<ImGroupMessageDO> selectListByMinId(Long userId, Collection<Long> groupIds, Long minId,
34 37 LocalDateTime minSendTime, Integer size) {
35 38 QueryWrapperX<ImGroupMessageDO> wrapper = new QueryWrapperX<>();
36 39 wrapper.in("group_id", groupIds)
37 40 .gt("id", minId)
38 41 .gt("send_time", minSendTime)
39   - .orderByAsc("id");
40   - wrapper.limitN(size);
41   - return selectList(wrapper);
42   - }
43   -
44   - /**
45   - * 查询"退群前"的离线消息(退群成员使用)
46   - * <p>
47   - * 语义:用户已退出某群,但仍需把 {@code minId} 之后、{@code minSendTime} 之后、不晚于退群时间的消息补齐到本地,便于前端看到完整上下文。
48   - * <p>
49   - * 撤回消息(status=RECALL)保留返回,与在群成员的 {@link #selectListByMinId} 行为一致,由前端按撤回信号渲染「消息已撤回」气泡。
50   - *
51   - * @param groupId 群编号
52   - * @param minId 最小消息 id(不含)
53   - * @param minSendTime 最早发送时间(不含)
54   - * @param quitTime 退群时间(含),仅返回退群当时已存在的消息
55   - * @param size 拉取数量
56   - * @return 消息列表(按 id 升序)
57   - */
58   - default List<ImGroupMessageDO> selectListByGroupIdAndMinIdAndQuitTimeBefore(Long groupId, Long minId,
59   - LocalDateTime minSendTime,
60   - LocalDateTime quitTime,
61   - Integer size) {
62   - QueryWrapperX<ImGroupMessageDO> wrapper = new QueryWrapperX<>();
63   - wrapper.eq("group_id", groupId)
64   - .gt("id", minId)
65   - .gt("send_time", minSendTime)
66   - .le("send_time", quitTime)
  42 + .apply(MyBatisUtils.findInSet("receiver_user_ids"), userId)
67 43 .orderByAsc("id");
68 44 wrapper.limitN(size);
69 45 return selectList(wrapper);
... ... @@ -72,17 +48,17 @@ public interface ImGroupMessageMapper extends BaseMapperX&lt;ImGroupMessageDO&gt; {
72 48 /**
73 49 * 查询群聊历史消息(游标拉取)
74 50 *
75   - * @param groupId 群编号
76   - * @param maxId 起始消息 id(不含),为空则从最新开始
77   - * @param limit 拉取数量
78   - * @param joinTime 入群时间,仅返回入群之后的消息
  51 + * @param userId 当前用户编号
  52 + * @param groupId 群编号
  53 + * @param maxId 起始消息 id(不含),为空则从最新开始
  54 + * @param limit 拉取数量
79 55 * @return 消息列表(按 id 倒序)
80 56 */
81   - default List<ImGroupMessageDO> selectHistoryList(Long groupId, Long maxId, Integer limit, LocalDateTime joinTime) {
  57 + default List<ImGroupMessageDO> selectHistoryListByUser(Long userId, Long groupId, Long maxId, Integer limit) {
82 58 QueryWrapperX<ImGroupMessageDO> wrapper = new QueryWrapperX<>();
83 59 wrapper.eq("group_id", groupId)
84 60 .lt(maxId != null, "id", maxId)
85   - .ge(joinTime != null, "send_time", joinTime)
  61 + .apply(MyBatisUtils.findInSet("receiver_user_ids"), userId)
86 62 .orderByDesc("id");
87 63 wrapper.limitN(limit);
88 64 return selectList(wrapper);
... ... @@ -108,7 +84,7 @@ public interface ImGroupMessageMapper extends BaseMapperX&lt;ImGroupMessageDO&gt; {
108 84 default List<ImGroupMessageDO> selectListByGroupIdAndPendingReceipt(Long groupId, Long minId, Long maxId) {
109 85 return selectList(new LambdaQueryWrapperX<ImGroupMessageDO>()
110 86 .eq(ImGroupMessageDO::getGroupId, groupId)
111   - .eq(ImGroupMessageDO::getReceiptStatus, ImGroupMessageReceiptStatusEnum.PENDING.getStatus())
  87 + .eq(ImGroupMessageDO::getReceiptStatus, ImMessageReceiptStatusEnum.PENDING.getStatus())
112 88 .gt(minId != null, ImGroupMessageDO::getId, minId)
113 89 .le(ImGroupMessageDO::getId, maxId)
114 90 .ne(ImGroupMessageDO::getStatus, ImMessageStatusEnum.RECALL.getStatus()));
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImPrivateMessageMapper.java
... ... @@ -67,23 +67,13 @@ public interface ImPrivateMessageMapper extends BaseMapperX&lt;ImPrivateMessageDO&gt;
67 67 .eq(ImPrivateMessageDO::getClientMessageId, clientMessageId));
68 68 }
69 69  
70   - default Long selectMaxIdBySenderIdAndReceiverIdAndStatus(Long senderId, Long receiverId, Integer status) {
71   - ImPrivateMessageDO message = selectOne(new LambdaQueryWrapperX<ImPrivateMessageDO>()
72   - .eq(ImPrivateMessageDO::getSenderId, senderId)
73   - .eq(ImPrivateMessageDO::getReceiverId, receiverId)
74   - .eq(ImPrivateMessageDO::getStatus, status)
75   - .orderByDesc(ImPrivateMessageDO::getId)
76   - .last("LIMIT 1"));
77   - return message != null ? message.getId() : null;
78   - }
79   -
80   - default int updateBySenderIdAndReceiverIdAndIdLeAndStatus(Long senderId, Long receiverId, Long maxMessageId,
81   - Integer whereStatus, ImPrivateMessageDO updateObj) {
  70 + default int updateBySenderIdAndReceiverIdAndIdLeAndReceiptStatus(Long senderId, Long receiverId, Long maxMessageId,
  71 + Integer whereReceiptStatus, ImPrivateMessageDO updateObj) {
82 72 return update(updateObj, new LambdaQueryWrapperX<ImPrivateMessageDO>()
83 73 .eq(ImPrivateMessageDO::getSenderId, senderId)
84 74 .eq(ImPrivateMessageDO::getReceiverId, receiverId)
85 75 .le(ImPrivateMessageDO::getId, maxMessageId)
86   - .eq(ImPrivateMessageDO::getStatus, whereStatus));
  76 + .eq(ImPrivateMessageDO::getReceiptStatus, whereReceiptStatus));
87 77 }
88 78  
89 79 default PageResult<ImPrivateMessageDO> selectPage(ImPrivateMessageManagerPageReqVO reqVO) {
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java
... ... @@ -154,7 +154,7 @@ public interface ImStatisticsManagerMapper {
154 154 @Param("endTime") LocalDateTime endTime);
155 155  
156 156 /**
157   - * 区间内消息类型分布(私聊+群聊合并)
  157 + * 区间内内容类型分布(私聊+群聊合并)
158 158 *
159 159 * @return [{type: 0, count: 123}, ...]
160 160 */
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/redis/RedisKeyConstants.java
... ... @@ -9,20 +9,6 @@ package cn.iocoder.yudao.module.im.dal.redis;
9 9 public interface RedisKeyConstants {
10 10  
11 11 /**
12   - * 群消息已读位置
13   - * KEY 格式: im:group:message:read:{groupId}
14   - * VALUE 数据类型: Hash (field: userId, value: maxReadMessageId)
15   - */
16   - String GROUP_MESSAGE_READ = "im:group:message:read:%s";
17   -
18   - /**
19   - * 频道消息已读位置
20   - * KEY 格式: im:channel:message:read:{channelId}
21   - * VALUE 数据类型: Hash (field: userId, value: maxReadMessageId)
22   - */
23   - String CHANNEL_MESSAGE_READ = "im:channel:message:read:%s";
24   -
25   - /**
26 12 * 好友关系状态缓存(合并「是否好友」+「是否拉黑」两态)
27 13 * <p>
28 14 * KEY 格式:friend_state:{userId}_{friendUserId}
... ... @@ -44,7 +30,7 @@ public interface RedisKeyConstants {
44 30 * KEY 格式:group_member_ids:{groupId}
45 31 * VALUE 数据类型:List<Long>
46 32 * <p>
47   - * 说明:只缓存轻量的 userId 列表,适合"群消息推送目标"这类只关心 userId 的场景。
  33 + * 说明:只缓存轻量的 userId 列表,适合「群消息推送目标」这类只关心 userId 的场景
48 34 */
49 35 String GROUP_MEMBER_IDS = "group_member_ids";
50 36  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/redis/message/ImChannelMessageReadRedisDAO.java deleted
1   -package cn.iocoder.yudao.module.im.dal.redis.message;
2   -
3   -import cn.hutool.core.convert.Convert;
4   -import jakarta.annotation.Resource;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
6   -import org.springframework.stereotype.Repository;
7   -
8   -import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.CHANNEL_MESSAGE_READ;
9   -
10   -/**
11   - * IM 频道消息已读位置 Redis DAO
12   - *
13   - * @author 芋道源码
14   - */
15   -@Repository
16   -public class ImChannelMessageReadRedisDAO {
17   -
18   - @Resource
19   - private StringRedisTemplate stringRedisTemplate;
20   -
21   - /**
22   - * 更新用户在某频道的最大已读消息编号
23   - *
24   - * @param channelId 频道编号
25   - * @param userId 用户编号
26   - * @param maxMessageId 最大已读消息编号
27   - */
28   - public void updateReadMaxMessageId(Long channelId, Long userId, Long maxMessageId) {
29   - String key = formatKey(channelId);
30   - stringRedisTemplate.opsForHash().put(key, userId.toString(), maxMessageId.toString());
31   - }
32   -
33   - /**
34   - * 获取用户在某频道的最大已读消息编号
35   - *
36   - * @param channelId 频道编号
37   - * @param userId 用户编号
38   - * @return 最大已读消息编号;不存在则返回 null
39   - */
40   - public Long getReadMaxMessageId(Long channelId, Long userId) {
41   - String key = formatKey(channelId);
42   - Object val = stringRedisTemplate.opsForHash().get(key, userId.toString());
43   - return Convert.toLong(val);
44   - }
45   -
46   - private static String formatKey(Long channelId) {
47   - return String.format(CHANNEL_MESSAGE_READ, channelId);
48   - }
49   -
50   -}
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/redis/message/ImGroupMessageReadRedisDAO.java deleted
1   -package cn.iocoder.yudao.module.im.dal.redis.message;
2   -
3   -import cn.hutool.core.convert.Convert;
4   -import jakarta.annotation.Resource;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
6   -import org.springframework.stereotype.Repository;
7   -
8   -import java.util.Collection;
9   -import java.util.HashMap;
10   -import java.util.Map;
11   -
12   -import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.GROUP_MESSAGE_READ;
13   -
14   -/**
15   - * IM 群消息已读位置 Redis DAO
16   - *
17   - * @author 芋道源码
18   - */
19   -@Repository
20   -public class ImGroupMessageReadRedisDAO {
21   -
22   - @Resource
23   - private StringRedisTemplate stringRedisTemplate;
24   -
25   - /**
26   - * 更新用户在某群的最大已读消息编号
27   - *
28   - * @param groupId 群编号
29   - * @param userId 用户编号
30   - * @param maxMessageId 最大已读消息编号
31   - */
32   - public void updateReadMaxMessageId(Long groupId, Long userId, Long maxMessageId) {
33   - String key = formatKey(groupId);
34   - stringRedisTemplate.opsForHash().put(key, userId.toString(), maxMessageId.toString());
35   - }
36   -
37   - /**
38   - * 获取用户在某群的最大已读消息编号
39   - *
40   - * @param groupId 群编号
41   - * @param userId 用户编号
42   - * @return 最大已读消息编号,不存在则返回 null
43   - */
44   - public Long getReadMaxMessageId(Long groupId, Long userId) {
45   - String key = formatKey(groupId);
46   - Object val = stringRedisTemplate.opsForHash().get(key, userId.toString());
47   - return Convert.toLong(val);
48   - }
49   -
50   - /**
51   - * 获取某群所有用户的已读位置
52   - *
53   - * @param groupId 群编号
54   - * @return userId → maxReadMessageId 映射
55   - */
56   - public Map<Long, Long> getReadMaxMessageIdMap(Long groupId) {
57   - String key = formatKey(groupId);
58   - Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(key);
59   - // 转换为 Long → Long 的 Map
60   - Map<Long, Long> result = new HashMap<>(entries.size());
61   - entries.forEach((k, v) -> result.put(Long.parseLong(k.toString()), Long.parseLong(v.toString())));
62   - return result;
63   - }
64   -
65   - /**
66   - * 删除用户在某群的已读位置
67   - *
68   - * @param groupId 群编号
69   - * @param userId 用户编号
70   - */
71   - public void deleteReadMaxMessageId(Long groupId, Long userId) {
72   - String key = formatKey(groupId);
73   - stringRedisTemplate.opsForHash().delete(key, userId.toString());
74   - }
75   -
76   - /**
77   - * 批量删除用户在某群的已读位置
78   - *
79   - * @param groupId 群编号
80   - * @param userIds 用户编号集合
81   - */
82   - public void deleteReadMaxMessageIds(Long groupId, Collection<Long> userIds) {
83   - String key = formatKey(groupId);
84   - Object[] hashKeys = userIds.stream().map(String::valueOf).toArray();
85   - stringRedisTemplate.opsForHash().delete(key, hashKeys);
86   - }
87   -
88   - /**
89   - * 删除某群所有用户的已读位置(整个 Hash Key)
90   - *
91   - * @param groupId 群编号
92   - */
93   - public void deleteReadMaxMessageIdMap(Long groupId) {
94   - String key = formatKey(groupId);
95   - stringRedisTemplate.delete(key);
96   - }
97   -
98   - private static String formatKey(Long groupId) {
99   - return String.format(GROUP_MESSAGE_READ, groupId);
100   - }
101   -
102   -}
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java
1   -package cn.iocoder.yudao.module.im.enums.message;
  1 +package cn.iocoder.yudao.module.im.enums;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.lang.Assert;
... ... @@ -11,13 +11,13 @@ import java.util.Arrays;
11 11 import java.util.Set;
12 12  
13 13 /**
14   - * IM 消息类型枚举
  14 + * IM 内容类型枚举
15 15 *
16 16 * @author 芋道源码
17 17 */
18 18 @Getter
19 19 @RequiredArgsConstructor
20   -public enum ImMessageTypeEnum implements ArrayValuable<Integer> {
  20 +public enum ImContentTypeEnum implements ArrayValuable<Integer> {
21 21  
22 22 // ========== 用户聊天消息(101-105 直接复用 OpenIM 段位编号) ==========
23 23 /**
... ... @@ -128,10 +128,6 @@ public enum ImMessageTypeEnum implements ArrayValuable&lt;Integer&gt; {
128 128 RTC_CALL_END(1611, "通话结束", true, false),
129 129  
130 130 // ========== 好友通知(1201-1210 直接复用 OpenIM 段位编号) ==========
131   - // TODO @芋艿:FRIEND_REQUEST_* 与 GROUP_REQUEST_* 都是 persistent=false 的 SysMsg,离线 pull 拉不到,
132   - // 目前可能丢失「实时 toast 提醒」体验(业务状态不丢,前端上线 fetch{Friend,Group}RequestList 能补回来);
133   - // 未来思考下怎么优化:候选方案 1)改 persistent=true 入私聊消息流 + 让客户端按 type 自渲染;
134   - // 2)服务端补一个「未读通知拉取」接口给前端冷启动调用。
135 131 /**
136 132 * 对应 OpenIM:FriendApplicationApprovedNotification 1201
137 133 * 对应自己的类:FriendRequestApprovedNotification
... ... @@ -285,9 +281,9 @@ public enum ImMessageTypeEnum implements ArrayValuable&lt;Integer&gt; {
285 281 /**
286 282 * 对应 OpenIM:sdkws.GroupMemberInfoSetTips(GroupMemberInfoSetNotification 1516,窄化到 displayUserName)
287 283 * 对应自己的类:GroupMemberNicknameUpdateNotification
288   - * 场景:成员修改自己在群里的昵称,全员广播;前端按 displayUserName 局部更新对应 member
  284 + * 场景:成员修改自己在群里的昵称,在线成员同步对应 member
289 285 */
290   - GROUP_MEMBER_NICKNAME_UPDATE(1516, "成员昵称变更", true, false),
  286 + GROUP_MEMBER_NICKNAME_UPDATE(1516, "成员昵称变更", false, false),
291 287 /**
292 288 * 对应 OpenIM:GroupMemberSetToAdminNotification 1517
293 289 * 对应自己的类:GroupAdminAddNotification
... ... @@ -339,7 +335,7 @@ public enum ImMessageTypeEnum implements ArrayValuable&lt;Integer&gt; {
339 335 */
340 336 GROUP_BANNED(1533, "群封禁变更", true, false);
341 337  
342   - public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImMessageTypeEnum::getType).toArray(Integer[]::new);
  338 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImContentTypeEnum::getType).toArray(Integer[]::new);
343 339  
344 340 private static final Set<Integer> FRIEND_NOTIFICATION_TYPES = CollUtil.newHashSet(
345 341 FRIEND_REQUEST_APPROVED.type,
... ... @@ -396,8 +392,8 @@ public enum ImMessageTypeEnum implements ArrayValuable&lt;Integer&gt; {
396 392 * @param type 消息类型
397 393 * @return 枚举实例
398 394 */
399   - public static ImMessageTypeEnum validate(Integer type) {
400   - ImMessageTypeEnum result = ArrayUtil.firstMatch(item -> item.type.equals(type), values());
  395 + public static ImContentTypeEnum validate(Integer type) {
  396 + ImContentTypeEnum result = ArrayUtil.firstMatch(item -> item.type.equals(type), values());
401 397 Assert.notNull(result, "未注册的消息类型 type={}", type);
402 398 return result;
403 399 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImConversationTypeEnum.java
... ... @@ -16,6 +16,7 @@ import java.util.Objects;
16 16 @Getter
17 17 public enum ImConversationTypeEnum implements ArrayValuable<Integer> {
18 18  
  19 + NONE(0, "无会话"), // 无会话
19 20 PRIVATE(1, "私聊"), // 私聊
20 21 GROUP(2, "群聊"), // 群聊
21 22 CHANNEL(3, "频道"); // 频道 / 公众号
... ... @@ -36,6 +37,10 @@ public enum ImConversationTypeEnum implements ArrayValuable&lt;Integer&gt; {
36 37 return ARRAYS;
37 38 }
38 39  
  40 + public static boolean isNone(Integer type) {
  41 + return Objects.equals(NONE.type, type);
  42 + }
  43 +
39 44 public static boolean isPrivate(Integer type) {
40 45 return Objects.equals(PRIVATE.type, type);
41 46 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImGroupMessageReceiptStatusEnum.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageReceiptStatusEnum.java
... ... @@ -7,19 +7,19 @@ import lombok.Getter;
7 7 import java.util.Arrays;
8 8  
9 9 /**
10   - * IM 群消息回执状态枚举
  10 + * IM 消息回执状态枚举
11 11 *
12 12 * @author 芋道源码
13 13 */
14 14 @Getter
15 15 @AllArgsConstructor
16   -public enum ImGroupMessageReceiptStatusEnum implements ArrayValuable<Integer> {
  16 +public enum ImMessageReceiptStatusEnum implements ArrayValuable<Integer> {
17 17  
18 18 NO_RECEIPT(0, "不需要回执"),
19 19 PENDING(1, "待完成"),
20 20 DONE(2, "已完成");
21 21  
22   - public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImGroupMessageReceiptStatusEnum::getStatus).toArray(Integer[]::new);
  22 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImMessageReceiptStatusEnum::getStatus).toArray(Integer[]::new);
23 23  
24 24 /**
25 25 * 状态
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java
... ... @@ -8,9 +8,6 @@ import java.util.Arrays;
8 8  
9 9 /**
10 10 * IM 消息状态枚举
11   - * <p>
12   - * 私聊:SENDING(-1, 仅客户端) / UNREAD(0) / RECALL(2) / READ(3)
13   - * 群聊:SENDING(-1, 仅客户端) / UNREAD(0, 作为正常状态) / RECALL(2)
14 11 *
15 12 * @author 芋道源码
16 13 */
... ... @@ -19,9 +16,8 @@ import java.util.Arrays;
19 16 public enum ImMessageStatusEnum implements ArrayValuable<Integer> {
20 17  
21 18 SENDING(-1, "发送中"), // 仅客户端使用
22   - UNREAD(0, "未读"), // 私聊=未读,群聊=正常(初始状态)
23   - RECALL(2, "已撤回"),
24   - READ(3, "已读"); // 仅私聊使用;群聊已读通过 Redis 已读位置实现
  19 + NORMAL(0, "正常"), // 私聊 / 群聊的正常(初始)状态
  20 + RECALL(2, "已撤回");
25 21  
26 22 public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImMessageStatusEnum::getStatus).toArray(Integer[]::new);
27 23  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/rtc/ImRtcParticipantStatusEnum.java
... ... @@ -24,7 +24,6 @@ import java.util.Objects;
24 24 @Getter
25 25 public enum ImRtcParticipantStatusEnum implements ArrayValuable<Integer> {
26 26  
27   - // TODO @芋艿:hand up 要不要也搞下。
28 27 INVITING(10, "邀请中"), // 已发出 invite,等被叫响应
29 28 JOINED(20, "已加入"), // 已 connect 进 LiveKit 房间
30 29 REJECTED(30, "已拒绝"), // 接通前点拒接
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java
... ... @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.im.mq.consumer.friend;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO;
5   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  5 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  6 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
6 7 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
7 8 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
8   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
9   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendInfoUpdatedNotification;
  9 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendInfoUpdatedNotification;
10 10 import cn.iocoder.yudao.module.system.api.message.user.AdminUserProfileUpdateMessage;
11 11 import jakarta.annotation.Resource;
12 12 import lombok.extern.slf4j.Slf4j;
... ... @@ -52,8 +52,9 @@ public class AdminUserProfileUpdateConsumer {
52 52 try {
53 53 FriendInfoUpdatedNotification payload = (FriendInfoUpdatedNotification) new FriendInfoUpdatedNotification()
54 54 .setOperatorUserId(userId).setFriendUserId(userId);
55   - websocketService.sendPrivateMessageAsync(friend.getFriendUserId(), ImPrivateMessageDTO.ofFriendNotification(
56   - ImMessageTypeEnum.FRIEND_INFO_UPDATED.getType(), userId, friend.getFriendUserId(), payload));
  55 + websocketService.sendNotificationAsync(friend.getFriendUserId(),
  56 + ImConversationTypeEnum.NONE.getType(),
  57 + ImContentTypeEnum.FRIEND_INFO_UPDATED.getType(), payload);
57 58 successCount++;
58 59 } catch (Exception e) {
59 60 log.warn("[onMessage][userId({}) friendUserId({}) 推送失败]",
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationReadService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.conversation;
  2 +
  3 +import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationReadDO;
  4 +
  5 +import java.util.Collection;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +
  9 +/**
  10 + * IM 会话读位置 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface ImConversationReadService {
  15 +
  16 + /**
  17 + * 更新用户在某会话的最大已读位置(单调递增,乱序 / 并发上报不会回退)
  18 + *
  19 + * @param userId 用户编号
  20 + * @param conversationType 会话类型
  21 + * @param conversationId 会话编号
  22 + * @param readMessageId 已读到的最大消息编号
  23 + * @return 读位置是否前进;true 时调用方才需要下发已读 / 回执事件
  24 + */
  25 + boolean updateConversationReadPosition(Long userId, Integer conversationType, Long conversationId, Long readMessageId);
  26 +
  27 + /**
  28 + * 获取用户在某会话的最大已读位置
  29 + *
  30 + * @param userId 用户编号
  31 + * @param conversationType 会话类型
  32 + * @param conversationId 会话编号
  33 + * @return 最大已读消息编号;不存在则返回 null
  34 + */
  35 + Long getConversationReadMessageId(Long userId, Integer conversationType, Long conversationId);
  36 +
  37 + /**
  38 + * 获取某会话内所有用户的读位置(用于群回执人数聚合)
  39 + *
  40 + * @param conversationType 会话类型
  41 + * @param conversationId 会话编号
  42 + * @return userId → 最大已读消息编号
  43 + */
  44 + Map<Long, Long> getUserReadMessageIdMap(Integer conversationType, Long conversationId);
  45 +
  46 + /**
  47 + * 批量获取某用户在多个会话的读位置(用于频道批量读位置、重连后按活跃会话补偿)
  48 + *
  49 + * @param userId 用户编号
  50 + * @param conversationType 会话类型
  51 + * @param conversationIds 会话编号集合
  52 + * @return conversationId → 最大已读消息编号
  53 + */
  54 + Map<Long, Long> getConversationReadMessageIdMap(Long userId, Integer conversationType, Collection<Long> conversationIds);
  55 +
  56 + /**
  57 + * 增量拉取当前用户的会话读位置(重连 / 离线补偿:按 update_time + id 游标)
  58 + *
  59 + * @param userId 用户编号
  60 + * @param lastUpdateTime 上次拉取到的最新更新时间(毫秒时间戳);首次拉取传 null
  61 + * @param lastId 上次拉取到的最后一条记录 id;首次拉取传 null
  62 + * @param limit 单次拉取条数
  63 + * @return 会话读位置列表,按更新时间、id 正序
  64 + */
  65 + List<ImConversationReadDO> pullConversationReadList(Long userId, Long lastUpdateTime, Long lastId, Integer limit);
  66 +
  67 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationReadServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.conversation;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationReadDO;
  5 +import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationReadMapper;
  6 +import jakarta.annotation.Resource;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.dao.DuplicateKeyException;
  9 +import org.springframework.stereotype.Service;
  10 +
  11 +import java.time.LocalDateTime;
  12 +import java.util.Collection;
  13 +import java.util.Collections;
  14 +import java.util.List;
  15 +import java.util.Map;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  18 +
  19 +/**
  20 + * IM 会话读位置 Service 实现类
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@Service
  25 +@Slf4j
  26 +public class ImConversationReadServiceImpl implements ImConversationReadService {
  27 +
  28 + @Resource
  29 + private ImConversationReadMapper conversationReadMapper;
  30 +
  31 + @Override
  32 + public boolean updateConversationReadPosition(Long userId, Integer conversationType, Long conversationId, Long readMessageId) {
  33 + LocalDateTime now = LocalDateTime.now();
  34 + // 1. 不存在则插入;并发下唯一键冲突,降级为回查 + CAS 更新
  35 + ImConversationReadDO existing = conversationReadMapper.selectByUserIdAndConversation(
  36 + userId, conversationType, conversationId);
  37 + if (existing == null) {
  38 + try {
  39 + conversationReadMapper.insert(new ImConversationReadDO().setUserId(userId)
  40 + .setConversationType(conversationType).setTargetId(conversationId)
  41 + .setMessageId(readMessageId).setReadTime(now));
  42 + return true;
  43 + } catch (DuplicateKeyException e) {
  44 + log.warn("[updateConversationReadPosition][userId({}) type({}) conversationId({}) 并发插入冲突,回查更新]",
  45 + userId, conversationType, conversationId);
  46 + existing = conversationReadMapper.selectByUserIdAndConversation(userId, conversationType, conversationId);
  47 + }
  48 + }
  49 + if (existing == null) {
  50 + return false;
  51 + }
  52 +
  53 + // 2. CAS 单调更新:mapper 内 WHERE message_id < ? 保证乱序 / 并发不回退;影响行数 > 0 即读位置前进
  54 + return conversationReadMapper.updateReadMessageIdToLarger(existing.getId(), readMessageId, now) > 0;
  55 + }
  56 +
  57 + @Override
  58 + public Long getConversationReadMessageId(Long userId, Integer conversationType, Long conversationId) {
  59 + ImConversationReadDO read = conversationReadMapper.selectByUserIdAndConversation(
  60 + userId, conversationType, conversationId);
  61 + return read != null ? read.getMessageId() : null;
  62 + }
  63 +
  64 + @Override
  65 + public Map<Long, Long> getUserReadMessageIdMap(Integer conversationType, Long conversationId) {
  66 + return convertMap(conversationReadMapper.selectListByConversation(conversationType, conversationId),
  67 + ImConversationReadDO::getUserId, ImConversationReadDO::getMessageId);
  68 + }
  69 +
  70 + @Override
  71 + public Map<Long, Long> getConversationReadMessageIdMap(Long userId, Integer conversationType,
  72 + Collection<Long> conversationIds) {
  73 + if (CollUtil.isEmpty(conversationIds)) {
  74 + return Collections.emptyMap();
  75 + }
  76 + List<ImConversationReadDO> list = conversationReadMapper.selectListByUserIdAndConversations(
  77 + userId, conversationType, conversationIds);
  78 + return convertMap(list, ImConversationReadDO::getTargetId, ImConversationReadDO::getMessageId);
  79 + }
  80 +
  81 + @Override
  82 + public List<ImConversationReadDO> pullConversationReadList(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  83 + return conversationReadMapper.selectPullListByUserId(userId, lastUpdateTime, lastId, limit);
  84 + }
  85 +
  86 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestService.java
... ... @@ -51,6 +51,17 @@ public interface ImFriendRequestService {
51 51 List<ImFriendRequestDO> getMyFriendRequestList(Long userId, Long maxId, Integer limit);
52 52  
53 53 /**
  54 + * 增量拉取「我相关」的好友申请(重连 / 离线补偿:双向 OR,按 update_time + id 游标)
  55 + *
  56 + * @param userId 用户编号
  57 + * @param lastUpdateTime 上次拉取到的最新更新时间(毫秒时间戳);首次拉取传 null
  58 + * @param lastId 上次拉取到的最后一条记录 id;首次拉取传 null
  59 + * @param limit 单次拉取条数
  60 + * @return 申请记录列表,按更新时间、id 正序
  61 + */
  62 + List<ImFriendRequestDO> pullFriendRequestList(Long userId, Long lastUpdateTime, Long lastId, Integer limit);
  63 +
  64 + /**
54 65 * 按 id 单查申请记录;通用读接口,调用方自行做越权过滤
55 66 */
56 67 ImFriendRequestDO getFriendRequest(Long id);
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java
... ... @@ -14,13 +14,13 @@ import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendRequestDO;
14 14 import cn.iocoder.yudao.module.im.dal.mysql.friend.ImFriendRequestMapper;
15 15 import cn.iocoder.yudao.module.im.enums.friend.ImFriendRequestHandleResultEnum;
16 16 import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum;
17   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  17 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  18 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
18 19 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
19 20 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
20   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
21   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendRequestApprovedNotification;
22   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendRequestNotification;
23   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendRequestRejectedNotification;
  21 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestApprovedNotification;
  22 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestNotification;
  23 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestRejectedNotification;
24 24 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
25 25 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
26 26 import jakarta.annotation.Resource;
... ... @@ -105,8 +105,8 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService {
105 105 if (fromUser != null) {
106 106 payload.setFromNickname(fromUser.getNickname()).setFromAvatar(fromUser.getAvatar());
107 107 }
108   - websocketService.sendPrivateMessageAsync(toUserId, ImPrivateMessageDTO.ofFriendNotification(
109   - ImMessageTypeEnum.FRIEND_REQUEST_RECEIVED.getType(), fromUserId, toUserId, payload));
  108 + websocketService.sendNotificationAsync(toUserId, ImConversationTypeEnum.NONE.getType(),
  109 + ImContentTypeEnum.FRIEND_REQUEST_RECEIVED.getType(), payload);
110 110  
111 111 // 4. 全局自动通过开关:注册 afterCommit 回调,事务提交后再走同意流程
112 112 // 回调内 try/catch 兜底 —— afterCommit 异常会被 Spring 静默吞掉,否则同意失败时申请方永远等不到 APPROVED
... ... @@ -172,8 +172,6 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService {
172 172 public void agreeFriendRequest(Long userId, Long requestId) {
173 173 // 1.1 校验申请存在、未处理、操作人是接收方
174 174 ImFriendRequestDO request = validateRequestForHandle(userId, requestId);
175   - // 1.2 复验双方用户有效
176   - adminUserApi.validateUserList(ListUtil.of(request.getFromUserId(), request.getToUserId()));
177 175  
178 176 // 2. 乐观锁更新申请处理结果
179 177 ImFriendRequestDO updateObj = new ImFriendRequestDO()
... ... @@ -192,8 +190,8 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService {
192 190 FriendRequestApprovedNotification payload = (FriendRequestApprovedNotification)
193 191 new FriendRequestApprovedNotification().setRequestId(request.getId())
194 192 .setOperatorUserId(userId).setFriendUserId(userId);
195   - websocketService.sendPrivateMessageAsync(request.getFromUserId(), ImPrivateMessageDTO.ofFriendNotification(
196   - ImMessageTypeEnum.FRIEND_REQUEST_APPROVED.getType(), userId, request.getFromUserId(), payload));
  193 + websocketService.sendNotificationAsync(request.getFromUserId(), ImConversationTypeEnum.NONE.getType(),
  194 + ImContentTypeEnum.FRIEND_REQUEST_APPROVED.getType(), payload);
197 195 }
198 196  
199 197 @Override
... ... @@ -217,8 +215,8 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService {
217 215 new FriendRequestRejectedNotification().setRequestId(request.getId())
218 216 .setHandleContent(handleContent)
219 217 .setOperatorUserId(userId).setFriendUserId(userId);
220   - websocketService.sendPrivateMessageAsync(request.getFromUserId(), ImPrivateMessageDTO.ofFriendNotification(
221   - ImMessageTypeEnum.FRIEND_REQUEST_REJECTED.getType(), userId, request.getFromUserId(), payload));
  218 + websocketService.sendNotificationAsync(request.getFromUserId(), ImConversationTypeEnum.NONE.getType(),
  219 + ImContentTypeEnum.FRIEND_REQUEST_REJECTED.getType(), payload);
222 220 }
223 221  
224 222 @Override
... ... @@ -234,6 +232,11 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService {
234 232 }
235 233  
236 234 @Override
  235 + public List<ImFriendRequestDO> pullFriendRequestList(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  236 + return friendRequestMapper.selectPullListByUserId(userId, lastUpdateTime, lastId, limit);
  237 + }
  238 +
  239 + @Override
237 240 public ImFriendRequestDO getFriendRequest(Long id) {
238 241 return friendRequestMapper.selectById(id);
239 242 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java
... ... @@ -43,6 +43,11 @@ public interface ImFriendService {
43 43 List<ImFriendDO> getFriendList(Long userId);
44 44  
45 45 /**
  46 + * 增量拉取当前用户的好友关系(重连 / 离线补偿:含已删除,按 update_time + id 游标)
  47 + */
  48 + List<ImFriendDO> pullFriendList(Long userId, Long lastUpdateTime, Long lastId, Integer limit);
  49 +
  50 + /**
46 51 * 获得当前用户的有效好友列表(仅 ENABLE 状态)
47 52 */
48 53 List<ImFriendDO> getEnableFriendList(Long userId);
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java
... ... @@ -11,12 +11,12 @@ import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO;
11 11 import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendRequestDO;
12 12 import cn.iocoder.yudao.module.im.dal.mysql.friend.ImFriendMapper;
13 13 import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum;
14   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  14 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  15 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
15 16 import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService;
16 17 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO;
17 18 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
18   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
19   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.*;
  19 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.*;
20 20 import jakarta.annotation.Resource;
21 21 import lombok.extern.slf4j.Slf4j;
22 22 import org.springframework.cache.annotation.CacheEvict;
... ... @@ -99,6 +99,11 @@ public class ImFriendServiceImpl implements ImFriendService {
99 99 }
100 100  
101 101 @Override
  102 + public List<ImFriendDO> pullFriendList(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  103 + return friendMapper.selectPullListByUserId(userId, lastUpdateTime, lastId, limit);
  104 + }
  105 +
  106 + @Override
102 107 public List<ImFriendDO> getEnableFriendList(Long userId) {
103 108 return friendMapper.selectListByUserIdAndStatus(userId, CommonStatusEnum.ENABLE.getStatus());
104 109 }
... ... @@ -155,8 +160,8 @@ public class ImFriendServiceImpl implements ImFriendService {
155 160 FriendUpdateNotification payload = (FriendUpdateNotification) new FriendUpdateNotification()
156 161 .setDisplayName(reqVO.getDisplayName()).setSilent(reqVO.getSilent()).setPinned(reqVO.getPinned())
157 162 .setOperatorUserId(userId).setFriendUserId(reqVO.getFriendUserId());
158   - websocketService.sendPrivateMessageAsync(userId, ImPrivateMessageDTO.ofFriendNotification(
159   - ImMessageTypeEnum.FRIEND_UPDATE.getType(), userId, userId, payload));
  163 + websocketService.sendNotificationAsync(userId, ImConversationTypeEnum.NONE.getType(),
  164 + ImContentTypeEnum.FRIEND_UPDATE.getType(), payload);
160 165 }
161 166  
162 167 @Override
... ... @@ -178,7 +183,7 @@ public class ImFriendServiceImpl implements ImFriendService {
178 183 FriendAddNotification payload = (FriendAddNotification) new FriendAddNotification()
179 184 .setOperatorUserId(fromUserId).setFriendUserId(toUserId);
180 185 privateMessageService.sendPrivateMessage(fromUserId, new ImPrivateMessageSendDTO()
181   - .setReceiverId(toUserId).setType(ImMessageTypeEnum.FRIEND_ADD.getType()).setContent(payload));
  186 + .setReceiverId(toUserId).setType(ImContentTypeEnum.FRIEND_ADD.getType()).setContent(payload));
182 187 }
183 188  
184 189 @Override
... ... @@ -197,7 +202,7 @@ public class ImFriendServiceImpl implements ImFriendService {
197 202 FriendAddNotification payload = (FriendAddNotification) new FriendAddNotification()
198 203 .setOperatorUserId(friendUserId).setFriendUserId(friendUserId);
199 204 privateMessageService.sendPrivateMessage(userId, new ImPrivateMessageSendDTO()
200   - .setReceiverId(friendUserId).setType(ImMessageTypeEnum.FRIEND_ADD.getType())
  205 + .setReceiverId(friendUserId).setType(ImContentTypeEnum.FRIEND_ADD.getType())
201 206 .setContent(payload).setPersistent(false));
202 207 }
203 208  
... ... @@ -219,7 +224,7 @@ public class ImFriendServiceImpl implements ImFriendService {
219 224 FriendDeleteNotification payload = ((FriendDeleteNotification) new FriendDeleteNotification()
220 225 .setOperatorUserId(userId).setFriendUserId(friendUserId)).setClear(clear);
221 226 privateMessageService.sendPrivateMessage(userId, new ImPrivateMessageSendDTO()
222   - .setReceiverId(friendUserId).setType(ImMessageTypeEnum.FRIEND_DELETE.getType())
  227 + .setReceiverId(friendUserId).setType(ImContentTypeEnum.FRIEND_DELETE.getType())
223 228 .setContent(payload).setPersistent(false));
224 229 }
225 230  
... ... @@ -245,8 +250,8 @@ public class ImFriendServiceImpl implements ImFriendService {
245 250 // 3. 推 FRIEND_BLOCK 给 A 多端
246 251 FriendBlockNotification payload = (FriendBlockNotification) new FriendBlockNotification()
247 252 .setOperatorUserId(userId).setFriendUserId(friendUserId);
248   - websocketService.sendPrivateMessageAsync(userId, ImPrivateMessageDTO.ofFriendNotification(
249   - ImMessageTypeEnum.FRIEND_BLOCK.getType(), userId, userId, payload));
  253 + websocketService.sendNotificationAsync(userId, ImConversationTypeEnum.NONE.getType(),
  254 + ImContentTypeEnum.FRIEND_BLOCK.getType(), payload);
250 255 }
251 256  
252 257 @Override
... ... @@ -271,8 +276,8 @@ public class ImFriendServiceImpl implements ImFriendService {
271 276 // 3. 推 FRIEND_UNBLOCK 给 A 多端
272 277 FriendUnblockNotification payload = (FriendUnblockNotification) new FriendUnblockNotification()
273 278 .setOperatorUserId(userId).setFriendUserId(friendUserId);
274   - websocketService.sendPrivateMessageAsync(userId, ImPrivateMessageDTO.ofFriendNotification(
275   - ImMessageTypeEnum.FRIEND_UNBLOCK.getType(), userId, userId, payload));
  279 + websocketService.sendNotificationAsync(userId, ImConversationTypeEnum.NONE.getType(),
  280 + ImContentTypeEnum.FRIEND_UNBLOCK.getType(), payload);
276 281 }
277 282  
278 283 /**
... ... @@ -294,7 +299,8 @@ public class ImFriendServiceImpl implements ImFriendService {
294 299 }
295 300 // 情况二:复用 DISABLE 旧记录 → 恢复 ENABLE + 重置 silent / pinned / blocked,对齐"重新加好友"语义
296 301 if (exists != null) {
297   - friendMapper.updateReAddFields(exists.getId(), CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now(),
  302 + LocalDateTime now = LocalDateTime.now();
  303 + friendMapper.updateReAddFields(exists.getId(), CommonStatusEnum.ENABLE.getStatus(), now, now,
298 304 false, false, false, displayName, addSource);
299 305 return;
300 306 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java
... ... @@ -87,13 +87,12 @@ public interface ImGroupMemberService {
87 87 List<ImGroupMemberDO> getActiveGroupMemberListByUserId(Long userId);
88 88  
89 89 /**
90   - * 查询用户已退群的群成员记录(DISABLE 状态)
  90 + * 查询用户曾经加入的所有群成员记录(含已退群)
91 91 *
92   - * @param userId 用户编号,必传
93   - * @param minQuitTime 最早退群时间(含),可空
94   - * @return 已退群成员记录列表
  92 + * @param userId 用户编号
  93 + * @return 群成员记录列表
95 94 */
96   - List<ImGroupMemberDO> getQuitGroupMemberListByUserId(Long userId, LocalDateTime minQuitTime);
  95 + List<ImGroupMemberDO> getGroupMemberListByUserId(Long userId);
97 96  
98 97 /**
99 98 * 添加群成员(入群),角色默认 MEMBER
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java
... ... @@ -77,7 +77,6 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService {
77 77  
78 78 @Override
79 79 public List<ImGroupMemberDO> getGroupMemberListByOwnerAndAdmin(Long groupId) {
80   - // TODO DONE @AI:把条件往下传;这样减少加载数据量!
81 80 return groupMemberMapper.selectListByGroupIdAndStatusAndRoles(groupId, CommonStatusEnum.ENABLE.getStatus(),
82 81 ListUtil.of(ImGroupMemberRoleEnum.OWNER.getRole(), ImGroupMemberRoleEnum.ADMIN.getRole()));
83 82 }
... ... @@ -106,8 +105,8 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService {
106 105 }
107 106  
108 107 @Override
109   - public List<ImGroupMemberDO> getQuitGroupMemberListByUserId(Long userId, LocalDateTime minQuitTime) {
110   - return groupMemberMapper.selectQuitListByUserId(userId, minQuitTime);
  108 + public List<ImGroupMemberDO> getGroupMemberListByUserId(Long userId) {
  109 + return groupMemberMapper.selectListByUserId(userId);
111 110 }
112 111  
113 112 @Override
... ... @@ -259,7 +258,7 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService {
259 258 .setId(member.getId());
260 259 groupMemberMapper.updateById(updateObj);
261 260  
262   - // 3.1 displayUserName 是公开字段,单独走 GROUP_MEMBER_NICKNAME_UPDATE 广播给全员;空串视为「清空昵称」也要广播;与旧值相同跳过
  261 + // 3.1 displayUserName 是公开字段,单独走 GROUP_MEMBER_NICKNAME_UPDATE 在线同步给全员;空串视为「清空昵称」也要同步;与旧值相同跳过
263 262 if (updateReqVO.getDisplayUserName() != null
264 263 && ObjUtil.notEqual(updateReqVO.getDisplayUserName(), member.getDisplayUserName())) {
265 264 groupMessageService.sendGroupMessage(userId, ImGroupMessageSendDTO.ofGroupMemberNicknameUpdate(
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestService.java
... ... @@ -64,6 +64,19 @@ public interface ImGroupRequestService {
64 64 List<ImGroupRequestDO> getUnhandledRequestListByOwnerOrAdmin(Long userId);
65 65  
66 66 /**
  67 + * 增量拉取「我管理的群」下的加群申请(重连 / 离线补偿:含已处理,按 update_time + id 游标)
  68 + * <p>
  69 + * 作用域与 {@link #getUnhandledRequestListByOwnerOrAdmin} 一致:按 ImGroupMember.role 取我作为 OWNER / ADMIN 的群
  70 + *
  71 + * @param userId 当前用户编号
  72 + * @param lastUpdateTime 游标:上次拉取的最后一条更新时间戳(毫秒)
  73 + * @param lastId 游标:上次拉取的最后一条申请编号
  74 + * @param limit 单次拉取条数
  75 + * @return 申请记录列表
  76 + */
  77 + List<ImGroupRequestDO> pullGroupRequestList(Long userId, Long lastUpdateTime, Long lastId, Integer limit);
  78 +
  79 + /**
67 80 * 拉取指定群下的全部加群申请(含已处理);仅群主 / 管理员可查
68 81 * <p>
69 82 * 用于群「进群申请」子页:最新一条卡片化突出 + 历史申请按 id 倒序
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java
... ... @@ -13,15 +13,15 @@ import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupRequestMapper;
13 13 import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum;
14 14 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
15 15 import cn.iocoder.yudao.module.im.enums.group.ImGroupRequestHandleResultEnum;
16   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  16 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  17 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
17 18 import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService;
18 19 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
19 20 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
20   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
21   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.BaseGroupNotification;
22   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestApprovedNotification;
23   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestReceivedNotification;
24   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestRejectedNotification;
  21 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.BaseGroupNotification;
  22 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestApprovedNotification;
  23 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestReceivedNotification;
  24 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestRejectedNotification;
25 25 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
26 26 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
27 27 import jakarta.annotation.Resource;
... ... @@ -97,12 +97,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
97 97 // 3. 情况二:群开启了审批,创建或复用一条主动申请记录
98 98 ImGroupRequestDO request = createOrResetApplyRequest(groupId, userId, reqVO);
99 99  
100   - // 4. 1503 私聊定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像
  100 + // 4. 1503 定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像
101 101 AdminUserRespDTO applyUser = adminUserApi.getUser(userId);
102 102 GroupRequestReceivedNotification payload = buildRequestNotification(group, request, applyUser);
103 103 for (Long receiverUserId : getGroupMemberListByOwnerAndAdminUserIds(group)) {
104   - websocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofGroupNotification(
105   - ImMessageTypeEnum.GROUP_REQUEST_RECEIVED.getType(), userId, receiverUserId, payload));
  104 + websocketService.sendNotificationAsync(receiverUserId, ImConversationTypeEnum.NONE.getType(),
  105 + ImContentTypeEnum.GROUP_REQUEST_RECEIVED.getType(), payload);
106 106 }
107 107 return request;
108 108 }
... ... @@ -139,12 +139,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
139 139 groupMemberService.addGroupMember(request.getGroupId(), request.getUserId(),
140 140 ImGroupMemberRoleEnum.NORMAL.getRole(), request.getAddSource(), request.getInviterUserId());
141 141  
142   - // 5.1 1505 私聊推送给申请人 + 群主 + 全部管理员(每端单推)
  142 + // 5.1 1505 定向推送给申请人 + 群主 + 全部管理员(每端单推)
143 143 GroupRequestApprovedNotification payload = (GroupRequestApprovedNotification) new GroupRequestApprovedNotification()
144 144 .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId())
145 145 .setOperatorUserId(userId);
146 146 broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload,
147   - ImMessageTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId);
  147 + ImContentTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId);
148 148 // 5.2 群事件:主动申请 → 1510 自由进群;被邀请 → 1509 成员加入
149 149 if (request.getInviterUserId() == null) {
150 150 groupMessageService.sendGroupMessage(userId,
... ... @@ -174,12 +174,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
174 174 throw exception(GROUP_REQUEST_HANDLED);
175 175 }
176 176  
177   - // 3. 1506 私聊推送给申请人 + 群主 + 全部管理员
  177 + // 3. 1506 定向推送给申请人 + 群主 + 全部管理员
178 178 GroupRequestRejectedNotification payload = (GroupRequestRejectedNotification) new GroupRequestRejectedNotification()
179 179 .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId())
180 180 .setHandleContent(handleContent).setOperatorUserId(userId);
181 181 broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload,
182   - ImMessageTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId);
  182 + ImContentTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId);
183 183 }
184 184  
185 185 @Override
... ... @@ -201,8 +201,8 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
201 201 AdminUserRespDTO applyUser = userMap.get(request.getUserId());
202 202 GroupRequestReceivedNotification payload = buildRequestNotification(group, request, applyUser);
203 203 for (Long receiverUserId : ownerAndAdmins) {
204   - websocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofGroupNotification(
205   - ImMessageTypeEnum.GROUP_REQUEST_RECEIVED.getType(), inviterUserId, receiverUserId, payload));
  204 + websocketService.sendNotificationAsync(receiverUserId, ImConversationTypeEnum.NONE.getType(),
  205 + ImContentTypeEnum.GROUP_REQUEST_RECEIVED.getType(), payload);
206 206 }
207 207 }
208 208 }
... ... @@ -212,8 +212,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
212 212 // 1. 找出当前用户作为 OWNER / ADMIN 的所有群
213 213 List<ImGroupMemberDO> myMembers = groupMemberService.getActiveGroupMemberListByUserId(userId);
214 214 Set<Long> ownerOrAdminGroupIds = convertSet(myMembers,
215   - ImGroupMemberDO::getGroupId,
216   - m -> ImGroupMemberRoleEnum.isOwnerOrAdmin(m.getRole()));
  215 + ImGroupMemberDO::getGroupId, member -> ImGroupMemberRoleEnum.isOwnerOrAdmin(member.getRole()));
217 216 if (CollUtil.isEmpty(ownerOrAdminGroupIds)) {
218 217 return Collections.emptyList();
219 218 }
... ... @@ -223,6 +222,19 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
223 222 }
224 223  
225 224 @Override
  225 + public List<ImGroupRequestDO> pullGroupRequestList(Long userId, Long lastUpdateTime, Long lastId, Integer limit) {
  226 + // 1. 找出当前用户作为 OWNER / ADMIN 的所有群
  227 + List<ImGroupMemberDO> myMembers = groupMemberService.getActiveGroupMemberListByUserId(userId);
  228 + Set<Long> ownerOrAdminGroupIds = convertSet(myMembers,
  229 + ImGroupMemberDO::getGroupId, member -> ImGroupMemberRoleEnum.isOwnerOrAdmin(member.getRole()));
  230 + if (CollUtil.isEmpty(ownerOrAdminGroupIds)) {
  231 + return Collections.emptyList();
  232 + }
  233 + // 2. 按游标增量拉取这些群下的申请
  234 + return groupRequestMapper.selectPullListByGroupIds(ownerOrAdminGroupIds, lastUpdateTime, lastId, limit);
  235 + }
  236 +
  237 + @Override
226 238 public List<ImGroupRequestDO> getGroupRequestListByGroupId(Long userId, Long groupId) {
227 239 // 1. 校验群存在 + 当前用户是群主 / 管理员
228 240 groupService.validateGroupExists(groupId);
... ... @@ -383,7 +395,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
383 395 }
384 396  
385 397 /**
386   - * 1505 / 1506 受众:申请人 + 群主 + 全部管理员;每端单独推一帧,前端按 receiver 是否申请人区分文案
  398 + * 1505 / 1506 受众:申请人 + 群主 + 全部管理员
387 399 */
388 400 private void broadcastToOwnerAdminsAndApplicant(Long groupId, Long applicantUserId, BaseGroupNotification payload,
389 401 Integer messageType, Long operatorUserId) {
... ... @@ -394,8 +406,8 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
394 406 Set<Long> receivers = new LinkedHashSet<>(getGroupMemberListByOwnerAndAdminUserIds(group));
395 407 receivers.add(applicantUserId);
396 408 for (Long receiverUserId : receivers) {
397   - websocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofGroupNotification(
398   - messageType, operatorUserId, receiverUserId, payload));
  409 + websocketService.sendNotificationAsync(receiverUserId, ImConversationTypeEnum.NONE.getType(),
  410 + messageType, payload);
399 411 }
400 412 }
401 413  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
... ... @@ -30,7 +30,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper;
30 30 import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum;
31 31 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
32 32 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
33   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  33 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
34 34 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
35 35 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
36 36 import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService;
... ... @@ -149,7 +149,9 @@ public class ImGroupServiceImpl implements ImGroupService {
149 149 boolean nameChanged = StrUtil.isNotEmpty(updateReqVO.getName());
150 150 boolean noticeChanged = updateReqVO.getNotice() != null;
151 151 boolean avatarChanged = StrUtil.isNotEmpty(updateReqVO.getAvatar());
152   - if (nameChanged || noticeChanged || avatarChanged) {
  152 + boolean joinApprovalChanged = updateReqVO.getJoinApproval() != null
  153 + && ObjUtil.notEqual(group.getJoinApproval(), updateReqVO.getJoinApproval());
  154 + if (nameChanged || noticeChanged || avatarChanged || joinApprovalChanged) {
153 155 List<Long> memberUserIds = groupMemberService.getActiveGroupMemberUserIdsByGroupId(groupId);
154 156 if (nameChanged) {
155 157 groupMessageService.sendGroupMessage(userId, memberUserIds, ImGroupMessageSendDTO.ofGroupNameUpdate(
... ... @@ -161,7 +163,11 @@ public class ImGroupServiceImpl implements ImGroupService {
161 163 }
162 164 if (avatarChanged) {
163 165 groupMessageService.sendGroupMessage(userId, memberUserIds, ImGroupMessageSendDTO.ofGroupInfoUpdate(
164   - groupId, userId, group.getAvatar(), updateReqVO.getAvatar()));
  166 + groupId, userId, group.getAvatar(), updateReqVO.getAvatar(), null, null));
  167 + }
  168 + if (joinApprovalChanged) {
  169 + groupMessageService.sendGroupMessage(userId, memberUserIds, ImGroupMessageSendDTO.ofGroupInfoUpdate(
  170 + groupId, userId, null, null, group.getJoinApproval(), updateReqVO.getJoinApproval()));
165 171 }
166 172 }
167 173  
... ... @@ -193,8 +199,6 @@ public class ImGroupServiceImpl implements ImGroupService {
193 199 .setStatus(CommonStatusEnum.DISABLE.getStatus()).setDissolvedTime(LocalDateTime.now()));
194 200 // 2.2 移除全部群成员
195 201 groupMemberService.removeGroupMembersByGroupId(id);
196   - // 2.3 清理已读缓存
197   - groupMessageService.deleteReadMaxMessageIdMap(id);
198 202 }
199 203  
200 204 // ==================== 群成员的写操作 ====================
... ... @@ -267,10 +271,8 @@ public class ImGroupServiceImpl implements ImGroupService {
267 271 // 2. 先发广播,后移成员(见类 javadoc)
268 272 groupMessageService.sendGroupMessage(userId, ImGroupMessageSendDTO.ofGroupMemberQuit(groupId, userId));
269 273  
270   - // 3.1 移除群成员
  274 + // 3. 移除群成员
271 275 groupMemberService.removeGroupMember(groupId, userId);
272   - // 3.2 清理已读缓存
273   - groupMessageService.deleteReadMaxMessageId(groupId, userId);
274 276 }
275 277  
276 278 @Override
... ... @@ -307,10 +309,8 @@ public class ImGroupServiceImpl implements ImGroupService {
307 309 groupMessageService.sendGroupMessage(userId,
308 310 ImGroupMessageSendDTO.ofGroupMemberKick(groupId, userId, validTargetUserIds));
309 311  
310   - // 3.1 批量移除群成员
  312 + // 3. 批量移除群成员;不清理读位置(保留退群前历史已读,供离线补偿)
311 313 groupMemberService.removeGroupMembers(groupId, validTargetUserIds);
312   - // 3.2 批量清理已读缓存
313   - groupMessageService.deleteReadMaxMessageIds(groupId, validTargetUserIds);
314 314 }
315 315  
316 316 @Override
... ... @@ -442,7 +442,7 @@ public class ImGroupServiceImpl implements ImGroupService {
442 442 if (message == null || ObjUtil.notEqual(message.getGroupId(), groupId)) {
443 443 throw exception(MESSAGE_NOT_IN_GROUP);
444 444 }
445   - if (!ImMessageTypeEnum.validate(message.getType()).isNormal()
  445 + if (!ImContentTypeEnum.validate(message.getType()).isNormal()
446 446 || ImMessageStatusEnum.RECALL.getStatus().equals(message.getStatus())) {
447 447 throw exception(MESSAGE_NOT_IN_GROUP);
448 448 }
... ... @@ -601,11 +601,8 @@ public class ImGroupServiceImpl implements ImGroupService {
601 601  
602 602 @Override
603 603 public List<ImGroupDO> getMyGroupList(Long userId) {
604   - // 1.1 查用户所在的、仍有效的群成员记录(仅 ENABLE 状态)
605   - List<ImGroupMemberDO> members = groupMemberService.getActiveGroupMemberListByUserId(userId);
606   - // 1.2 再查最近 N 天(与群消息离线拉取窗口一致)内退群的成员记录(退群前可能有离线消息需要展示,一并返回作为前端缓存)
607   - LocalDateTime minQuitTime = LocalDateTime.now().minusDays(imProperties.getMessage().getGroupPullMaxDays());
608   - members.addAll(groupMemberService.getQuitGroupMemberListByUserId(userId, minQuitTime));
  604 + // 1. 查用户曾经加入的所有群(含退群,前端按需过滤);退群前的离线消息也要能展示
  605 + List<ImGroupMemberDO> members = groupMemberService.getGroupMemberListByUserId(userId);
609 606 if (CollUtil.isEmpty(members)) {
610 607 return Collections.emptyList();
611 608 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageService.java
... ... @@ -27,7 +27,7 @@ public interface ImChannelMessageService {
27 27 * @param size 返回条数
28 28 * @return 频道消息列表;按 id 升序
29 29 */
30   - List<ImChannelMessageDO> getMessageListForPull(Long userId, Long minId, Integer size);
  30 + List<ImChannelMessageDO> pullChannelMessageList(Long userId, Long minId, Integer size);
31 31  
32 32 /**
33 33 * 上报频道消息已读位置;同步推 READ 事件给自己多端
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageServiceImpl.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.im.service.message;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.util.ObjUtil;
5 6 import cn.hutool.extra.spring.SpringUtil;
6 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
... ... @@ -11,12 +12,14 @@ import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.channel.Im
11 12 import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelMaterialDO;
12 13 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO;
13 14 import cn.iocoder.yudao.module.im.dal.mysql.message.ImChannelMessageMapper;
14   -import cn.iocoder.yudao.module.im.dal.redis.message.ImChannelMessageReadRedisDAO;
15   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  15 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
  16 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
16 17 import cn.iocoder.yudao.module.im.service.channel.ImChannelMaterialService;
  18 +import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
17 19 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
18   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO;
19   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.MaterialMessage;
  20 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImChannelMessageNotification;
  21 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReadNotification;
  22 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.MaterialMessage;
20 23 import jakarta.annotation.Resource;
21 24 import org.springframework.scheduling.annotation.Async;
22 25 import org.springframework.stereotype.Service;
... ... @@ -25,7 +28,6 @@ import org.springframework.validation.annotation.Validated;
25 28  
26 29 import java.time.LocalDateTime;
27 30 import java.util.Collection;
28   -import java.util.HashMap;
29 31 import java.util.List;
30 32 import java.util.Map;
31 33  
... ... @@ -50,39 +52,41 @@ public class ImChannelMessageServiceImpl implements ImChannelMessageService {
50 52 private ImWebSocketService webSocketService;
51 53  
52 54 @Resource
53   - private ImChannelMessageReadRedisDAO channelMessageReadRedisDAO;
  55 + private ImConversationReadService conversationReadService;
54 56  
55 57 // ==================== 用户端 ====================
56 58  
57 59 @Override
58   - public List<ImChannelMessageDO> getMessageListForPull(Long userId, Long minId, Integer size) {
  60 + public List<ImChannelMessageDO> pullChannelMessageList(Long userId, Long minId, Integer size) {
59 61 return channelMessageMapper.selectListByUserAndMinId(userId, minId, size);
60 62 }
61 63  
62 64 @Override
63 65 public Map<Long, Long> getChannelReadMaxMessageIdMap(Long userId, Collection<Long> channelIds) {
64   - Map<Long, Long> result = new HashMap<>(channelIds.size());
65   - for (Long channelId : channelIds) {
66   - Long max = channelMessageReadRedisDAO.getReadMaxMessageId(channelId, userId);
67   - if (max != null) {
68   - result.put(channelId, max);
69   - }
70   - }
71   - return result;
  66 + return conversationReadService.getConversationReadMessageIdMap(
  67 + userId, ImConversationTypeEnum.CHANNEL.getType(), channelIds);
72 68 }
73 69  
74 70 @Override
75 71 public void readChannelMessages(Long userId, Long channelId, Long messageId) {
76 72 Assert.notNull(channelId, "频道编号不能为空");
77 73 Assert.notNull(messageId, "已读消息编号不能为空");
78   - // 1. 已读位置未前进,直接返回
79   - Long prevMaxMessageId = channelMessageReadRedisDAO.getReadMaxMessageId(channelId, userId);
80   - if (prevMaxMessageId != null && prevMaxMessageId >= messageId) {
  74 + // 1.1 校验消息真实存在且属于该频道,避免未来 / 伪造 messageId 污染读位置
  75 + ImChannelMessageDO message = channelMessageMapper.selectById(messageId);
  76 + if (message == null || ObjUtil.notEqual(message.getChannelId(), channelId)) {
  77 + return;
  78 + }
  79 + // 1.2 定向消息校验对当前用户可见(receiver_user_ids 为空表示全员可见)
  80 + if (CollUtil.isNotEmpty(message.getReceiverUserIds()) && !message.getReceiverUserIds().contains(userId)) {
81 81 return;
82 82 }
83 83  
84   - // 2. 更新 Redis 频道已读位置
85   - channelMessageReadRedisDAO.updateReadMaxMessageId(channelId, userId, messageId);
  84 + // 2. 更新频道已读位置;读位置未前进则不推
  85 + boolean advanced = conversationReadService.updateConversationReadPosition(
  86 + userId, ImConversationTypeEnum.CHANNEL.getType(), channelId, messageId);
  87 + if (!advanced) {
  88 + return;
  89 + }
86 90  
87 91 // 3. 异步推 READ 事件给自己多端同步
88 92 getSelf().readChannelMessageEvent(userId, channelId, messageId);
... ... @@ -93,7 +97,8 @@ public class ImChannelMessageServiceImpl implements ImChannelMessageService {
93 97 */
94 98 @Async
95 99 public void readChannelMessageEvent(Long userId, Long channelId, Long readId) {
96   - webSocketService.sendChannelMessageAsync(userId, ImChannelMessageDTO.ofRead(channelId, readId));
  100 + webSocketService.sendNotificationAsync(userId, ImConversationTypeEnum.CHANNEL.getType(),
  101 + ImContentTypeEnum.READ.getType(), ImMessageReadNotification.ofChannel(channelId, readId));
97 102 }
98 103  
99 104 private ImChannelMessageServiceImpl getSelf() {
... ... @@ -113,15 +118,16 @@ public class ImChannelMessageServiceImpl implements ImChannelMessageService {
113 118 String payloadJson = JsonUtils.toJsonString(payload);
114 119 // 2.2 落库 1 行 message;reqVO 同名字段(materialId / receiverUserIds)自动拷贝,剩余字段补 set
115 120 ImChannelMessageDO message = BeanUtils.toBean(reqVO, ImChannelMessageDO.class).setChannelId(material.getChannelId())
116   - .setType(ImMessageTypeEnum.MATERIAL.getType()).setContent(payloadJson).setSendTime(LocalDateTime.now());
  121 + .setType(ImContentTypeEnum.MATERIAL.getType()).setContent(payloadJson).setSendTime(LocalDateTime.now());
117 122 channelMessageMapper.insert(message);
118 123  
119 124 // 3. 异步推 WebSocket:指定用户走点对点;全员(receiverUserIds 为空)走广播
120   - ImChannelMessageDTO dto = ImChannelMessageDTO.ofSend(message);
  125 + ImChannelMessageNotification dto = ImChannelMessageNotification.ofSend(message);
121 126 if (CollUtil.isNotEmpty(reqVO.getReceiverUserIds())) {
122   - webSocketService.sendChannelMessageAsync(reqVO.getReceiverUserIds(), dto);
  127 + webSocketService.sendNotificationAsync(reqVO.getReceiverUserIds(), ImConversationTypeEnum.CHANNEL.getType(),
  128 + dto.getType(), dto);
123 129 } else {
124   - webSocketService.broadcastChannelMessageAsync(dto);
  130 + webSocketService.broadcastNotificationAsync(ImConversationTypeEnum.CHANNEL.getType(), dto.getType(), dto);
125 131 }
126 132 return message.getId();
127 133 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageService.java
... ... @@ -98,35 +98,6 @@ public interface ImGroupMessageService {
98 98 */
99 99 List<ImGroupMessageDO> getGroupMessageList(Long userId, ImGroupMessageListReqVO reqVO);
100 100  
101   - /**
102   - * 清理用户在某群的已读位置缓存
103   - * <p>
104   - * 用于成员退群场景
105   - *
106   - * @param groupId 群编号
107   - * @param userId 用户编号
108   - */
109   - void deleteReadMaxMessageId(Long groupId, Long userId);
110   -
111   - /**
112   - * 批量清理用户在某群的已读位置缓存
113   - * <p>
114   - * 用于批量踢出场景
115   - *
116   - * @param groupId 群编号
117   - * @param userIds 用户编号集合
118   - */
119   - void deleteReadMaxMessageIds(Long groupId, Collection<Long> userIds);
120   -
121   - /**
122   - * 清理某群所有用户的已读位置缓存
123   - * <p>
124   - * 用于群解散场景
125   - *
126   - * @param groupId 群编号
127   - */
128   - void deleteReadMaxMessageIdMap(Long groupId);
129   -
130 101 // ==================== 管理后台 ====================
131 102  
132 103 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
... ... @@ -6,7 +6,6 @@ import cn.hutool.core.util.BooleanUtil;
6 6 import cn.hutool.core.util.IdUtil;
7 7 import cn.hutool.core.util.ObjUtil;
8 8 import cn.hutool.extra.spring.SpringUtil;
9   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
10 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
11 10 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
12 11 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
... ... @@ -17,23 +16,27 @@ import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
17 16 import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
18 17 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
19 18 import cn.iocoder.yudao.module.im.dal.mysql.message.ImGroupMessageMapper;
20   -import cn.iocoder.yudao.module.im.dal.redis.message.ImGroupMessageReadRedisDAO;
  19 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
21 20 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
22   -import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum;
  21 +import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
23 22 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
24   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  23 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
25 24 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
  25 +import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
26 26 import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
27 27 import cn.iocoder.yudao.module.im.service.group.ImGroupService;
28 28 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
29 29 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
30 30 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
31   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
32   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage;
33   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage;
  31 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification;
  32 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReadNotification;
  33 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReceiptNotification;
  34 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage;
  35 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.RecallMessage;
34 36 import cn.iocoder.yudao.module.im.util.ImMessageUtils;
35 37 import jakarta.annotation.Resource;
36 38 import lombok.extern.slf4j.Slf4j;
  39 +import org.springframework.dao.DuplicateKeyException;
37 40 import org.springframework.scheduling.annotation.Async;
38 41 import org.springframework.stereotype.Service;
39 42 import org.springframework.transaction.annotation.Transactional;
... ... @@ -41,7 +44,6 @@ import org.springframework.validation.annotation.Validated;
41 44  
42 45 import java.time.LocalDateTime;
43 46 import java.util.*;
44   -import java.util.stream.Collectors;
45 47  
46 48 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
47 49 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
... ... @@ -57,17 +59,8 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
57 59 @Slf4j
58 60 public class ImGroupMessageServiceImpl implements ImGroupMessageService {
59 61  
60   - /**
61   - * 仅用于规避群消息 pull 的"假空页":
62   - * 首批消息可能因入群时间或定向接收过滤后变成空列表,但后续更大的 id 仍然存在可见消息。
63   - * 因此仅在过滤结果为空时,按本轮消息最大 id 向后再试几次。
64   - */
65   - private static final int PULL_GROUP_MESSAGE_EMPTY_RETRY_TIMES = 3;
66   -
67 62 @Resource
68 63 private ImGroupMessageMapper groupMessageMapper;
69   - @Resource
70   - private ImGroupMessageReadRedisDAO groupMessageReadRedisDAO;
71 64  
72 65 @Resource
73 66 private ImGroupService groupService;
... ... @@ -75,6 +68,8 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
75 68 private ImGroupMemberService groupMemberService;
76 69 @Resource
77 70 private ImSensitiveWordService sensitiveWordService;
  71 + @Resource
  72 + private ImConversationReadService conversationReadService;
78 73  
79 74 @Resource
80 75 private ImWebSocketService imWebSocketService;
... ... @@ -100,34 +95,44 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
100 95 // 1.4 禁言校验
101 96 validateMuteStatus(group, senderMember);
102 97 // 1.5 文本消息敏感词过滤
103   - if (ImMessageTypeEnum.TEXT.getType().equals(reqVO.getType())) {
  98 + if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) {
104 99 sensitiveWordService.validateText(reqVO.getContent());
105 100 }
106 101  
107   - // 2.1 引用 quote 消息规范化
108   - reqVO.setContent(normalizeQuoteContent(reqVO, senderMember));
109   - // 2.2 构建并保存消息
  102 + // 2.1 固化发送当时可见成员快照:用户发送均为全员广播;getReceiverUserIds 兜底纳入发送者,钉死发送者必可见
  103 + List<Long> memberUserIds = groupMemberService.getActiveGroupMemberUserIdsByGroupId(reqVO.getGroupId());
  104 + Set<Long> receiverUserIds = getReceiverUserIds(null, senderId, memberUserIds);
  105 + // 2.2 引用 quote 消息规范化(含可见性子集校验,防止定向消息内容被广播引用泄漏)
  106 + reqVO.setContent(normalizeQuoteContent(reqVO, senderMember, receiverUserIds));
  107 + // 2.3 构建并保存消息;唯一键冲突时回查已存在消息返回
110 108 ImGroupMessageDO message = BeanUtils.toBean(reqVO, ImGroupMessageDO.class, m -> m
111   - .setSenderId(senderId).setStatus(ImMessageStatusEnum.UNREAD.getStatus()).setSendTime(LocalDateTime.now())
  109 + .setSenderId(senderId).setStatus(ImMessageStatusEnum.NORMAL.getStatus()).setSendTime(LocalDateTime.now())
  110 + .setReceiverUserIds(new ArrayList<>(receiverUserIds))
112 111 .setReceiptStatus(resolveReceiptStatus(reqVO.getReceipt())));
113   - groupMessageMapper.insert(message);
  112 + try {
  113 + groupMessageMapper.insert(message);
  114 + } catch (DuplicateKeyException e) {
  115 + log.warn("[sendGroupMessage][senderId({}) clientMessageId({}) 并发插入冲突,回查返回]",
  116 + senderId, reqVO.getClientMessageId());
  117 + return groupMessageMapper.selectBySenderIdAndClientMessageId(senderId, reqVO.getClientMessageId());
  118 + }
114 119  
115   - // 3. WebSocket 异步推送(群内可见成员 + 发送方多端同步)
116   - List<Long> memberUserIds = groupMemberService.getActiveGroupMemberUserIdsByGroupId(message.getGroupId());
117   - Set<Long> targetUserIds = getVisibleUserIds(message.getReceiverUserIds(), senderId, memberUserIds);
118   - imWebSocketService.sendGroupMessageAsync(targetUserIds, ImGroupMessageDTO.ofSend(message));
  120 + // 3. WebSocket 异步推送(快照内可见成员 + 发送方多端同步)
  121 + ImGroupMessageNotification notification = ImGroupMessageNotification.ofSend(message);
  122 + imWebSocketService.sendNotificationAsync(receiverUserIds, ImConversationTypeEnum.GROUP.getType(),
  123 + notification.getType(), notification);
119 124 return message;
120 125 }
121 126  
122 127 @Override
123 128 public ImGroupMessageDO sendGroupMessage(Long senderId, ImGroupMessageSendDTO dto) {
124 129 List<Long> memberUserIds = groupMemberService.getActiveGroupMemberUserIdsByGroupId(dto.getGroupId());
125   - Set<Long> targetUserIds = getVisibleUserIds(dto.getReceiverUserIds(), senderId, memberUserIds);
126   - return sendGroupMessage(senderId, targetUserIds, dto);
  130 + Set<Long> receiverUserIds = getReceiverUserIds(dto.getReceiverUserIds(), senderId, memberUserIds);
  131 + return sendGroupMessage(senderId, receiverUserIds, dto);
127 132 }
128 133  
129 134 @Override
130   - public ImGroupMessageDO sendGroupMessage(Long senderId, Collection<Long> targetUserIds, ImGroupMessageSendDTO dto) {
  135 + public ImGroupMessageDO sendGroupMessage(Long senderId, Collection<Long> receiverUserIds, ImGroupMessageSendDTO dto) {
131 136 // 1.1 content 序列化:null / String 透传,POJO 走 JSON
132 137 Object payload = dto.getContent();
133 138 String contentString = payload == null || payload instanceof String
... ... @@ -137,16 +142,18 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
137 142 ImGroupMessageDO message = new ImGroupMessageDO().setClientMessageId(IdUtil.fastSimpleUUID())
138 143 .setSenderId(senderId).setGroupId(dto.getGroupId())
139 144 .setType(dto.getType()).setContent(contentString)
140   - .setStatus(ImMessageStatusEnum.UNREAD.getStatus()).setSendTime(LocalDateTime.now())
141   - .setAtUserIds(dto.getAtUserIds()).setReceiverUserIds(dto.getReceiverUserIds())
  145 + .setStatus(ImMessageStatusEnum.NORMAL.getStatus()).setSendTime(LocalDateTime.now())
  146 + .setAtUserIds(dto.getAtUserIds()).setReceiverUserIds(new ArrayList<>(receiverUserIds))
142 147 .setReceiptStatus(resolveReceiptStatus(dto.getReceipt()));
143 148 // 1.3 按 type.persistent 决定是否入库
144   - if (ImMessageTypeEnum.validate(dto.getType()).isPersistent()) {
  149 + if (ImContentTypeEnum.validate(dto.getType()).isPersistent()) {
145 150 groupMessageMapper.insert(message);
146 151 }
147 152  
148 153 // 2. WebSocket 异步推送
149   - imWebSocketService.sendGroupMessageAsync(targetUserIds, ImGroupMessageDTO.ofSend(message));
  154 + ImGroupMessageNotification notification = ImGroupMessageNotification.ofSend(message);
  155 + imWebSocketService.sendNotificationAsync(receiverUserIds, ImConversationTypeEnum.GROUP.getType(),
  156 + notification.getType(), notification);
150 157 return message;
151 158 }
152 159  
... ... @@ -180,7 +187,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
180 187  
181 188 // 3. 发送撤回事件
182 189 return sendGroupMessage(userId, new ImGroupMessageSendDTO().setGroupId(message.getGroupId())
183   - .setType(ImMessageTypeEnum.RECALL.getType())
  190 + .setType(ImContentTypeEnum.RECALL.getType())
184 191 .setReceiverUserIds(message.getReceiverUserIds())
185 192 .setContent(new RecallMessage().setMessageId(messageId)));
186 193 }
... ... @@ -195,155 +202,53 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
195 202 // 0. 拉取时间窗;超过窗口的老消息不再通过离线通道推送
196 203 LocalDateTime minSendTime = LocalDateTime.now().minusDays(imProperties.getMessage().getGroupPullMaxDays());
197 204  
198   - // 1.1 主查询:仅用"当前仍在群"的成员记录驱动;若首批消息过滤后为空,则允许内部重试
199   - List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByUserId(userId);
200   - Map<Long, ImGroupMemberDO> memberMap = convertMap(activeMembers, ImGroupMemberDO::getGroupId);
201   - List<ImGroupMessageDO> messages = new ArrayList<>();
202   - if (CollUtil.isNotEmpty(activeMembers)) {
203   - List<Long> groupIds = convertList(activeMembers, ImGroupMemberDO::getGroupId);
204   - messages.addAll(pullActiveGroupMessageList(userId, groupIds, minId, size, minSendTime, memberMap));
205   - }
206   - // 1.2 补齐"退群前"的消息:
207   - // - 继续基于用户原始 minId 单次查询,不能被主查询内部探测游标带着前进;
208   - // - 若 minId > 0 且能查到对应消息,则进一步把下限抬到该消息的 sendTime,避免把客户端已拥有的老消息再次推送。
209   - messages.addAll(pullQuitGroupMessageList(userId, minId, size, minSendTime, memberMap));
210   -
211   - // 2. 合并后统一过滤,得到当前用户可见的结果
212   - List<ImGroupMessageDO> result = filterGroupMessageList(messages, memberMap, userId, size);
213   -
214   - // 3. 按当前用户补齐:消息已读态(相对 Redis 已读游标)、本人发送的回执消息的已读人数
215   - appendMessageStatusAndReceipt(userId, result);
216   - log.info("[pullGroupMessageList][userId({}) minId({}) size({}) result({})]", userId, minId, size, result.size());
217   - return result;
218   - }
219   -
220   - /**
221   - * 拉取当前仍在群的主路径消息。
222   - *
223   - * 仅当首批消息过滤后仍无可见消息时,才按消息最大 id 继续向后探测,
224   - * 直到命中可见消息或确认该来源已耗尽。
225   - */
226   - private List<ImGroupMessageDO> pullActiveGroupMessageList(Long userId, List<Long> groupIds, Long minId,
227   - Integer size, LocalDateTime minSendTime,
228   - Map<Long, ImGroupMemberDO> memberMap) {
229   - // 1. 主查询内部探测游标:仅用于向后探测,不代表客户端真实已送达边界
230   - Long activeMinId = minId;
231   - for (int retryCount = 0; retryCount <= PULL_GROUP_MESSAGE_EMPTY_RETRY_TIMES; retryCount++) {
232   - // 2. 查询本轮消息;若已无更多消息,则当前主路径直接结束
233   - List<ImGroupMessageDO> messages = groupMessageMapper.selectListByMinId(groupIds, activeMinId,
234   - minSendTime, size);
235   - if (CollUtil.isEmpty(messages)) {
236   - return Collections.emptyList();
237   - }
238   - boolean hasVisibleMessage = CollUtil.anyMatch(messages,
239   - message -> isMessageVisible(message, memberMap.get(message.getGroupId()), userId));
240   - boolean sourceExhausted = messages.size() < size;
241   - // 3. 本轮已命中可见消息,或主查询来源已耗尽,直接返回这一轮消息
242   - if (hasVisibleMessage || sourceExhausted) {
243   - return messages;
244   - }
245   -
246   - // 4. 按本轮消息最大 id 推进内部游标,跳过这段不可见区间;若游标未前进则直接停止
247   - Long maxMessageId = getMaxValue(messages, ImGroupMessageDO::getId);
248   - if (maxMessageId == null || maxMessageId <= activeMinId) {
249   - return Collections.emptyList();
250   - }
251   - activeMinId = maxMessageId;
  205 + // 1. 候选群 = 用户曾经加入的所有群(含退群);可见性与时间窗都交给 SQL,退群群最多贡献 0 条
  206 + Set<Long> groupIds = convertSet(groupMemberService.getGroupMemberListByUserId(userId),
  207 + ImGroupMemberDO::getGroupId);
  208 + if (CollUtil.isEmpty(groupIds)) {
  209 + return Collections.emptyList();
252 210 }
253   - return Collections.emptyList();
254   - }
255 211  
256   - /**
257   - * 拉取已离开群路径的消息(退群前消息)
258   - */
259   - private List<ImGroupMessageDO> pullQuitGroupMessageList(Long userId, Long minId, Integer size,
260   - LocalDateTime minSendTime,
261   - Map<Long, ImGroupMemberDO> memberMap) {
262   - // 1. 退群补齐始终基于用户原始 minId 计算时间边界,避免被主查询内部重试游标误伤
263   - LocalDateTime minQuitTime = minSendTime;
264   - if (minId != null && minId > 0) {
265   - ImGroupMessageDO minMessage = groupMessageMapper.selectById(minId);
266   - if (minMessage != null && minMessage.getSendTime() != null
267   - && minMessage.getSendTime().isAfter(minSendTime)) {
268   - minQuitTime = minMessage.getSendTime();
269   - }
270   - }
271   - // 2. 查询用户离开的群记录;若原始 minId 对应消息仍在窗口内,则用它的发送时间抬升退群筛选下限
272   - List<ImGroupMessageDO> messages = new ArrayList<>();
273   - List<ImGroupMemberDO> quitMembers = groupMemberService.getQuitGroupMemberListByUserId(userId, minQuitTime);
274   - for (ImGroupMemberDO quitMember : quitMembers) {
275   - // 3. 按原始 minId + 退群时间补齐该群退群前消息,并把成员记录写回 memberMap 供统一可见性过滤使用
276   - List<ImGroupMessageDO> quitGroupMessages = groupMessageMapper.selectListByGroupIdAndMinIdAndQuitTimeBefore(
277   - quitMember.getGroupId(), minId, minSendTime, quitMember.getQuitTime(), size);
278   - if (CollUtil.isEmpty(quitGroupMessages)) {
279   - continue;
280   - }
281   - messages.addAll(quitGroupMessages);
282   - memberMap.put(quitMember.getGroupId(), quitMember);
283   - }
284   - return messages;
285   - }
  212 + // 2. 按 receiver_user_ids 快照过滤可见性,结果按 id 升序
  213 + List<ImGroupMessageDO> messages = groupMessageMapper.selectListByMinId(userId, groupIds, minId, minSendTime, size);
286 214  
287   - /**
288   - * 过滤一批原始群消息,得到当前用户可见的返回结果
289   - */
290   - private List<ImGroupMessageDO> filterGroupMessageList(List<ImGroupMessageDO> messages,
291   - Map<Long, ImGroupMemberDO> memberMap,
292   - Long userId, Integer size) {
293   - // 按可见性过滤(入群前不可见、定向消息排除),按 id 升序后仅取本页 size 条,
294   - // 避免「在群 + 退群前」多路合并时一次响应跨度过大、游标直接跳到全局最大 id 而漏拉中间消息
295   - return messages.stream()
296   - .filter(msg -> isMessageVisible(msg, memberMap.get(msg.getGroupId()), userId))
297   - .sorted(Comparator.comparing(ImGroupMessageDO::getId))
298   - .limit(size)
299   - .collect(Collectors.toList());
  215 + // 3. 补齐本人发送的回执消息的已读人数
  216 + appendMessageReceipt(userId, messages);
  217 + log.info("[pullGroupMessageList][userId({}) minId({}) size({}) result({})]", userId, minId, size, messages.size());
  218 + return messages;
300 219 }
301 220  
302 221 /**
303   - * 补全消息已读态和回执已读人数
304   - *
305   - * 1. 消息已读态(status):根据 Redis 已读游标判断 READ / UNREAD
306   - * 2. 回执已读人数(readCount):仅对本人发送的回执消息,计算可见成员中的已读人数
  222 + * 补全本人发送消息的回执已读人数(readCount)
  223 + * <p>
  224 + * 仅对本人发送、且需要回执(非 NO_RECEIPT)的消息,按 receiver_user_ids 快照 ∩ 当前有效成员 - 发送者 算已读人数
307 225 */
308   - @SuppressWarnings({"StatementWithEmptyBody", "DataFlowIssue"})
309   - private void appendMessageStatusAndReceipt(Long userId, List<ImGroupMessageDO> messages) {
  226 + @SuppressWarnings("DataFlowIssue")
  227 + private void appendMessageReceipt(Long userId, List<ImGroupMessageDO> messages) {
310 228 if (CollUtil.isEmpty(messages)) {
311 229 return;
312 230 }
313   - // 群已读关闭:不查 Redis 已读游标,status 保持 DB 原值(含撤回),readCount 不补齐
  231 + // 群已读关闭:不补 readCount
314 232 if (BooleanUtil.isFalse(imProperties.getMessage().isGroupReadEnabled())) {
315 233 return;
316 234 }
317   - Map<Long, Long> readMaxMessageIdsByGroup = new HashMap<>(); // 群 → 已读位置
318 235 Map<Long, Map<Long, Long>> readPositionsByGroup = new HashMap<>(); // 群 → (用户 → 已读位置)
319 236 Map<Long, List<ImGroupMemberDO>> membersByGroup = new HashMap<>(); // 群 → 全部成员列表
320 237 for (ImGroupMessageDO message : messages) {
321   - // 消息已读态(status):撤回 > 已读 > 未读
322   - Long groupId = message.getGroupId();
323   - long readMaxMessageId = readMaxMessageIdsByGroup.computeIfAbsent(groupId, gid -> {
324   - Long readMaxMsgId = groupMessageReadRedisDAO.getReadMaxMessageId(gid, userId);
325   - return readMaxMsgId != null ? readMaxMsgId : -1L;
326   - });
327   - if (ImMessageStatusEnum.RECALL.getStatus().equals(message.getStatus())) {
328   - // 保持撤回态
329   - } else if (readMaxMessageId >= message.getId()) {
330   - message.setStatus(ImMessageStatusEnum.READ.getStatus());
331   - } else {
332   - message.setStatus(ImMessageStatusEnum.UNREAD.getStatus());
333   - }
334   -
335   - // 回执消息的已读人数(readCount):仅补齐本人发送的,其他消息不处理(回执消息才关心已读人数,且只对发送者可见)
  238 + // 仅补本人发送、且需要回执(非 NO_RECEIPT)的消息
336 239 if (ObjUtil.notEqual(message.getSenderId(), userId)
337   - || ImGroupMessageReceiptStatusEnum.NO_RECEIPT.getStatus().equals(message.getReceiptStatus())) {
  240 + || ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus().equals(message.getReceiptStatus())) {
338 241 continue;
339 242 }
  243 + Long groupId = message.getGroupId();
340 244 Map<Long, Long> positions = readPositionsByGroup.computeIfAbsent(groupId,
341   - gid -> groupMessageReadRedisDAO.getReadMaxMessageIdMap(gid));
342   - List<ImGroupMemberDO> allMembers = membersByGroup.computeIfAbsent(groupId,
343   - groupMemberService::getGroupMemberListByGroupId);
344   - Set<Long> visibleUserIds = getVisibleUserIds(message, allMembers);
345   - visibleUserIds.remove(message.getSenderId());
346   - int readCount = getSumValue(visibleUserIds,
  245 + gid -> conversationReadService.getUserReadMessageIdMap(ImConversationTypeEnum.GROUP.getType(), gid));
  246 + // 应读分母取当前有效成员(剔除已退群),与异步回执刷新、前端已读弹层口径一致
  247 + List<ImGroupMemberDO> activeMembers = membersByGroup.computeIfAbsent(groupId,
  248 + groupMemberService::getActiveGroupMemberListByGroupId);
  249 + Set<Long> receiverUserIds = getReceiverUserIds(message, activeMembers);
  250 + receiverUserIds.remove(message.getSenderId());
  251 + int readCount = getSumValue(receiverUserIds,
347 252 uid -> positions.getOrDefault(uid, -1L) >= message.getId() ? 1 : null,
348 253 Integer::sum, 0);
349 254 message.setReadCount(readCount);
... ... @@ -357,25 +262,24 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
357 262 throw exception(MESSAGE_GROUP_READ_DISABLED);
358 263 }
359 264 Assert.notNull(messageId, "已读消息编号不能为空");
360   - // 1.1 获取群成员记录
361   - ImGroupMemberDO member = groupMemberService.getGroupMember(groupId, userId);
362   - // 1.2 校验消息属于当前群,且对当前用户可见
  265 + // 1. 校验消息属于当前群,且对当前用户可见(按快照)
363 266 ImGroupMessageDO message = groupMessageMapper.selectById(messageId);
364 267 if (message == null
365 268 || ObjUtil.notEqual(message.getGroupId(), groupId)
366   - || !isMessageVisible(message, member, userId)) {
  269 + || !isMessageReceived(message, userId)) {
367 270 throw exception(MESSAGE_NOT_IN_GROUP);
368 271 }
369 272  
370   - // 2. 已读位置未前进,直接返回
371   - Long prevMaxMessageId = groupMessageReadRedisDAO.getReadMaxMessageId(groupId, userId);
372   - if (prevMaxMessageId != null && prevMaxMessageId >= messageId) {
  273 + // 2. 取旧读位置(用于回执刷新区间),再更新群已读位置;读位置未前进则不推
  274 + Long prevMaxMessageId = conversationReadService.getConversationReadMessageId(
  275 + userId, ImConversationTypeEnum.GROUP.getType(), groupId);
  276 + boolean advanced = conversationReadService.updateConversationReadPosition(
  277 + userId, ImConversationTypeEnum.GROUP.getType(), groupId, messageId);
  278 + if (!advanced) {
373 279 return;
374 280 }
375   - // 3. 更新 Redis 群已读位置
376   - groupMessageReadRedisDAO.updateReadMaxMessageId(groupId, userId, messageId);
377 281  
378   - // 4. 异步发送 READ 事件 + 刷新范围内的群回执
  282 + // 3. 异步发送 READ 事件 + 刷新范围内的群回执
379 283 getSelf().readGroupMessageEvent(userId, groupId, prevMaxMessageId, messageId);
380 284 }
381 285  
... ... @@ -386,13 +290,13 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
386 290 throw exception(MESSAGE_GROUP_READ_DISABLED);
387 291 }
388 292 // 1.1 校验用户在群中(权限校验)
389   - ImGroupMemberDO operator = groupMemberService.validateMemberInGroup(groupId, userId);
  293 + groupMemberService.validateMemberInGroup(groupId, userId);
390 294 // 1.2 获取消息;并校验消息归属于该群、对调用者可见、调用者是发送方
391 295 ImGroupMessageDO message = groupMessageMapper.selectById(messageId);
392 296 if (message == null || ObjUtil.notEqual(message.getGroupId(), groupId)) {
393 297 return Collections.emptyList();
394 298 }
395   - if (!isMessageVisible(message, operator, userId)) {
  299 + if (!isMessageReceived(message, userId)) {
396 300 return Collections.emptyList();
397 301 }
398 302 // 1.3 仅消息发送方关心已读人数;非发送方查询直接返回空
... ... @@ -400,18 +304,19 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
400 304 return Collections.emptyList();
401 305 }
402 306  
403   - // 2. 获取所有成员和已读位置
404   - List<ImGroupMemberDO> allMembers = groupMemberService.getGroupMemberListByGroupId(groupId);
405   - Map<Long, Long> allPositions = groupMessageReadRedisDAO.getReadMaxMessageIdMap(groupId);
  307 + // 2. 获取当前有效成员和已读位置(剔除已退群,与回执分母口径一致)
  308 + List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByGroupId(groupId);
  309 + Map<Long, Long> allPositions = conversationReadService.getUserReadMessageIdMap(
  310 + ImConversationTypeEnum.GROUP.getType(), groupId);
406 311  
407 312 // 3. 计算该消息的可见成员集合(排除发送者自己)
408   - Set<Long> visibleUserIds = getVisibleUserIds(message, allMembers);
409   - visibleUserIds.remove(message.getSenderId());
  313 + Set<Long> receiverUserIds = getReceiverUserIds(message, activeMembers);
  314 + receiverUserIds.remove(message.getSenderId());
410 315  
411 316 // 4. 只返回在可见范围内且已读位置 >= messageId 的用户
412 317 List<Long> readUserIds = new ArrayList<>();
413 318 allPositions.forEach((uid, readMaxMessageId) -> {
414   - if (visibleUserIds.contains(uid) && readMaxMessageId >= messageId) {
  319 + if (receiverUserIds.contains(uid) && readMaxMessageId >= messageId) {
415 320 readUserIds.add(uid);
416 321 }
417 322 });
... ... @@ -420,15 +325,14 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
420 325  
421 326 @Override
422 327 public List<ImGroupMessageDO> getGroupMessageList(Long userId, ImGroupMessageListReqVO reqVO) {
423   - // 1. 校验用户在群中
424   - ImGroupMemberDO member = groupMemberService.validateMemberInGroup(reqVO.getGroupId(), userId);
425   -
426   - // 2. 查询历史消息(仅入群之后)
427   - List<ImGroupMessageDO> messages = groupMessageMapper.selectHistoryList(
428   - reqVO.getGroupId(), reqVO.getMaxId(), reqVO.getLimit(), member.getJoinTime());
  328 + // 1. 校验用户曾经在群(当前在群或已退群),与 pull 退群窗口口径一致;内容仍由 receiver_user_ids 快照过滤
  329 + if (groupMemberService.getGroupMember(reqVO.getGroupId(), userId) == null) {
  330 + throw exception(GROUP_MEMBER_NOT_IN_GROUP);
  331 + }
429 332  
430   - // 3. 过滤定向消息:仅保留当前用户可见的(receiverUserIds 为空 / 含当前用户 / 本人发送)
431   - return filterList(messages, message -> isMessageVisible(message, member, userId));
  333 + // 2. 查询历史消息:SQL 已按 receiver_user_ids 快照过滤当前用户可见
  334 + return groupMessageMapper.selectHistoryListByUser(
  335 + userId, reqVO.getGroupId(), reqVO.getMaxId(), reqVO.getLimit());
432 336 }
433 337  
434 338 // ========== 异步 WebSocket 推送 ==========
... ... @@ -445,8 +349,9 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
445 349 @SuppressWarnings("DataFlowIssue")
446 350 public void readGroupMessageEvent(Long userId, Long groupId, Long prevMaxMessageId, Long newMaxMessageId) {
447 351 // 1. 发送 READ 事件给自己的其他终端(多端同步)
448   - imWebSocketService.sendGroupMessageAsync(userId,
449   - ImGroupMessageDTO.ofRead(userId, groupId, newMaxMessageId));
  352 + imWebSocketService.sendNotificationAsync(userId, ImConversationTypeEnum.GROUP.getType(),
  353 + ImContentTypeEnum.READ.getType(),
  354 + ImMessageReadNotification.ofGroup(userId, groupId, newMaxMessageId));
450 355  
451 356 // 2. 刷新 (prevMaxMessageId, newMaxMessageId] 区间内的待回执消息
452 357 List<ImGroupMessageDO> pendingMessages = groupMessageMapper.selectListByGroupIdAndPendingReceipt(
... ... @@ -455,28 +360,30 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
455 360 return;
456 361 }
457 362 List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByGroupId(groupId);
458   - Map<Long, Long> allPositions = groupMessageReadRedisDAO.getReadMaxMessageIdMap(groupId);
  363 + Map<Long, Long> allPositions = conversationReadService.getUserReadMessageIdMap(
  364 + ImConversationTypeEnum.GROUP.getType(), groupId);
459 365 for (ImGroupMessageDO message : pendingMessages) {
460   - // 2.1.1 统计可见成员中的已读人数
461   - Set<Long> visibleUserIds = getVisibleUserIds(message, activeMembers);
462   - visibleUserIds.remove(message.getSenderId()); // 发送者自己不算已读
463   - if (CollUtil.isEmpty(visibleUserIds)) {
  366 + // 2.1.1 统计可见成员中的已读人数(应读分母 = 快照 ∩ 当前有效成员 - sender)
  367 + Set<Long> receiverUserIds = getReceiverUserIds(message, activeMembers);
  368 + receiverUserIds.remove(message.getSenderId()); // 发送者自己不算已读
  369 + if (CollUtil.isEmpty(receiverUserIds)) {
464 370 continue;
465 371 }
466   - int readCount = getSumValue(visibleUserIds,
  372 + int readCount = getSumValue(receiverUserIds,
467 373 uid -> allPositions.getOrDefault(uid, -1L) >= message.getId() ? 1 : null,
468 374 Integer::sum, 0);
469 375 // 2.1.2 全部已读 → 标记回执完成
470   - Integer newReceiptStatus = ImGroupMessageReceiptStatusEnum.PENDING.getStatus();
471   - if (readCount >= visibleUserIds.size()) {
472   - newReceiptStatus = ImGroupMessageReceiptStatusEnum.DONE.getStatus();
  376 + Integer newReceiptStatus = ImMessageReceiptStatusEnum.PENDING.getStatus();
  377 + if (readCount >= receiverUserIds.size()) {
  378 + newReceiptStatus = ImMessageReceiptStatusEnum.DONE.getStatus();
473 379 groupMessageMapper.updateById(new ImGroupMessageDO().setId(message.getId())
474 380 .setReceiptStatus(newReceiptStatus));
475 381 }
476 382  
477 383 // 2.2 发送 RECEIPT 事件给消息发送方(只有 ta 关心已读进度)
478   - imWebSocketService.sendGroupMessageAsync(message.getSenderId(),
479   - ImGroupMessageDTO.ofReceipt(message.getId(), groupId, readCount, newReceiptStatus));
  384 + imWebSocketService.sendNotificationAsync(message.getSenderId(), ImConversationTypeEnum.GROUP.getType(),
  385 + ImContentTypeEnum.RECEIPT.getType(),
  386 + ImMessageReceiptNotification.ofGroup(message.getId(), groupId, readCount, newReceiptStatus));
480 387 }
481 388 }
482 389  
... ... @@ -487,9 +394,11 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
487 394 *
488 395 * @param reqVO 发送请求
489 396 * @param senderMember 发送人成员
  397 + * @param newAudience 新消息可见成员集合(发送当时快照)
490 398 * @return 规范化后的 content
491 399 */
492   - private String normalizeQuoteContent(ImGroupMessageSendReqVO reqVO, ImGroupMemberDO senderMember) {
  400 + private String normalizeQuoteContent(ImGroupMessageSendReqVO reqVO, ImGroupMemberDO senderMember,
  401 + Set<Long> newAudience) {
493 402 // 解析客户端 content 里的 quote.messageId
494 403 Long quoteMessageId = ImMessageUtils.parseQuoteMessageId(reqVO.getContent());
495 404  
... ... @@ -508,12 +417,13 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
508 417 if (ObjUtil.notEqual(original.getGroupId(), reqVO.getGroupId())) {
509 418 throw exception(MESSAGE_QUOTE_INVALID);
510 419 }
511   - // 拒绝定向消息(仅发送人可见的内容若被全员广播 quote.content,会泄漏给原本看不到的成员)
512   - if (CollUtil.isNotEmpty(original.getReceiverUserIds())) {
  420 + // 校验对发送人可见(按快照)
  421 + if (!isMessageReceived(original, senderMember.getUserId())) {
513 422 throw exception(MESSAGE_QUOTE_INVALID);
514 423 }
515   - // 校验对发送人可见(入群时间 / 退群时间)
516   - if (!isMessageVisible(original, senderMember, senderMember.getUserId())) {
  424 + // 防泄漏:新消息可见集合必须是被引用消息可见集合的子集,否则禁止引用;
  425 + // 否则只对部分成员可见的定向消息内容,会随广播引用泄漏给原本看不到的成员
  426 + if (!new HashSet<>(original.getReceiverUserIds()).containsAll(newAudience)) {
517 427 throw exception(MESSAGE_QUOTE_INVALID);
518 428 }
519 429 // 构建 quote 对象并注入 content
... ... @@ -537,87 +447,48 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
537 447 }
538 448  
539 449 /**
540   - * 判断一条群消息对某个群成员是否可见
  450 + * 判断一条群消息是否被某个用户接收到
  451 + * <p>
  452 + * 接收范围以发送当时固化的 receiver_user_ids 快照为准;发送者也在快照内。
541 453 *
542   - * @param msg 消息
543   - * @param member 群成员
544   - * @param userId 当前用户编号(用于定向消息过滤)
545   - * @return 是否可见
  454 + * @param message 消息
  455 + * @param userId 当前用户编号
  456 + * @return 是否接收到
546 457 */
547   - private boolean isMessageVisible(ImGroupMessageDO msg, ImGroupMemberDO member, Long userId) {
548   - if (member == null) {
549   - return false;
550   - }
551   - // 1. 入群时间晚于消息发送时间 → 不可见
552   - if (member.getJoinTime() != null && msg.getSendTime().isBefore(member.getJoinTime())) {
553   - return false;
554   - }
555   - // 2. 已退群且退群时间早于消息发送时间 → 不可见
556   - if (CommonStatusEnum.DISABLE.getStatus().equals(member.getStatus())
557   - && member.getQuitTime() != null && msg.getSendTime().isAfter(member.getQuitTime())) {
558   - return false;
559   - }
560   - // 3.1 无定向接收列表 → 全员可见
561   - if (CollUtil.isEmpty(msg.getReceiverUserIds())) {
562   - return true;
563   - }
564   - // 3.2 当前用户在定向列表中,或本人即发送者 → 可见
565   - return msg.getReceiverUserIds().contains(userId)
566   - || ObjUtil.equal(msg.getSenderId(), userId);
  458 + @SuppressWarnings("BooleanMethodIsAlwaysInverted")
  459 + private boolean isMessageReceived(ImGroupMessageDO message, Long userId) {
  460 + return CollUtil.contains(message.getReceiverUserIds(), userId);
567 461 }
568 462  
569 463 /**
570   - * 计算一条群消息的可见成员集合(含发送者)
  464 + * 计算一条群消息的可见成员集合(快照与传入成员的交集,含发送者)
571 465 */
572   - private Set<Long> getVisibleUserIds(ImGroupMessageDO message, List<ImGroupMemberDO> members) {
573   - return convertSet(members, ImGroupMemberDO::getUserId,
574   - member -> isMessageVisible(message, member, member.getUserId()));
  466 + private Set<Long> getReceiverUserIds(ImGroupMessageDO message, List<ImGroupMemberDO> members) {
  467 + if (CollUtil.isEmpty(message.getReceiverUserIds())) {
  468 + return new HashSet<>();
  469 + }
  470 + Set<Long> snapshot = new HashSet<>(message.getReceiverUserIds());
  471 + return convertSet(members, ImGroupMemberDO::getUserId, member -> snapshot.contains(member.getUserId()));
575 472 }
576 473  
577 474 /**
578   - * 基于群成员 userId 列表,过滤出一条新消息的可见成员集合(含发送者)。
  475 + * 基于群成员 userId 列表,计算一条新消息的可见成员快照(含发送者)。
579 476 * <p>
580   - * 仅适用于「新消息」推送场景({@code sendTime = now}),不涉及 joinTime / quitTime 判定,
581   - * 只应用 {@code receiverUserIds} 定向过滤;语义与
582   - * {@link #isMessageVisible(ImGroupMessageDO, ImGroupMemberDO, Long)} 的第 3 步保持一致。
  477 + * 仅适用于「新消息」发送场景:无定向接收列表则全员可见,否则取定向用户与当前成员的交集;
  478 + * 发送者始终纳入快照,保证 receiver_user_ids 非空且发送方可见。
583 479 */
584   - private Set<Long> getVisibleUserIds(List<Long> receiverUserIds, Long senderId, Collection<Long> memberUserIds) {
585   - if (CollUtil.isEmpty(memberUserIds)) {
586   - return new HashSet<>();
587   - }
588   - // 无定向接收列表 → 全员可见
589   - if (CollUtil.isEmpty(receiverUserIds)) {
590   - return new HashSet<>(memberUserIds);
591   - }
592   - // 有定向接收列表 → 仅定向用户可见;发送者自己也能看到自己的消息(多端同步)
593   - Set<Long> allowed = new HashSet<>(receiverUserIds);
  480 + private Set<Long> getReceiverUserIds(List<Long> directedUserIds, Long senderId, Collection<Long> memberUserIds) {
  481 + // 无定向接收列表 → 全员可见;否则取定向用户与当前成员的交集
  482 + Set<Long> result = CollUtil.isEmpty(directedUserIds)
  483 + ? new HashSet<>(memberUserIds)
  484 + : new HashSet<>(CollUtil.intersection(memberUserIds, directedUserIds));
  485 + // 发送者始终可见(多端同步),即便成员缓存暂未包含
594 486 if (senderId != null) {
595   - allowed.add(senderId);
596   - }
597   - Set<Long> result = new HashSet<>();
598   - for (Long userId : memberUserIds) {
599   - if (allowed.contains(userId)) {
600   - result.add(userId);
601   - }
  487 + result.add(senderId);
602 488 }
603 489 return result;
604 490 }
605 491  
606   - @Override
607   - public void deleteReadMaxMessageId(Long groupId, Long userId) {
608   - groupMessageReadRedisDAO.deleteReadMaxMessageId(groupId, userId);
609   - }
610   -
611   - @Override
612   - public void deleteReadMaxMessageIds(Long groupId, Collection<Long> userIds) {
613   - groupMessageReadRedisDAO.deleteReadMaxMessageIds(groupId, userIds);
614   - }
615   -
616   - @Override
617   - public void deleteReadMaxMessageIdMap(Long groupId) {
618   - groupMessageReadRedisDAO.deleteReadMaxMessageIdMap(groupId);
619   - }
620   -
621 492 // ==================== 管理后台 ====================
622 493  
623 494 @Override
... ... @@ -652,11 +523,11 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
652 523 */
653 524 private Integer resolveReceiptStatus(Boolean receipt) {
654 525 if (BooleanUtil.isFalse(imProperties.getMessage().isGroupReadEnabled())) {
655   - return ImGroupMessageReceiptStatusEnum.NO_RECEIPT.getStatus();
  526 + return ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus();
656 527 }
657 528 return BooleanUtil.isTrue(receipt)
658   - ? ImGroupMessageReceiptStatusEnum.PENDING.getStatus()
659   - : ImGroupMessageReceiptStatusEnum.NO_RECEIPT.getStatus();
  529 + ? ImMessageReceiptStatusEnum.PENDING.getStatus()
  530 + : ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus();
660 531 }
661 532  
662 533 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java
... ... @@ -59,8 +59,8 @@ public interface ImPrivateMessageService {
59 59 /**
60 60 * 标记私聊消息已读
61 61 * <p>
62   - * 语义:将「对方发给当前用户、id <= messageId 的未读消息」一次性翻转为已读,
63   - * 与群聊 readGroupMessages 对称,避免"select-then-update"两步式带来的竞态。
  62 + * 语义:把「对方发给当前用户、id <= messageId 的待回执消息」一次性更新为已完成(DONE)并前进读位置,
  63 + * 与群聊 readGroupMessages 对称,避免「select-then-update」两步式带来的竞态。
64 64 *
65 65 * @param userId 当前用户编号
66 66 * @param receiverId 接收方用户编号(对方)
... ... @@ -72,7 +72,7 @@ public interface ImPrivateMessageService {
72 72 * 查询对方已读到我发的最大消息 id
73 73 * <p>
74 74 * 用于多端 / 离线场景下的已读位置补齐:客户端进入会话或断线重连后,
75   - * 调用此接口拿到对方的 maxReadId,再按 id <= maxReadId 翻转本地自发消息为已读,弥补离线期间错过的 RECEIPT 推送事件。
  75 + * 调用此接口拿到对方的 maxReadId,再按 id <= maxReadId 更新本地自发消息的回执状态,弥补离线期间错过的 RECEIPT 推送事件。
76 76 *
77 77 * @param userId 当前用户编号
78 78 * @param peerId 对方用户编号
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
... ... @@ -12,19 +12,25 @@ import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivate
12 12 import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivateMessageSendReqVO;
13 13 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
14 14 import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
  15 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
  16 +import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
15 17 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
16   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  18 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
17 19 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
  20 +import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
18 21 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
19 22 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO;
20 23 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
21 24 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
22   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
23   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage;
24   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage;
  25 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReadNotification;
  26 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReceiptNotification;
  27 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImPrivateMessageNotification;
  28 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage;
  29 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.RecallMessage;
25 30 import cn.iocoder.yudao.module.im.util.ImMessageUtils;
26 31 import jakarta.annotation.Resource;
27 32 import lombok.extern.slf4j.Slf4j;
  33 +import org.springframework.dao.DuplicateKeyException;
28 34 import org.springframework.stereotype.Service;
29 35 import org.springframework.transaction.annotation.Transactional;
30 36 import org.springframework.validation.annotation.Validated;
... ... @@ -52,6 +58,8 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
52 58 private ImFriendService friendService;
53 59 @Resource
54 60 private ImSensitiveWordService sensitiveWordService;
  61 + @Resource
  62 + private ImConversationReadService conversationReadService;
55 63  
56 64 @Resource
57 65 private ImWebSocketService imWebSocketService;
... ... @@ -74,21 +82,32 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
74 82 // 1.3 好友校验
75 83 friendService.validateFriend(senderId, reqVO.getReceiverId());
76 84 // 1.4 文本消息敏感词过滤
77   - if (ImMessageTypeEnum.TEXT.getType().equals(reqVO.getType())) {
  85 + if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) {
78 86 sensitiveWordService.validateText(reqVO.getContent());
79 87 }
80 88  
81 89 // 2.1 引用 quote 消息规范化
82 90 reqVO.setContent(normalizeQuoteContent(reqVO, senderId));
83   - // 2.2 构建并保存消息
  91 + // 2.2 构建并保存消息;唯一键冲突时回查已存在消息返回
  92 + // 用户私聊消息默认需要回执(receipt 不传按 true);系统通知走 DTO 通道,默认不回执
  93 + Boolean receipt = reqVO.getReceipt() != null ? reqVO.getReceipt() : Boolean.TRUE;
84 94 ImPrivateMessageDO message = BeanUtils.toBean(reqVO, ImPrivateMessageDO.class, m -> m
85   - .setSenderId(senderId).setStatus(ImMessageStatusEnum.UNREAD.getStatus()).setSendTime(LocalDateTime.now()));
86   - privateMessageMapper.insert(message);
  95 + .setSenderId(senderId).setStatus(ImMessageStatusEnum.NORMAL.getStatus())
  96 + .setReceiptStatus(resolveReceiptStatus(receipt)).setSendTime(LocalDateTime.now()));
  97 + try {
  98 + privateMessageMapper.insert(message);
  99 + } catch (DuplicateKeyException e) {
  100 + log.warn("[sendPrivateMessage][senderId({}) clientMessageId({}) 并发插入冲突,回查返回]",
  101 + senderId, reqVO.getClientMessageId());
  102 + return privateMessageMapper.selectBySenderIdAndClientMessageId(senderId, reqVO.getClientMessageId());
  103 + }
87 104  
88 105 // 3. WebSocket 异步推送:接收方 + 发送方多端同步
89   - ImPrivateMessageDTO websocketMessage = ImPrivateMessageDTO.ofSend(message);
90   - imWebSocketService.sendPrivateMessageAsync(message.getReceiverId(), websocketMessage);
91   - imWebSocketService.sendPrivateMessageAsync(senderId, websocketMessage);
  106 + ImPrivateMessageNotification notification = ImPrivateMessageNotification.ofSend(message);
  107 + imWebSocketService.sendNotificationAsync(message.getReceiverId(), ImConversationTypeEnum.PRIVATE.getType(),
  108 + notification.getType(), notification);
  109 + imWebSocketService.sendNotificationAsync(senderId, ImConversationTypeEnum.PRIVATE.getType(),
  110 + notification.getType(), notification);
92 111 return message;
93 112 }
94 113  
... ... @@ -103,24 +122,39 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
103 122 ImPrivateMessageDO message = new ImPrivateMessageDO().setClientMessageId(IdUtil.fastSimpleUUID())
104 123 .setSenderId(senderId).setReceiverId(dto.getReceiverId())
105 124 .setType(dto.getType()).setContent(contentString)
106   - .setStatus(ImMessageStatusEnum.UNREAD.getStatus()).setSendTime(LocalDateTime.now());
  125 + .setStatus(ImMessageStatusEnum.NORMAL.getStatus())
  126 + .setReceiptStatus(resolveReceiptStatus(dto.getReceipt())).setSendTime(LocalDateTime.now());
107 127 // 1.3 决定是否持久化:dto.persistent 优先;为 null 时按 type 默认
108 128 boolean persistent = dto.getPersistent() != null
109 129 ? dto.getPersistent()
110   - : ImMessageTypeEnum.validate(dto.getType()).isPersistent();
  130 + : ImContentTypeEnum.validate(dto.getType()).isPersistent();
111 131 if (persistent) {
112 132 privateMessageMapper.insert(message);
113 133 }
114 134  
115 135 // 2. WebSocket 异步推送:双向(默认);单边语义(persistent=false)下仅推 sender 多端,对方不感知
116   - ImPrivateMessageDTO websocketMessage = ImPrivateMessageDTO.ofSend(message);
  136 + ImPrivateMessageNotification notification = ImPrivateMessageNotification.ofSend(message);
117 137 if (persistent) {
118   - imWebSocketService.sendPrivateMessageAsync(dto.getReceiverId(), websocketMessage);
  138 + imWebSocketService.sendNotificationAsync(dto.getReceiverId(), ImConversationTypeEnum.PRIVATE.getType(),
  139 + notification.getType(), notification);
119 140 }
120   - imWebSocketService.sendPrivateMessageAsync(senderId, websocketMessage);
  141 + imWebSocketService.sendNotificationAsync(senderId, ImConversationTypeEnum.PRIVATE.getType(),
  142 + notification.getType(), notification);
121 143 return message;
122 144 }
123 145  
  146 + /**
  147 + * 计算私聊消息回执 status:私聊已读关闭时强制 NO_RECEIPT,忽略发送方传入的 receipt(receipt 为 null 等价 false)
  148 + */
  149 + private Integer resolveReceiptStatus(Boolean receipt) {
  150 + if (BooleanUtil.isFalse(imProperties.getMessage().isPrivateReadEnabled())) {
  151 + return ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus();
  152 + }
  153 + return BooleanUtil.isTrue(receipt)
  154 + ? ImMessageReceiptStatusEnum.PENDING.getStatus()
  155 + : ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus();
  156 + }
  157 +
124 158 @Override
125 159 @Transactional(rollbackFor = Exception.class)
126 160 public ImPrivateMessageDO recallPrivateMessage(Long userId, Long messageId) {
... ... @@ -149,7 +183,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
149 183  
150 184 // 3. 发送撤回事件
151 185 return sendPrivateMessage(userId, new ImPrivateMessageSendDTO().setReceiverId(message.getReceiverId())
152   - .setType(ImMessageTypeEnum.RECALL.getType()).setContent(new RecallMessage().setMessageId(messageId)));
  186 + .setType(ImContentTypeEnum.RECALL.getType()).setContent(new RecallMessage().setMessageId(messageId)));
153 187 }
154 188  
155 189 /**
... ... @@ -211,20 +245,26 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
211 245 throw exception(MESSAGE_PRIVATE_READ_DISABLED);
212 246 }
213 247 Assert.notNull(messageId, "已读消息编号不能为空");
214   - // 2. 把 (receiverId → userId) 这条会话上、id <= messageId 的未读消息一步更新为已读
215   - // 仅 UNREAD 行被命中,避免覆盖已撤回/已读的状态;select-then-update 合成单条 SQL 后也消除了竞态窗口
216   - int updated = privateMessageMapper.updateBySenderIdAndReceiverIdAndIdLeAndStatus(
217   - receiverId, userId, messageId, ImMessageStatusEnum.UNREAD.getStatus(),
218   - new ImPrivateMessageDO().setStatus(ImMessageStatusEnum.READ.getStatus()));
219   - if (updated == 0) {
  248 +
  249 + // 2. 回执置 DONE:把 (receiverId → userId) 上 id <= messageId、待回执(PENDING) 的消息标记为已完成
  250 + // status 不再表达已读(保持 NORMAL);只翻 PENDING 行,避免覆盖 NO_RECEIPT / 已 DONE
  251 + privateMessageMapper.updateBySenderIdAndReceiverIdAndIdLeAndReceiptStatus(
  252 + receiverId, userId, messageId, ImMessageReceiptStatusEnum.PENDING.getStatus(),
  253 + new ImPrivateMessageDO().setReceiptStatus(ImMessageReceiptStatusEnum.DONE.getStatus()));
  254 +
  255 + // 3. 同步写 im_conversation_read(读位置唯一权威,单调递增);读位置前进才下发事件
  256 + boolean advanced = conversationReadService.updateConversationReadPosition(
  257 + userId, ImConversationTypeEnum.PRIVATE.getType(), receiverId, messageId);
  258 + if (!advanced) {
220 259 return;
221 260 }
222 261  
223   - // 3. 异步发送 READ + RECEIPT 事件(已读位置以前端上报为准,与多端 / 对方 UI 显示一致)
224   - imWebSocketService.sendPrivateMessageAsync(userId,
225   - ImPrivateMessageDTO.ofRead(userId, receiverId, messageId));
226   - imWebSocketService.sendPrivateMessageAsync(receiverId,
227   - ImPrivateMessageDTO.ofReceipt(userId, receiverId, messageId));
  262 + // 4. 异步发送 READ + RECEIPT 事件(已读位置以前端上报为准,与多端 / 对方 UI 显示一致)
  263 + imWebSocketService.sendNotificationAsync(userId, ImConversationTypeEnum.PRIVATE.getType(),
  264 + ImContentTypeEnum.READ.getType(), ImMessageReadNotification.ofPrivate(userId, receiverId, messageId));
  265 + imWebSocketService.sendNotificationAsync(receiverId, ImConversationTypeEnum.PRIVATE.getType(),
  266 + ImContentTypeEnum.RECEIPT.getType(),
  267 + ImMessageReceiptNotification.ofPrivate(userId, receiverId, messageId));
228 268 }
229 269  
230 270 @Override
... ... @@ -232,8 +272,9 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
232 272 if (BooleanUtil.isFalse(imProperties.getMessage().isPrivateReadEnabled())) {
233 273 throw exception(MESSAGE_PRIVATE_READ_DISABLED);
234 274 }
235   - return privateMessageMapper.selectMaxIdBySenderIdAndReceiverIdAndStatus(
236   - userId, peerId, ImMessageStatusEnum.READ.getStatus());
  275 + // 对端 peer 在「与 userId 的会话」里的读位置 = peer 把 userId 发的消息读到哪
  276 + return conversationReadService.getConversationReadMessageId(
  277 + peerId, ImConversationTypeEnum.PRIVATE.getType(), userId);
237 278 }
238 279  
239 280 @Override
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImGroupMessageSendDTO.java
1 1 package cn.iocoder.yudao.module.im.service.message.dto;
2 2  
3 3 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
4   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
5   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.*;
  4 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  5 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.*;
6 6 import jakarta.validation.constraints.NotNull;
7 7 import lombok.Data;
8 8  
... ... @@ -26,7 +26,7 @@ public class ImGroupMessageSendDTO {
26 26 /**
27 27 * 消息类型
28 28 * <p>
29   - * 枚举 {@link ImMessageTypeEnum}
  29 + * 枚举 {@link ImContentTypeEnum}
30 30 */
31 31 @NotNull(message = "消息类型不能为空")
32 32 private Integer type;
... ... @@ -53,30 +53,34 @@ public class ImGroupMessageSendDTO {
53 53 */
54 54 private Boolean receipt;
55 55  
56   - // ========== 群广播事件静态工厂(对应 ImMessageTypeEnum 群事件) ==========
  56 + // ========== 群广播事件静态工厂(对应 ImContentTypeEnum 群事件) ==========
57 57  
58 58 public static ImGroupMessageSendDTO ofGroupCreate(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
59 59 GroupCreateNotification notification = new GroupCreateNotification();
60 60 notification.setOperatorUserId(operatorUserId);
61 61 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
62 62 return new ImGroupMessageSendDTO().setGroupId(groupId)
63   - .setType(ImMessageTypeEnum.GROUP_CREATE.getType()).setContent(notification);
  63 + .setType(ImContentTypeEnum.GROUP_CREATE.getType()).setContent(notification);
64 64 }
65 65  
66   - public static ImGroupMessageSendDTO ofGroupInfoUpdate(Long groupId, Long operatorUserId, String oldAvatar, String newAvatar) {
  66 + public static ImGroupMessageSendDTO ofGroupInfoUpdate(Long groupId, Long operatorUserId,
  67 + String oldAvatar, String newAvatar,
  68 + Boolean oldJoinApproval, Boolean newJoinApproval) {
67 69 GroupInfoUpdateNotification notification = new GroupInfoUpdateNotification();
68 70 notification.setOperatorUserId(operatorUserId);
69 71 notification.setOldAvatar(oldAvatar);
70 72 notification.setNewAvatar(newAvatar);
  73 + notification.setOldJoinApproval(oldJoinApproval);
  74 + notification.setNewJoinApproval(newJoinApproval);
71 75 return new ImGroupMessageSendDTO().setGroupId(groupId)
72   - .setType(ImMessageTypeEnum.GROUP_INFO_UPDATE.getType()).setContent(notification);
  76 + .setType(ImContentTypeEnum.GROUP_INFO_UPDATE.getType()).setContent(notification);
73 77 }
74 78  
75 79 public static ImGroupMessageSendDTO ofGroupMemberQuit(Long groupId, Long operatorUserId) {
76 80 GroupMemberQuitNotification notification = new GroupMemberQuitNotification();
77 81 notification.setOperatorUserId(operatorUserId);
78 82 return new ImGroupMessageSendDTO().setGroupId(groupId)
79   - .setType(ImMessageTypeEnum.GROUP_MEMBER_QUIT.getType()).setContent(notification);
  83 + .setType(ImContentTypeEnum.GROUP_MEMBER_QUIT.getType()).setContent(notification);
80 84 }
81 85  
82 86 public static ImGroupMessageSendDTO ofGroupOwnerTransfer(Long groupId, Long operatorUserId, Long newOwnerUserId) {
... ... @@ -84,7 +88,7 @@ public class ImGroupMessageSendDTO {
84 88 notification.setOperatorUserId(operatorUserId);
85 89 notification.setNewOwnerUserId(newOwnerUserId);
86 90 return new ImGroupMessageSendDTO().setGroupId(groupId)
87   - .setType(ImMessageTypeEnum.GROUP_OWNER_TRANSFER.getType()).setContent(notification);
  91 + .setType(ImContentTypeEnum.GROUP_OWNER_TRANSFER.getType()).setContent(notification);
88 92 }
89 93  
90 94 public static ImGroupMessageSendDTO ofGroupMemberKick(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -92,7 +96,7 @@ public class ImGroupMessageSendDTO {
92 96 notification.setOperatorUserId(operatorUserId);
93 97 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
94 98 return new ImGroupMessageSendDTO().setGroupId(groupId)
95   - .setType(ImMessageTypeEnum.GROUP_MEMBER_KICK.getType()).setContent(notification);
  99 + .setType(ImContentTypeEnum.GROUP_MEMBER_KICK.getType()).setContent(notification);
96 100 }
97 101  
98 102 public static ImGroupMessageSendDTO ofGroupMemberInvite(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -100,7 +104,7 @@ public class ImGroupMessageSendDTO {
100 104 notification.setOperatorUserId(operatorUserId);
101 105 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
102 106 return new ImGroupMessageSendDTO().setGroupId(groupId)
103   - .setType(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType()).setContent(notification);
  107 + .setType(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType()).setContent(notification);
104 108 }
105 109  
106 110 public static ImGroupMessageSendDTO ofGroupMemberEnter(Long groupId, Long entrantUserId, Integer addSource) {
... ... @@ -109,14 +113,14 @@ public class ImGroupMessageSendDTO {
109 113 notification.setEntrantUserId(entrantUserId);
110 114 notification.setAddSource(addSource);
111 115 return new ImGroupMessageSendDTO().setGroupId(groupId)
112   - .setType(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType()).setContent(notification);
  116 + .setType(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType()).setContent(notification);
113 117 }
114 118  
115 119 public static ImGroupMessageSendDTO ofGroupDissolve(Long groupId, Long operatorUserId) {
116 120 GroupDissolveNotification notification = new GroupDissolveNotification();
117 121 notification.setOperatorUserId(operatorUserId);
118 122 return new ImGroupMessageSendDTO().setGroupId(groupId)
119   - .setType(ImMessageTypeEnum.GROUP_DISSOLVE.getType()).setContent(notification);
  123 + .setType(ImContentTypeEnum.GROUP_DISSOLVE.getType()).setContent(notification);
120 124 }
121 125  
122 126 public static ImGroupMessageSendDTO ofGroupMemberNicknameUpdate(Long groupId, Long operatorUserId, String displayUserName) {
... ... @@ -124,7 +128,7 @@ public class ImGroupMessageSendDTO {
124 128 notification.setOperatorUserId(operatorUserId);
125 129 notification.setDisplayUserName(displayUserName);
126 130 return new ImGroupMessageSendDTO().setGroupId(groupId)
127   - .setType(ImMessageTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()).setContent(notification);
  131 + .setType(ImContentTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()).setContent(notification);
128 132 }
129 133  
130 134 public static ImGroupMessageSendDTO ofGroupAdminAdd(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -132,7 +136,7 @@ public class ImGroupMessageSendDTO {
132 136 notification.setOperatorUserId(operatorUserId);
133 137 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
134 138 return new ImGroupMessageSendDTO().setGroupId(groupId)
135   - .setType(ImMessageTypeEnum.GROUP_ADMIN_ADD.getType()).setContent(notification);
  139 + .setType(ImContentTypeEnum.GROUP_ADMIN_ADD.getType()).setContent(notification);
136 140 }
137 141  
138 142 public static ImGroupMessageSendDTO ofGroupAdminRemove(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -140,7 +144,7 @@ public class ImGroupMessageSendDTO {
140 144 notification.setOperatorUserId(operatorUserId);
141 145 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
142 146 return new ImGroupMessageSendDTO().setGroupId(groupId)
143   - .setType(ImMessageTypeEnum.GROUP_ADMIN_REMOVE.getType()).setContent(notification);
  147 + .setType(ImContentTypeEnum.GROUP_ADMIN_REMOVE.getType()).setContent(notification);
144 148 }
145 149  
146 150 public static ImGroupMessageSendDTO ofGroupNoticeUpdate(Long groupId, Long operatorUserId, String oldNotice, String newNotice) {
... ... @@ -148,7 +152,7 @@ public class ImGroupMessageSendDTO {
148 152 notification.setOperatorUserId(operatorUserId);
149 153 notification.setOldNotice(oldNotice).setNewNotice(newNotice);
150 154 return new ImGroupMessageSendDTO().setGroupId(groupId)
151   - .setType(ImMessageTypeEnum.GROUP_NOTICE_UPDATE.getType()).setContent(notification);
  155 + .setType(ImContentTypeEnum.GROUP_NOTICE_UPDATE.getType()).setContent(notification);
152 156 }
153 157  
154 158 public static ImGroupMessageSendDTO ofGroupNameUpdate(Long groupId, Long operatorUserId, String oldName, String newName) {
... ... @@ -156,7 +160,7 @@ public class ImGroupMessageSendDTO {
156 160 notification.setOperatorUserId(operatorUserId);
157 161 notification.setOldName(oldName).setNewName(newName);
158 162 return new ImGroupMessageSendDTO().setGroupId(groupId)
159   - .setType(ImMessageTypeEnum.GROUP_NAME_UPDATE.getType()).setContent(notification);
  163 + .setType(ImContentTypeEnum.GROUP_NAME_UPDATE.getType()).setContent(notification);
160 164 }
161 165  
162 166 public static ImGroupMessageSendDTO ofGroupMemberSettingUpdate(Long groupId, Long operatorUserId, Boolean silent, String groupRemark) {
... ... @@ -164,7 +168,7 @@ public class ImGroupMessageSendDTO {
164 168 notification.setOperatorUserId(operatorUserId);
165 169 notification.setSilent(silent).setGroupRemark(groupRemark);
166 170 return new ImGroupMessageSendDTO().setGroupId(groupId)
167   - .setType(ImMessageTypeEnum.GROUP_MEMBER_SETTING_UPDATE.getType()).setContent(notification);
  171 + .setType(ImContentTypeEnum.GROUP_MEMBER_SETTING_UPDATE.getType()).setContent(notification);
168 172 }
169 173  
170 174 public static ImGroupMessageSendDTO ofGroupMessagePin(Long groupId, Long operatorUserId, ImGroupMessageDO message) {
... ... @@ -176,7 +180,7 @@ public class ImGroupMessageSendDTO {
176 180 notification.setOperatorUserId(operatorUserId);
177 181 notification.setMessageId(message.getId()).setMessage(pinnedMessage);
178 182 return new ImGroupMessageSendDTO().setGroupId(groupId)
179   - .setType(ImMessageTypeEnum.GROUP_MESSAGE_PIN.getType()).setContent(notification);
  183 + .setType(ImContentTypeEnum.GROUP_MESSAGE_PIN.getType()).setContent(notification);
180 184 }
181 185  
182 186 public static ImGroupMessageSendDTO ofGroupMessageUnpin(Long groupId, Long operatorUserId, Long messageId) {
... ... @@ -184,7 +188,7 @@ public class ImGroupMessageSendDTO {
184 188 notification.setOperatorUserId(operatorUserId);
185 189 notification.setMessageId(messageId);
186 190 return new ImGroupMessageSendDTO().setGroupId(groupId)
187   - .setType(ImMessageTypeEnum.GROUP_MESSAGE_UNPIN.getType()).setContent(notification);
  191 + .setType(ImContentTypeEnum.GROUP_MESSAGE_UNPIN.getType()).setContent(notification);
188 192 }
189 193  
190 194 public static ImGroupMessageSendDTO ofGroupMemberMuted(Long groupId, Long operatorUserId,
... ... @@ -195,7 +199,7 @@ public class ImGroupMessageSendDTO {
195 199 notification.setMutedUserId(mutedUserId);
196 200 notification.setMuteEndTime(muteEndTime);
197 201 return new ImGroupMessageSendDTO().setGroupId(groupId)
198   - .setType(ImMessageTypeEnum.GROUP_MEMBER_MUTED.getType()).setContent(notification);
  202 + .setType(ImContentTypeEnum.GROUP_MEMBER_MUTED.getType()).setContent(notification);
199 203 }
200 204  
201 205 public static ImGroupMessageSendDTO ofGroupMemberCancelMuted(Long groupId, Long operatorUserId, Long mutedUserId) {
... ... @@ -203,21 +207,21 @@ public class ImGroupMessageSendDTO {
203 207 notification.setOperatorUserId(operatorUserId);
204 208 notification.setMutedUserId(mutedUserId);
205 209 return new ImGroupMessageSendDTO().setGroupId(groupId)
206   - .setType(ImMessageTypeEnum.GROUP_MEMBER_CANCEL_MUTED.getType()).setContent(notification);
  210 + .setType(ImContentTypeEnum.GROUP_MEMBER_CANCEL_MUTED.getType()).setContent(notification);
207 211 }
208 212  
209 213 public static ImGroupMessageSendDTO ofGroupMuted(Long groupId, Long operatorUserId) {
210 214 GroupMutedNotification notification = new GroupMutedNotification();
211 215 notification.setOperatorUserId(operatorUserId);
212 216 return new ImGroupMessageSendDTO().setGroupId(groupId)
213   - .setType(ImMessageTypeEnum.GROUP_MUTED.getType()).setContent(notification);
  217 + .setType(ImContentTypeEnum.GROUP_MUTED.getType()).setContent(notification);
214 218 }
215 219  
216 220 public static ImGroupMessageSendDTO ofGroupCancelMuted(Long groupId, Long operatorUserId) {
217 221 GroupCancelMutedNotification notification = new GroupCancelMutedNotification();
218 222 notification.setOperatorUserId(operatorUserId);
219 223 return new ImGroupMessageSendDTO().setGroupId(groupId)
220   - .setType(ImMessageTypeEnum.GROUP_CANCEL_MUTED.getType()).setContent(notification);
  224 + .setType(ImContentTypeEnum.GROUP_CANCEL_MUTED.getType()).setContent(notification);
221 225 }
222 226  
223 227 public static ImGroupMessageSendDTO ofGroupBanned(Long groupId, Long operatorUserId, boolean banned) {
... ... @@ -225,7 +229,7 @@ public class ImGroupMessageSendDTO {
225 229 notification.setOperatorUserId(operatorUserId);
226 230 notification.setBanned(banned);
227 231 return new ImGroupMessageSendDTO().setGroupId(groupId)
228   - .setType(ImMessageTypeEnum.GROUP_BANNED.getType()).setContent(notification);
  232 + .setType(ImContentTypeEnum.GROUP_BANNED.getType()).setContent(notification);
229 233 }
230 234  
231 235 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImPrivateMessageSendDTO.java
1 1 package cn.iocoder.yudao.module.im.service.message.dto;
2 2  
3   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  3 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
4 4 import lombok.Data;
5 5  
6 6 /**
... ... @@ -18,7 +18,7 @@ public class ImPrivateMessageSendDTO {
18 18 /**
19 19 * 消息类型
20 20 * <p>
21   - * 枚举 {@link ImMessageTypeEnum}
  21 + * 枚举 {@link ImContentTypeEnum}
22 22 */
23 23 private Integer type;
24 24 /**
... ... @@ -30,10 +30,14 @@ public class ImPrivateMessageSendDTO {
30 30 /**
31 31 * 是否持久化 + 推送给接收方(单边语义开关)
32 32 * <p>
33   - * null:默认按 {@link ImMessageTypeEnum#isPersistent()} 决定是否入库 + 双向 WS 推送(保持原行为)<br>
  33 + * null:默认按 {@link ImContentTypeEnum#isPersistent()} 决定是否入库 + 双向 WS 推送(保持原行为)<br>
34 34 * false:覆盖为单边——不入库、仅推 sender 多端,对方不感知(如「你已删除 XXX」这类仅自己可见的 TIP)<br>
35 35 * true:覆盖为双向 + 入库
36 36 */
37 37 private Boolean persistent;
  38 + /**
  39 + * 是否需要回执;null 等价 false(系统消息默认不需要回执)
  40 + */
  41 + private Boolean receipt;
38 42  
39 43 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java
... ... @@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.rtc.ImRtcCallMapper;
15 15 import cn.iocoder.yudao.module.im.dal.mysql.rtc.ImRtcParticipantMapper;
16 16 import cn.iocoder.yudao.module.im.dal.redis.rtc.ImRtcCallLockRedisDAO;
17 17 import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
18   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  18 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
19 19 import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallEndReasonEnum;
20 20 import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallStatusEnum;
21 21 import cn.iocoder.yudao.module.im.enums.rtc.ImRtcParticipantRoleEnum;
... ... @@ -30,8 +30,7 @@ import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService;
30 30 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
31 31 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO;
32 32 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
33   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
34   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc.*;
  33 +import cn.iocoder.yudao.module.im.service.websocket.notification.rtc.*;
35 34 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
36 35 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
37 36 import jakarta.annotation.Resource;
... ... @@ -57,7 +56,7 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
57 56 * 并发幂等:同好友对 / 同群活跃唯一性走 {@link ImRtcCallLockRedisDAO} 分布式锁 + 锁内 SELECT 兜底;webhook 兜底走条件 UPDATE;
58 57 * <p>
59 58 * 推送通道分流:
60   - * 1601 RTC_CALL(INVITING / JOINED / REJECTED / NO_ANSWER / LEFT 子类型)→ {@link ImWebSocketService#sendPrivateMessageAsync} 仅推参与方;
  59 + * 1601 RTC_CALL(INVITING / JOINED / REJECTED / NO_ANSWER / LEFT 子类型)→ {@link ImWebSocketService#sendNotificationAsync} 仅推参与方;
61 60 * 1602 / 1603 PARTICIPANT_CONNECTED / DISCONNECTED → {@link ImWebSocketService} 推参与方 + 群通话场景广播全群;
62 61 * 1610 RTC_CALL_START + 1611 RTC_CALL_END → {@link ImPrivateMessageService} / {@link ImGroupMessageService} 入消息流当聊天 tip
63 62 * (START 仅群通话;两者分别在 invite / cancel(leave) 事务里 INSERT,自增 id 自然保证顺序)
... ... @@ -707,7 +706,6 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
707 706 }
708 707  
709 708 // 3.1 群通话:推 RTC_CALL(NO_ANSWER) 让前端 banner 移除该人 + 级联关房判定
710   - // TODO DONE @AI:拆分独立 NO_ANSWER 信令,不再复用 REJECT
711 709 if (ImConversationTypeEnum.isGroup(call.getConversationType())) {
712 710 pushCallNoAnswerNotification(call, userId, userMap.get(userId));
713 711 endSessionIfTerminal(call, userId);
... ... @@ -1003,8 +1001,8 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1003 1001 String token = signToken(inviteeId, resolveDisplayName(invitee, inviteeId), call.getRoom());
1004 1002 ImRtcCallNotification payload = ImRtcCallNotification.ofInvite(
1005 1003 call, inviter, imProperties.getRtc().getLivekitUrl(), token, inviteeIds);
1006   - webSocketService.sendPrivateMessageAsync(inviteeId, ImPrivateMessageDTO.ofRtcNotification(
1007   - ImMessageTypeEnum.RTC_CALL.getType(), call.getInviterUserId(), inviteeId, payload));
  1004 + webSocketService.sendNotificationAsync(inviteeId, ImConversationTypeEnum.NONE.getType(),
  1005 + ImContentTypeEnum.RTC_CALL.getType(), payload);
1008 1006 }
1009 1007  
1010 1008 /**
... ... @@ -1019,8 +1017,8 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1019 1017 AdminUserRespDTO operator = operatorUserId != null ? adminUserApi.getUser(operatorUserId) : null;
1020 1018 ImRtcCallNotification payload = ImRtcCallNotification.ofReject(call, operatorUserId, operator);
1021 1019 for (Long receiverUserId : getCallAudienceUserIdList(call)) {
1022   - webSocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofRtcNotification(
1023   - ImMessageTypeEnum.RTC_CALL.getType(), operatorUserId, receiverUserId, payload));
  1020 + webSocketService.sendNotificationAsync(receiverUserId, ImConversationTypeEnum.NONE.getType(),
  1021 + ImContentTypeEnum.RTC_CALL.getType(), payload);
1024 1022 }
1025 1023 }
1026 1024  
... ... @@ -1036,8 +1034,8 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1036 1034 private void pushCallNoAnswerNotification(ImRtcCallDO call, Long operatorUserId, AdminUserRespDTO operator) {
1037 1035 ImRtcCallNotification payload = ImRtcCallNotification.ofNoAnswer(call, operatorUserId, operator);
1038 1036 for (Long receiverUserId : getCallAudienceUserIdList(call)) {
1039   - webSocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofRtcNotification(
1040   - ImMessageTypeEnum.RTC_CALL.getType(), operatorUserId, receiverUserId, payload));
  1037 + webSocketService.sendNotificationAsync(receiverUserId, ImConversationTypeEnum.NONE.getType(),
  1038 + ImContentTypeEnum.RTC_CALL.getType(), payload);
1041 1039 }
1042 1040 }
1043 1041  
... ... @@ -1048,7 +1046,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1048 1046 * @param userId 加入的参与者用户编号
1049 1047 */
1050 1048 private void pushParticipantConnectedNotification(ImRtcCallDO call, Long userId) {
1051   - pushParticipantNotification(call, ImMessageTypeEnum.RTC_PARTICIPANT_CONNECTED.getType(), userId,
  1049 + pushParticipantNotification(call, ImContentTypeEnum.RTC_PARTICIPANT_CONNECTED.getType(), userId,
1052 1050 ImRtcParticipantConnectedNotification.of(call, userId));
1053 1051 }
1054 1052  
... ... @@ -1059,7 +1057,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1059 1057 * @param userId 离开的参与者用户编号
1060 1058 */
1061 1059 private void pushParticipantDisconnectedNotification(ImRtcCallDO call, Long userId) {
1062   - pushParticipantNotification(call, ImMessageTypeEnum.RTC_PARTICIPANT_DISCONNECTED.getType(), userId,
  1060 + pushParticipantNotification(call, ImContentTypeEnum.RTC_PARTICIPANT_DISCONNECTED.getType(), userId,
1063 1061 ImRtcParticipantDisconnectedNotification.of(call, userId));
1064 1062 }
1065 1063  
... ... @@ -1076,8 +1074,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1076 1074 if (CollUtil.isEmpty(receivers)) {
1077 1075 return;
1078 1076 }
1079   - ImPrivateMessageDTO dto = ImPrivateMessageDTO.ofRtcNotification(type, actorUserId, null, payload);
1080   - webSocketService.sendPrivateMessageAsync(receivers, dto);
  1077 + webSocketService.sendNotificationAsync(receivers, ImConversationTypeEnum.NONE.getType(), type, payload);
1081 1078 }
1082 1079  
1083 1080 /**
... ... @@ -1092,7 +1089,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1092 1089 private void pushCallStartNotification(ImRtcCallDO call, AdminUserRespDTO inviter, Set<Long> invitees) {
1093 1090 ImRtcCallStartNotification payload = ImRtcCallStartNotification.of(call, inviter);
1094 1091 Long peerUserId = ImConversationTypeEnum.isGroup(call.getConversationType()) ? null : CollUtil.getFirst(invitees);
1095   - pushCallChatMessage(call, ImMessageTypeEnum.RTC_CALL_START, payload, peerUserId);
  1092 + pushCallChatMessage(call, ImContentTypeEnum.RTC_CALL_START, payload, peerUserId);
1096 1093 }
1097 1094  
1098 1095 /**
... ... @@ -1116,7 +1113,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1116 1113 p -> ObjUtil.notEqual(p.getUserId(), call.getInviterUserId()));
1117 1114 peerUserId = peer != null ? peer.getUserId() : null;
1118 1115 }
1119   - pushCallChatMessage(call, ImMessageTypeEnum.RTC_CALL_END, payload, peerUserId);
  1116 + pushCallChatMessage(call, ImContentTypeEnum.RTC_CALL_END, payload, peerUserId);
1120 1117 }
1121 1118  
1122 1119 /**
... ... @@ -1129,7 +1126,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1129 1126 * @param payload 推送 payload
1130 1127 * @param peerUserId 私聊对端用户编号;群聊忽略,私聊缺失时回退为 senderId
1131 1128 */
1132   - private void pushCallChatMessage(ImRtcCallDO call, ImMessageTypeEnum type, Object payload, Long peerUserId) {
  1129 + private void pushCallChatMessage(ImRtcCallDO call, ImContentTypeEnum type, Object payload, Long peerUserId) {
1133 1130 Long senderId = call.getInviterUserId();
1134 1131 if (ImConversationTypeEnum.isGroup(call.getConversationType())) {
1135 1132 ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO().setGroupId(call.getGroupId())
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/statistics/ImStatisticsManagerService.java
... ... @@ -80,7 +80,7 @@ public interface ImStatisticsManagerService {
80 80 Map<LocalDateTime, Long> getGroupMessageDailyCountMap(LocalDateTime beginTime, LocalDateTime endTime);
81 81  
82 82 /**
83   - * 获取区间内消息类型分布 Map(key 为消息类型)
  83 + * 获取区间内内容类型分布 Map(key 为消息类型)
84 84 */
85 85 Map<Integer, Long> getMessageTypeCountMap(LocalDateTime beginTime, LocalDateTime endTime);
86 86  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketService.java
1 1 package cn.iocoder.yudao.module.im.service.websocket;
2 2  
3   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO;
4   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
5   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
6   -
7 3 import java.util.Collection;
8 4 import java.util.Collections;
9 5  
10 6 /**
11 7 * IM WebSocket 推送 Service 接口
12 8 * <p>
13   - * 统一封装 WebSocket 消息推送,事务内调用时提交后异步执行。
  9 + * 统一封装 WebSocket 通知推送,事务内调用时提交后异步执行。
14 10 *
15 11 * @author 芋道源码
16 12 */
17 13 public interface ImWebSocketService {
18 14  
19 15 /**
20   - * 异步推送私聊消息给指定用户
21   - *
22   - * @param userId 目标用户编号
23   - * @param dto 私聊消息 DTO
24   - */
25   - default void sendPrivateMessageAsync(Long userId, ImPrivateMessageDTO dto) {
26   - sendPrivateMessageAsync(Collections.singleton(userId), dto);
27   - }
28   -
29   - /**
30   - * 异步批量推送私聊消息给多个用户;用于同一份 DTO 扇出到多个收件人
31   - * <p>
32   - * 相比逐个发送,仅注册一次 afterCommit 回调和异步任务。
33   - *
34   - * @param userIds 目标用户编号列表
35   - * @param dto 私聊消息 DTO
36   - */
37   - void sendPrivateMessageAsync(Collection<Long> userIds, ImPrivateMessageDTO dto);
38   -
39   - /**
40   - * 异步推送群聊消息给指定用户
41   - *
42   - * @param userId 目标用户编号
43   - * @param dto 群聊消息 DTO
44   - */
45   - default void sendGroupMessageAsync(Long userId, ImGroupMessageDTO dto) {
46   - sendGroupMessageAsync(Collections.singleton(userId), dto);
47   - }
48   -
49   - /**
50   - * 异步批量推送群聊消息给多个用户
51   - *
52   - * @param userIds 目标用户编号列表
53   - * @param dto 群聊消息 DTO
54   - */
55   - void sendGroupMessageAsync(Collection<Long> userIds, ImGroupMessageDTO dto);
56   -
57   - /**
58   - * 异步推送频道消息给指定用户
  16 + * 异步推送 WebSocket 通知给指定用户
59 17 *
60   - * @param userId 目标用户编号
61   - * @param dto 频道消息 DTO
  18 + * @param userId 目标用户编号
  19 + * @param conversationType 会话类型,参见 ImConversationTypeEnum 枚举类
  20 + * @param contentType 内容类型,参见 ImContentTypeEnum 枚举类
  21 + * @param payload 通知 payload
62 22 */
63   - default void sendChannelMessageAsync(Long userId, ImChannelMessageDTO dto) {
64   - sendChannelMessageAsync(Collections.singleton(userId), dto);
  23 + default void sendNotificationAsync(Long userId, Integer conversationType, Integer contentType, Object payload) {
  24 + sendNotificationAsync(Collections.singleton(userId), conversationType, contentType, payload);
65 25 }
66 26  
67 27 /**
68   - * 异步批量推送频道消息给多个用户
  28 + * 异步批量推送 WebSocket 通知给多个用户
69 29 *
70   - * @param userIds 目标用户编号列表
71   - * @param dto 频道消息 DTO
  30 + * @param userIds 目标用户编号列表
  31 + * @param conversationType 会话类型,参见 ImConversationTypeEnum 枚举类
  32 + * @param contentType 内容类型,参见 ImContentTypeEnum 枚举类
  33 + * @param payload 通知 payload
72 34 */
73   - void sendChannelMessageAsync(Collection<Long> userIds, ImChannelMessageDTO dto);
  35 + void sendNotificationAsync(Collection<Long> userIds, Integer conversationType, Integer contentType, Object payload);
74 36  
75 37 /**
76   - * 异步广播频道消息给当前所有在线管理端用户;用于全员推送
  38 + * 异步广播 WebSocket 通知给当前所有在线管理端用户
77 39 *
78   - * @param dto 频道消息 DTO
  40 + * @param conversationType 会话类型,参见 ImConversationTypeEnum 枚举类
  41 + * @param contentType 内容类型,参见 ImContentTypeEnum 枚举类
  42 + * @param payload 通知 payload
79 43 */
80   - void broadcastChannelMessageAsync(ImChannelMessageDTO dto);
  44 + void broadcastNotificationAsync(Integer conversationType, Integer contentType, Object payload);
81 45  
82 46 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImpl.java
... ... @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.im.service.websocket;
2 2  
3 3 import cn.hutool.extra.spring.SpringUtil;
4 4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO;
6   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
7   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
  5 +import cn.iocoder.yudao.module.im.service.websocket.notification.ImNotificationWebSocketDTO;
8 6 import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
9 7 import jakarta.annotation.Resource;
10 8 import lombok.extern.slf4j.Slf4j;
... ... @@ -36,83 +34,51 @@ public class ImWebSocketServiceImpl implements ImWebSocketService {
36 34 private WebSocketSenderApi webSocketSenderApi;
37 35  
38 36 @Override
39   - public void sendPrivateMessageAsync(Collection<Long> userIds, ImPrivateMessageDTO dto) {
40   - // 说明:通过 executeAfterTransaction 保证事务提交后再推送,避免客户端收到消息后查询数据库时事务尚未提交
41   - // 通过 getSelf() 获取 Spring 代理对象调用 @Async 方法,确保异步 AOP 生效(直接 this 调用会绕过代理)
42   - executeAfterTransaction(() -> getSelf().doSendPrivateMessage(userIds, dto));
  37 + public void sendNotificationAsync(Collection<Long> userIds, Integer conversationType, Integer contentType,
  38 + Object payload) {
  39 + ImNotificationWebSocketDTO notification = buildNotification(conversationType, contentType, payload);
  40 + executeAfterTransaction(() -> getSelf().doSendNotification(userIds, notification));
43 41 }
44 42  
45 43 @Override
46   - public void sendGroupMessageAsync(Collection<Long> userIds, ImGroupMessageDTO dto) {
47   - executeAfterTransaction(() -> getSelf().doSendGroupMessage(userIds, dto));
  44 + public void broadcastNotificationAsync(Integer conversationType, Integer contentType, Object payload) {
  45 + ImNotificationWebSocketDTO notification = buildNotification(conversationType, contentType, payload);
  46 + executeAfterTransaction(() -> getSelf().doBroadcastNotification(notification));
48 47 }
49 48  
50   - @Override
51   - public void sendChannelMessageAsync(Collection<Long> userIds, ImChannelMessageDTO dto) {
52   - executeAfterTransaction(() -> getSelf().doSendChannelMessage(userIds, dto));
53   - }
54   -
55   - @Override
56   - public void broadcastChannelMessageAsync(ImChannelMessageDTO dto) {
57   - executeAfterTransaction(() -> getSelf().doBroadcastChannelMessage(dto));
58   - }
59   -
60   - /**
61   - * 异步发送私聊 WebSocket 消息;多收件人共享同一 dto,避免按收件人重复注册 afterCommit 回调
62   - */
63   - @Async
64   - public void doSendPrivateMessage(Collection<Long> userIds, ImPrivateMessageDTO dto) {
65   - for (Long userId : getDistinctUserIds(userIds)) {
66   - try {
67   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
68   - ImPrivateMessageDTO.TYPE, dto);
69   - } catch (Exception e) {
70   - log.error("[doSendPrivateMessage][userId({}) dto({}) 发送失败]", userId, dto, e);
71   - }
72   - }
73   - }
74   -
75   - /**
76   - * 异步发送群聊 WebSocket 消息
77   - */
78   - @Async
79   - public void doSendGroupMessage(Collection<Long> userIds, ImGroupMessageDTO dto) {
80   - for (Long userId : getDistinctUserIds(userIds)) {
81   - try {
82   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
83   - ImGroupMessageDTO.TYPE, dto);
84   - } catch (Exception e) {
85   - log.error("[doSendGroupMessage][userId({}) dto({}) 发送失败]", userId, dto, e);
86   - }
87   - }
  49 + private static ImNotificationWebSocketDTO buildNotification(Integer conversationType, Integer contentType,
  50 + Object payload) {
  51 + return new ImNotificationWebSocketDTO()
  52 + .setConversationType(conversationType)
  53 + .setContentType(contentType)
  54 + .setPayload(payload);
88 55 }
89 56  
90 57 /**
91   - * 异步发送频道 WebSocket 消息
  58 + * 异步发送 WebSocket 通知
92 59 */
93 60 @Async
94   - public void doSendChannelMessage(Collection<Long> userIds, ImChannelMessageDTO dto) {
  61 + public void doSendNotification(Collection<Long> userIds, ImNotificationWebSocketDTO notification) {
95 62 for (Long userId : getDistinctUserIds(userIds)) {
96 63 try {
97 64 webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
98   - ImChannelMessageDTO.TYPE, dto);
  65 + ImNotificationWebSocketDTO.TYPE, notification);
99 66 } catch (Exception e) {
100   - log.error("[doSendChannelMessage][userId({}) dto({}) 发送失败]", userId, dto, e);
  67 + log.error("[doSendNotification][userId({}) notification({}) 发送失败]", userId, notification, e);
101 68 }
102 69 }
103 70 }
104 71  
105 72 /**
106   - * 异步广播频道 WebSocket 消息给当前所有在线管理端用户;
107   - * 依赖 infra WebSocketSenderApi 按 UserType 广播能力,离线用户由客户端上线 pull 兜底
  73 + * 异步广播 WebSocket 通知
108 74 */
109 75 @Async
110   - public void doBroadcastChannelMessage(ImChannelMessageDTO dto) {
  76 + public void doBroadcastNotification(ImNotificationWebSocketDTO notification) {
111 77 try {
112 78 webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(),
113   - ImChannelMessageDTO.TYPE, dto);
  79 + ImNotificationWebSocketDTO.TYPE, notification);
114 80 } catch (Exception e) {
115   - log.error("[doBroadcastChannelMessage][dto({}) 广播失败]", dto, e);
  81 + log.error("[doBroadcastNotification][notification({}) 广播失败]", notification, e);
116 82 }
117 83 }
118 84  
... ... @@ -121,19 +87,15 @@ public class ImWebSocketServiceImpl implements ImWebSocketService {
121 87 }
122 88  
123 89 /**
124   - * 事务感知的任务调度:
125   - * - 有事务:注册 afterCommit 回调,事务提交后再执行,防止客户端拿到消息去查库时数据还没落盘
126   - * - 无事务:直接执行(如非 @Transactional 方法中的调用)
  90 + * 事务感知的任务调度
127 91 *
128   - * @param task 待执行的推送任务(内部通过 getSelf() 走 @Async 异步执行)
  92 + * @param task 待执行的推送任务
129 93 */
130 94 private void executeAfterTransaction(Runnable task) {
131   - // 情况一:没有事务,直接执行
132 95 if (!TransactionSynchronizationManager.isSynchronizationActive()) {
133 96 task.run();
134 97 return;
135 98 }
136   - // 情况二:有事务,注册 afterCommit 事件,在事务提交后执行
137 99 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
138 100  
139 101 @Override
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImPrivateMessageDTO.java deleted
1   -package cn.iocoder.yudao.module.im.service.websocket.dto;
2   -
3   -import cn.hutool.core.lang.Assert;
4   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5   -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
7   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
8   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.BaseFriendNotification;
9   -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.BaseGroupNotification;
10   -import lombok.Data;
11   -import lombok.experimental.Accessors;
12   -
13   -import java.time.LocalDateTime;
14   -
15   -/**
16   - * IM 私聊消息 WebSocket 统一推送 DTO
17   - * <p>
18   - * 发送、已读、回执、撤回都通过 {@link #type} 字段区分,
19   - * 并统一复用 {@link #id} 字段表达目标消息或已读位置。
20   - *
21   - * @author 芋道源码
22   - */
23   -@Data
24   -@Accessors(chain = true)
25   -public class ImPrivateMessageDTO {
26   -
27   - public static final String TYPE = "im-private-message";
28   -
29   - /**
30   - * 消息编号
31   - * <p>
32   - * 普通消息:当前消息 id
33   - * READ:已读位置(我已读到这条消息)
34   - * RECEIPT:已读位置(对方已读到这条消息)
35   - * RECALL:被撤回的原消息 id
36   - */
37   - private Long id;
38   - /**
39   - * 客户端消息编号
40   - */
41   - private String clientMessageId;
42   - /**
43   - * 发送人编号
44   - */
45   - private Long senderId;
46   - /**
47   - * 接收人编号
48   - */
49   - private Long receiverId;
50   - /**
51   - * 消息类型
52   - */
53   - private Integer type;
54   - /**
55   - * 消息内容
56   - */
57   - private String content;
58   - /**
59   - * 消息状态
60   - */
61   - private Integer status;
62   - /**
63   - * 发送时间
64   - */
65   - private LocalDateTime sendTime;
66   -
67   - // ========== 静态工厂方法 ==========
68   -
69   - /**
70   - * 构建发送消息 DTO
71   - *
72   - * @param message 私聊消息 DO
73   - * @return 私聊 DTO
74   - */
75   - public static ImPrivateMessageDTO ofSend(ImPrivateMessageDO message) {
76   - return BeanUtils.toBean(message, ImPrivateMessageDTO.class);
77   - }
78   -
79   - /**
80   - * 构建已读同步 DTO(多端同步:通知自己的其他终端"我已经读了某个会话")
81   - *
82   - * @param senderId 当前用户编号
83   - * @param receiverId 对方用户编号
84   - * @param readId 已读位置(最大已读消息编号)
85   - * @return 私聊 DTO
86   - */
87   - public static ImPrivateMessageDTO ofRead(Long senderId, Long receiverId, Long readId) {
88   - return new ImPrivateMessageDTO()
89   - .setId(readId).setType(ImMessageTypeEnum.READ.getType())
90   - .setSenderId(senderId).setReceiverId(receiverId);
91   - }
92   -
93   - /**
94   - * 构建已读回执 DTO(通知对方"我已读了你的消息")
95   - *
96   - * @param senderId 已读方的用户编号
97   - * @param receiverId 对方用户编号
98   - * @param readId 已读位置(最大已读消息编号)
99   - * @return 私聊 DTO
100   - */
101   - public static ImPrivateMessageDTO ofReceipt(Long senderId, Long receiverId, Long readId) {
102   - return new ImPrivateMessageDTO()
103   - .setId(readId).setType(ImMessageTypeEnum.RECEIPT.getType())
104   - .setSenderId(senderId).setReceiverId(receiverId);
105   - }
106   -
107   - // ==================== 好友变更相关 ====================
108   -
109   - /**
110   - * 构建好友通知推送 DTO(统一入口)
111   - *
112   - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 FRIEND_* 段
113   - * @param operatorUserId 操作人用户编号;同时作为帧的 senderId 用于定位接收端 friendUserId
114   - * @param receiverUserId 推送目标用户编号
115   - * @param payload 好友通知 payload(继承 {@link BaseFriendNotification})
116   - * @return 私聊 DTO
117   - */
118   - public static ImPrivateMessageDTO ofFriendNotification(Integer type, Long operatorUserId,
119   - Long receiverUserId, BaseFriendNotification payload) {
120   - validateNotification(type, payload, ImMessageTypeEnum.isFriendNotification(type));
121   - return new ImPrivateMessageDTO().setType(type)
122   - .setSenderId(operatorUserId).setReceiverId(receiverUserId)
123   - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now());
124   - }
125   -
126   - // ==================== 群定向私聊通知 ====================
127   -
128   - // TODO DONE @AI:群申请定向通知继续走私聊通道
129   - /**
130   - * 构建群通知推送 DTO(走私聊通道定向推送,不入群消息流)
131   - * <p>
132   - * 用于 GROUP_REQUEST_RECEIVED / GROUP_REQUEST_APPROVED / GROUP_REQUEST_REJECTED 段位;
133   - * 与 {@link cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO} 走 sendGroupMessage 群广播路径不同
134   - *
135   - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 GROUP_REQUEST_* 段
136   - * @param operatorUserId 操作人用户编号;同时作为帧的 senderId
137   - * @param receiverUserId 推送目标用户编号
138   - * @param payload 群事件 payload(继承 {@link BaseGroupNotification})
139   - * @return 私聊 DTO
140   - */
141   - public static ImPrivateMessageDTO ofGroupNotification(Integer type, Long operatorUserId,
142   - Long receiverUserId, BaseGroupNotification payload) {
143   - validateNotification(type, payload, ImMessageTypeEnum.isGroupRequestNotification(type));
144   - return new ImPrivateMessageDTO().setType(type)
145   - .setSenderId(operatorUserId).setReceiverId(receiverUserId)
146   - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now());
147   - }
148   -
149   - // ==================== 实时通话信令 ====================
150   -
151   - /**
152   - * 构建通话信令推送 DTO(走私聊通道仅推参与方,不入消息流)
153   - * <p>
154   - * 用于 RTC_CALL(INVITE / REJECT 等)/ RTC_PARTICIPANT_CONNECTED / RTC_PARTICIPANT_DISCONNECTED
155   - *
156   - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 RTC_* 段
157   - * @param senderId 发送人编号;INVITE 时为发起人,REJECT 时为拒绝者,参与者事件时为加入 / 离开者
158   - * @param receiverUserId 推送目标用户编号
159   - * @param payload 通话事件 payload(任意 RTC 通知 DTO)
160   - * @return 私聊 DTO
161   - */
162   - public static ImPrivateMessageDTO ofRtcNotification(Integer type, Long senderId,
163   - Long receiverUserId, Object payload) {
164   - validateNotification(type, payload, ImMessageTypeEnum.isRtcNotification(type));
165   - return new ImPrivateMessageDTO().setType(type)
166   - .setSenderId(senderId).setReceiverId(receiverUserId)
167   - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now());
168   - }
169   -
170   - private static void validateNotification(Integer type, Object payload, boolean supported) {
171   - Assert.notNull(type, "消息类型不能为空");
172   - Assert.notNull(payload, "消息内容不能为空");
173   - Assert.isTrue(supported, "消息类型不匹配 type={}", type);
174   - }
175   -
176   -}
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/ImNotificationWebSocketDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification;
  2 +
  3 +import lombok.Data;
  4 +import lombok.experimental.Accessors;
  5 +
  6 +/**
  7 + * IM WebSocket 在线通知外壳
  8 + * <p>
  9 + * conversationType 定位会话维度;contentType 定位业务内容;payload 承载对应通知对象。
  10 + * 会进入聊天流的私聊、群聊、频道事件走 message 子包;不进入聊天流的好友、加群申请、通话信令走 NONE 会话。
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Data
  15 +@Accessors(chain = true)
  16 +public class ImNotificationWebSocketDTO {
  17 +
  18 + public static final String TYPE = "im-notification";
  19 +
  20 + /**
  21 + * 会话类型,参见 ImConversationTypeEnum 枚举类
  22 + */
  23 + private Integer conversationType;
  24 + /**
  25 + * 内容类型,参见 ImContentTypeEnum 枚举类
  26 + */
  27 + private Integer contentType;
  28 + /**
  29 + * 负载数据
  30 + */
  31 + private Object payload;
  32 +
  33 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/BaseFriendNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/BaseFriendNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendAddNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendAddNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendBlockNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendBlockNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendDeleteNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendDeleteNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendInfoUpdatedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendInfoUpdatedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestApprovedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestApprovedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestRejectedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestRejectedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUnblockNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUnblockNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUpdateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUpdateNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.friend;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/BaseGroupNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/BaseGroupNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.group;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminAddNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminAddNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.group;
2 2  
3 3 /**
4 4 * 添加管理员事件通知(memberUserIds 为被设管理员的成员)
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminRemoveNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminRemoveNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.group;
2 2  
3 3 /**
4 4 * 撤销管理员事件通知(memberUserIds 为被撤销管理员的成员)
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupBannedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupBannedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.group;
2 2  
3 3 import lombok.Data;
4 4  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCancelMutedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCancelMutedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.group;
2 2  
3 3 import lombok.Data;
4 4 import lombok.EqualsAndHashCode;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCreateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCreateNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.group;
2 2  
3 3 /**
4 4 * 群创建事件通知(memberUserIds 含创建者 + 初始邀请成员)
... ...