Commit 3dd717939354799e4f3e97c7df8512209effa368

Authored by YunaiV
1 parent 210a8d5a

refactor: 扁平化 IM WebSocket 通知推送 API

- 将 WebSocket 推送入口统一为 userId/userIds + conversationType + contentType + payload
- 移除业务侧 ImNotificationWebSocketDTO 构造和无会话专用发送入口
- 收敛私聊、群聊、频道、好友、加群申请、RTC 通知调用路径
- 精简 ImNotificationWebSocketDTO,仅保留统一外壳字段
- 保留群消息 payload 的 receiptStatus、readCount、receiverUserIds
- 更新相关单元测试,覆盖群消息通知 payload 字段
Showing 101 changed files with 576 additions and 614 deletions

Too many changes.

To preserve performance only 100 of 101 files are displayed.

sql/mysql/ruoyi-vue-pro.sql
... ... @@ -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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_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_message_type', 0, 'warning', '', NULL, 'admin', '2026-05-05 13:26:53', 'admin', '2026-05-05 13:26:53', 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,9 +1474,9 @@ 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_message_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_message_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_message_type', 0, 'success', '', '频道运营推送的图文卡片消息', '1', '2026-05-18 13:14:34', '1', '2026-05-18 13:14:34', 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 1482 COMMIT;
... ... @@ -1689,7 +1689,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
1689 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);
1690 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);
1691 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');
1692   -INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2200, 'IM 消息类型', 'im_message_type', 0, '对应 ImMessageTypeEnum', 'admin', '2026-04-30 11:35:07', 'admin', '2026-04-30 11:35:07', 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 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);
1694 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);
1695 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);
... ...
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;
... ...
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;
... ...
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/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/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,7 +26,7 @@ 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\":\"你好\"}")
... ... @@ -42,7 +42,7 @@ public class ImPrivateMessageSendReqVO {
42 42 @AssertTrue(message = "消息类型不允许")
43 43 @JsonIgnore
44 44 public boolean isTypeNormal() {
45   - return type == null || ImMessageTypeEnum.validate(type).isNormal();
  45 + return type == null || ImContentTypeEnum.validate(type).isNormal();
46 46 }
47 47  
48 48 }
... ...
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
... ... @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
5 5 import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
6 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 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImPrivateMessageDO.java
... ... @@ -3,7 +3,7 @@ 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.module.im.enums.message.ImMessageReceiptStatusEnum;
5 5 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
6   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  6 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
7 7 import com.baomidou.mybatisplus.annotation.KeySequence;
8 8 import com.baomidou.mybatisplus.annotation.TableId;
9 9 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -50,7 +50,7 @@ public class ImPrivateMessageDO extends BaseDO {
50 50 /**
51 51 * 消息类型
52 52 * <p>
53   - * 枚举 {@link ImMessageTypeEnum}
  53 + * 枚举 {@link ImContentTypeEnum}
54 54 */
55 55 private Integer type;
56 56 /**
... ...
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/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/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 /**
... ... @@ -335,7 +335,7 @@ public enum ImMessageTypeEnum implements ArrayValuable&lt;Integer&gt; {
335 335 */
336 336 GROUP_BANNED(1533, "群封禁变更", true, false);
337 337  
338   - 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);
339 339  
340 340 private static final Set<Integer> FRIEND_NOTIFICATION_TYPES = CollUtil.newHashSet(
341 341 FRIEND_REQUEST_APPROVED.type,
... ... @@ -392,8 +392,8 @@ public enum ImMessageTypeEnum implements ArrayValuable&lt;Integer&gt; {
392 392 * @param type 消息类型
393 393 * @return 枚举实例
394 394 */
395   - public static ImMessageTypeEnum validate(Integer type) {
396   - 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());
397 397 Assert.notNull(result, "未注册的消息类型 type={}", type);
398 398 return result;
399 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/service/friend/ImFriendRequestServiceImpl.java
... ... @@ -17,10 +17,9 @@ import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum;
17 17 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
18 18 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
19 19 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;
  20 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestApprovedNotification;
  21 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestNotification;
  22 +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestRejectedNotification;
24 23 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
25 24 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
26 25 import jakarta.annotation.Resource;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java
... ... @@ -17,11 +17,10 @@ import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
17 17 import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService;
18 18 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
19 19 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;
  20 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.BaseGroupNotification;
  21 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestApprovedNotification;
  22 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestReceivedNotification;
  23 +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestRejectedNotification;
25 24 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
26 25 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
27 26 import jakarta.annotation.Resource;
... ... @@ -97,7 +96,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
97 96 // 3. 情况二:群开启了审批,创建或复用一条主动申请记录
98 97 ImGroupRequestDO request = createOrResetApplyRequest(groupId, userId, reqVO);
99 98  
100   - // 4. 1503 私聊定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像
  99 + // 4. 1503 定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像
101 100 AdminUserRespDTO applyUser = adminUserApi.getUser(userId);
102 101 GroupRequestReceivedNotification payload = buildRequestNotification(group, request, applyUser);
103 102 for (Long receiverUserId : getGroupMemberListByOwnerAndAdminUserIds(group)) {
... ... @@ -139,12 +138,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
139 138 groupMemberService.addGroupMember(request.getGroupId(), request.getUserId(),
140 139 ImGroupMemberRoleEnum.NORMAL.getRole(), request.getAddSource(), request.getInviterUserId());
141 140  
142   - // 5.1 1505 私聊推送给申请人 + 群主 + 全部管理员(每端单推)
  141 + // 5.1 1505 定向推送给申请人 + 群主 + 全部管理员(每端单推)
143 142 GroupRequestApprovedNotification payload = (GroupRequestApprovedNotification) new GroupRequestApprovedNotification()
144 143 .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId())
145 144 .setOperatorUserId(userId);
146 145 broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload,
147   - ImMessageTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId);
  146 + ImContentTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId);
148 147 // 5.2 群事件:主动申请 → 1510 自由进群;被邀请 → 1509 成员加入
149 148 if (request.getInviterUserId() == null) {
150 149 groupMessageService.sendGroupMessage(userId,
... ... @@ -174,12 +173,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
174 173 throw exception(GROUP_REQUEST_HANDLED);
175 174 }
176 175  
177   - // 3. 1506 私聊推送给申请人 + 群主 + 全部管理员
  176 + // 3. 1506 定向推送给申请人 + 群主 + 全部管理员
178 177 GroupRequestRejectedNotification payload = (GroupRequestRejectedNotification) new GroupRequestRejectedNotification()
179 178 .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId())
180 179 .setHandleContent(handleContent).setOperatorUserId(userId);
181 180 broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload,
182   - ImMessageTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId);
  181 + ImContentTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId);
183 182 }
184 183  
185 184 @Override
... ... @@ -395,7 +394,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService {
395 394 }
396 395  
397 396 /**
398   - * 1505 / 1506 受众:申请人 + 群主 + 全部管理员;每端单独推一帧,前端按 receiver 是否申请人区分文案
  397 + * 1505 / 1506 受众:申请人 + 群主 + 全部管理员
399 398 */
400 399 private void broadcastToOwnerAdminsAndApplicant(Long groupId, Long applicantUserId, BaseGroupNotification payload,
401 400 Integer messageType, Long operatorUserId) {
... ...
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;
... ... @@ -436,7 +436,7 @@ public class ImGroupServiceImpl implements ImGroupService {
436 436 if (message == null || ObjUtil.notEqual(message.getGroupId(), groupId)) {
437 437 throw exception(MESSAGE_NOT_IN_GROUP);
438 438 }
439   - if (!ImMessageTypeEnum.validate(message.getType()).isNormal()
  439 + if (!ImContentTypeEnum.validate(message.getType()).isNormal()
440 440 || ImMessageStatusEnum.RECALL.getStatus().equals(message.getStatus())) {
441 441 throw exception(MESSAGE_NOT_IN_GROUP);
442 442 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageServiceImpl.java
... ... @@ -13,12 +13,13 @@ import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelMaterialDO;
13 13 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO;
14 14 import cn.iocoder.yudao.module.im.dal.mysql.message.ImChannelMessageMapper;
15 15 import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
16   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  16 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
17 17 import cn.iocoder.yudao.module.im.service.channel.ImChannelMaterialService;
18 18 import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
19 19 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
20   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO;
21   -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;
22 23 import jakarta.annotation.Resource;
23 24 import org.springframework.scheduling.annotation.Async;
24 25 import org.springframework.stereotype.Service;
... ... @@ -116,7 +117,7 @@ public class ImChannelMessageServiceImpl implements ImChannelMessageService {
116 117 String payloadJson = JsonUtils.toJsonString(payload);
117 118 // 2.2 落库 1 行 message;reqVO 同名字段(materialId / receiverUserIds)自动拷贝,剩余字段补 set
118 119 ImChannelMessageDO message = BeanUtils.toBean(reqVO, ImChannelMessageDO.class).setChannelId(material.getChannelId())
119   - .setType(ImMessageTypeEnum.MATERIAL.getType()).setContent(payloadJson).setSendTime(LocalDateTime.now());
  120 + .setType(ImContentTypeEnum.MATERIAL.getType()).setContent(payloadJson).setSendTime(LocalDateTime.now());
120 121 channelMessageMapper.insert(message);
121 122  
122 123 // 3. 异步推 WebSocket:指定用户走点对点;全员(receiverUserIds 为空)走广播
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
... ... @@ -20,7 +20,7 @@ import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
20 20 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
21 21 import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
22 22 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
23   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  23 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
24 24 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
25 25 import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
26 26 import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
... ... @@ -28,9 +28,11 @@ 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;
... ... @@ -93,7 +95,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
93 95 // 1.4 禁言校验
94 96 validateMuteStatus(group, senderMember);
95 97 // 1.5 文本消息敏感词过滤
96   - if (ImMessageTypeEnum.TEXT.getType().equals(reqVO.getType())) {
  98 + if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) {
97 99 sensitiveWordService.validateText(reqVO.getContent());
98 100 }
99 101  
... ... @@ -142,7 +144,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
142 144 .setAtUserIds(dto.getAtUserIds()).setReceiverUserIds(new ArrayList<>(receiverUserIds))
143 145 .setReceiptStatus(resolveReceiptStatus(dto.getReceipt()));
144 146 // 1.3 按 type.persistent 决定是否入库
145   - if (ImMessageTypeEnum.validate(dto.getType()).isPersistent()) {
  147 + if (ImContentTypeEnum.validate(dto.getType()).isPersistent()) {
146 148 groupMessageMapper.insert(message);
147 149 }
148 150  
... ... @@ -181,7 +183,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
181 183  
182 184 // 3. 发送撤回事件
183 185 return sendGroupMessage(userId, new ImGroupMessageSendDTO().setGroupId(message.getGroupId())
184   - .setType(ImMessageTypeEnum.RECALL.getType())
  186 + .setType(ImContentTypeEnum.RECALL.getType())
185 187 .setReceiverUserIds(message.getReceiverUserIds())
186 188 .setContent(new RecallMessage().setMessageId(messageId)));
187 189 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
... ... @@ -15,16 +15,18 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
15 15 import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
16 16 import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
17 17 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
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.framework.config.ImProperties;
20 20 import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
21 21 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
22 22 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO;
23 23 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
24 24 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
25   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
26   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage;
27   -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;
28 30 import cn.iocoder.yudao.module.im.util.ImMessageUtils;
29 31 import jakarta.annotation.Resource;
30 32 import lombok.extern.slf4j.Slf4j;
... ... @@ -80,7 +82,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
80 82 // 1.3 好友校验
81 83 friendService.validateFriend(senderId, reqVO.getReceiverId());
82 84 // 1.4 文本消息敏感词过滤
83   - if (ImMessageTypeEnum.TEXT.getType().equals(reqVO.getType())) {
  85 + if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) {
84 86 sensitiveWordService.validateText(reqVO.getContent());
85 87 }
86 88  
... ... @@ -123,7 +125,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
123 125 // 1.3 决定是否持久化:dto.persistent 优先;为 null 时按 type 默认
124 126 boolean persistent = dto.getPersistent() != null
125 127 ? dto.getPersistent()
126   - : ImMessageTypeEnum.validate(dto.getType()).isPersistent();
  128 + : ImContentTypeEnum.validate(dto.getType()).isPersistent();
127 129 if (persistent) {
128 130 privateMessageMapper.insert(message);
129 131 }
... ... @@ -177,7 +179,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
177 179  
178 180 // 3. 发送撤回事件
179 181 return sendPrivateMessage(userId, new ImPrivateMessageSendDTO().setReceiverId(message.getReceiverId())
180   - .setType(ImMessageTypeEnum.RECALL.getType()).setContent(new RecallMessage().setMessageId(messageId)));
  182 + .setType(ImContentTypeEnum.RECALL.getType()).setContent(new RecallMessage().setMessageId(messageId)));
181 183 }
182 184  
183 185 /**
... ...
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,14 +53,14 @@ 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 66 public static ImGroupMessageSendDTO ofGroupInfoUpdate(Long groupId, Long operatorUserId, String oldAvatar, String newAvatar) {
... ... @@ -69,14 +69,14 @@ public class ImGroupMessageSendDTO {
69 69 notification.setOldAvatar(oldAvatar);
70 70 notification.setNewAvatar(newAvatar);
71 71 return new ImGroupMessageSendDTO().setGroupId(groupId)
72   - .setType(ImMessageTypeEnum.GROUP_INFO_UPDATE.getType()).setContent(notification);
  72 + .setType(ImContentTypeEnum.GROUP_INFO_UPDATE.getType()).setContent(notification);
73 73 }
74 74  
75 75 public static ImGroupMessageSendDTO ofGroupMemberQuit(Long groupId, Long operatorUserId) {
76 76 GroupMemberQuitNotification notification = new GroupMemberQuitNotification();
77 77 notification.setOperatorUserId(operatorUserId);
78 78 return new ImGroupMessageSendDTO().setGroupId(groupId)
79   - .setType(ImMessageTypeEnum.GROUP_MEMBER_QUIT.getType()).setContent(notification);
  79 + .setType(ImContentTypeEnum.GROUP_MEMBER_QUIT.getType()).setContent(notification);
80 80 }
81 81  
82 82 public static ImGroupMessageSendDTO ofGroupOwnerTransfer(Long groupId, Long operatorUserId, Long newOwnerUserId) {
... ... @@ -84,7 +84,7 @@ public class ImGroupMessageSendDTO {
84 84 notification.setOperatorUserId(operatorUserId);
85 85 notification.setNewOwnerUserId(newOwnerUserId);
86 86 return new ImGroupMessageSendDTO().setGroupId(groupId)
87   - .setType(ImMessageTypeEnum.GROUP_OWNER_TRANSFER.getType()).setContent(notification);
  87 + .setType(ImContentTypeEnum.GROUP_OWNER_TRANSFER.getType()).setContent(notification);
88 88 }
89 89  
90 90 public static ImGroupMessageSendDTO ofGroupMemberKick(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -92,7 +92,7 @@ public class ImGroupMessageSendDTO {
92 92 notification.setOperatorUserId(operatorUserId);
93 93 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
94 94 return new ImGroupMessageSendDTO().setGroupId(groupId)
95   - .setType(ImMessageTypeEnum.GROUP_MEMBER_KICK.getType()).setContent(notification);
  95 + .setType(ImContentTypeEnum.GROUP_MEMBER_KICK.getType()).setContent(notification);
96 96 }
97 97  
98 98 public static ImGroupMessageSendDTO ofGroupMemberInvite(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -100,7 +100,7 @@ public class ImGroupMessageSendDTO {
100 100 notification.setOperatorUserId(operatorUserId);
101 101 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
102 102 return new ImGroupMessageSendDTO().setGroupId(groupId)
103   - .setType(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType()).setContent(notification);
  103 + .setType(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType()).setContent(notification);
104 104 }
105 105  
106 106 public static ImGroupMessageSendDTO ofGroupMemberEnter(Long groupId, Long entrantUserId, Integer addSource) {
... ... @@ -109,14 +109,14 @@ public class ImGroupMessageSendDTO {
109 109 notification.setEntrantUserId(entrantUserId);
110 110 notification.setAddSource(addSource);
111 111 return new ImGroupMessageSendDTO().setGroupId(groupId)
112   - .setType(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType()).setContent(notification);
  112 + .setType(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType()).setContent(notification);
113 113 }
114 114  
115 115 public static ImGroupMessageSendDTO ofGroupDissolve(Long groupId, Long operatorUserId) {
116 116 GroupDissolveNotification notification = new GroupDissolveNotification();
117 117 notification.setOperatorUserId(operatorUserId);
118 118 return new ImGroupMessageSendDTO().setGroupId(groupId)
119   - .setType(ImMessageTypeEnum.GROUP_DISSOLVE.getType()).setContent(notification);
  119 + .setType(ImContentTypeEnum.GROUP_DISSOLVE.getType()).setContent(notification);
120 120 }
121 121  
122 122 public static ImGroupMessageSendDTO ofGroupMemberNicknameUpdate(Long groupId, Long operatorUserId, String displayUserName) {
... ... @@ -124,7 +124,7 @@ public class ImGroupMessageSendDTO {
124 124 notification.setOperatorUserId(operatorUserId);
125 125 notification.setDisplayUserName(displayUserName);
126 126 return new ImGroupMessageSendDTO().setGroupId(groupId)
127   - .setType(ImMessageTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()).setContent(notification);
  127 + .setType(ImContentTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()).setContent(notification);
128 128 }
129 129  
130 130 public static ImGroupMessageSendDTO ofGroupAdminAdd(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -132,7 +132,7 @@ public class ImGroupMessageSendDTO {
132 132 notification.setOperatorUserId(operatorUserId);
133 133 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
134 134 return new ImGroupMessageSendDTO().setGroupId(groupId)
135   - .setType(ImMessageTypeEnum.GROUP_ADMIN_ADD.getType()).setContent(notification);
  135 + .setType(ImContentTypeEnum.GROUP_ADMIN_ADD.getType()).setContent(notification);
136 136 }
137 137  
138 138 public static ImGroupMessageSendDTO ofGroupAdminRemove(Long groupId, Long operatorUserId, Collection<Long> memberUserIds) {
... ... @@ -140,7 +140,7 @@ public class ImGroupMessageSendDTO {
140 140 notification.setOperatorUserId(operatorUserId);
141 141 notification.setMemberUserIds(new ArrayList<>(memberUserIds));
142 142 return new ImGroupMessageSendDTO().setGroupId(groupId)
143   - .setType(ImMessageTypeEnum.GROUP_ADMIN_REMOVE.getType()).setContent(notification);
  143 + .setType(ImContentTypeEnum.GROUP_ADMIN_REMOVE.getType()).setContent(notification);
144 144 }
145 145  
146 146 public static ImGroupMessageSendDTO ofGroupNoticeUpdate(Long groupId, Long operatorUserId, String oldNotice, String newNotice) {
... ... @@ -148,7 +148,7 @@ public class ImGroupMessageSendDTO {
148 148 notification.setOperatorUserId(operatorUserId);
149 149 notification.setOldNotice(oldNotice).setNewNotice(newNotice);
150 150 return new ImGroupMessageSendDTO().setGroupId(groupId)
151   - .setType(ImMessageTypeEnum.GROUP_NOTICE_UPDATE.getType()).setContent(notification);
  151 + .setType(ImContentTypeEnum.GROUP_NOTICE_UPDATE.getType()).setContent(notification);
152 152 }
153 153  
154 154 public static ImGroupMessageSendDTO ofGroupNameUpdate(Long groupId, Long operatorUserId, String oldName, String newName) {
... ... @@ -156,7 +156,7 @@ public class ImGroupMessageSendDTO {
156 156 notification.setOperatorUserId(operatorUserId);
157 157 notification.setOldName(oldName).setNewName(newName);
158 158 return new ImGroupMessageSendDTO().setGroupId(groupId)
159   - .setType(ImMessageTypeEnum.GROUP_NAME_UPDATE.getType()).setContent(notification);
  159 + .setType(ImContentTypeEnum.GROUP_NAME_UPDATE.getType()).setContent(notification);
160 160 }
161 161  
162 162 public static ImGroupMessageSendDTO ofGroupMemberSettingUpdate(Long groupId, Long operatorUserId, Boolean silent, String groupRemark) {
... ... @@ -164,7 +164,7 @@ public class ImGroupMessageSendDTO {
164 164 notification.setOperatorUserId(operatorUserId);
165 165 notification.setSilent(silent).setGroupRemark(groupRemark);
166 166 return new ImGroupMessageSendDTO().setGroupId(groupId)
167   - .setType(ImMessageTypeEnum.GROUP_MEMBER_SETTING_UPDATE.getType()).setContent(notification);
  167 + .setType(ImContentTypeEnum.GROUP_MEMBER_SETTING_UPDATE.getType()).setContent(notification);
168 168 }
169 169  
170 170 public static ImGroupMessageSendDTO ofGroupMessagePin(Long groupId, Long operatorUserId, ImGroupMessageDO message) {
... ... @@ -176,7 +176,7 @@ public class ImGroupMessageSendDTO {
176 176 notification.setOperatorUserId(operatorUserId);
177 177 notification.setMessageId(message.getId()).setMessage(pinnedMessage);
178 178 return new ImGroupMessageSendDTO().setGroupId(groupId)
179   - .setType(ImMessageTypeEnum.GROUP_MESSAGE_PIN.getType()).setContent(notification);
  179 + .setType(ImContentTypeEnum.GROUP_MESSAGE_PIN.getType()).setContent(notification);
180 180 }
181 181  
182 182 public static ImGroupMessageSendDTO ofGroupMessageUnpin(Long groupId, Long operatorUserId, Long messageId) {
... ... @@ -184,7 +184,7 @@ public class ImGroupMessageSendDTO {
184 184 notification.setOperatorUserId(operatorUserId);
185 185 notification.setMessageId(messageId);
186 186 return new ImGroupMessageSendDTO().setGroupId(groupId)
187   - .setType(ImMessageTypeEnum.GROUP_MESSAGE_UNPIN.getType()).setContent(notification);
  187 + .setType(ImContentTypeEnum.GROUP_MESSAGE_UNPIN.getType()).setContent(notification);
188 188 }
189 189  
190 190 public static ImGroupMessageSendDTO ofGroupMemberMuted(Long groupId, Long operatorUserId,
... ... @@ -195,7 +195,7 @@ public class ImGroupMessageSendDTO {
195 195 notification.setMutedUserId(mutedUserId);
196 196 notification.setMuteEndTime(muteEndTime);
197 197 return new ImGroupMessageSendDTO().setGroupId(groupId)
198   - .setType(ImMessageTypeEnum.GROUP_MEMBER_MUTED.getType()).setContent(notification);
  198 + .setType(ImContentTypeEnum.GROUP_MEMBER_MUTED.getType()).setContent(notification);
199 199 }
200 200  
201 201 public static ImGroupMessageSendDTO ofGroupMemberCancelMuted(Long groupId, Long operatorUserId, Long mutedUserId) {
... ... @@ -203,21 +203,21 @@ public class ImGroupMessageSendDTO {
203 203 notification.setOperatorUserId(operatorUserId);
204 204 notification.setMutedUserId(mutedUserId);
205 205 return new ImGroupMessageSendDTO().setGroupId(groupId)
206   - .setType(ImMessageTypeEnum.GROUP_MEMBER_CANCEL_MUTED.getType()).setContent(notification);
  206 + .setType(ImContentTypeEnum.GROUP_MEMBER_CANCEL_MUTED.getType()).setContent(notification);
207 207 }
208 208  
209 209 public static ImGroupMessageSendDTO ofGroupMuted(Long groupId, Long operatorUserId) {
210 210 GroupMutedNotification notification = new GroupMutedNotification();
211 211 notification.setOperatorUserId(operatorUserId);
212 212 return new ImGroupMessageSendDTO().setGroupId(groupId)
213   - .setType(ImMessageTypeEnum.GROUP_MUTED.getType()).setContent(notification);
  213 + .setType(ImContentTypeEnum.GROUP_MUTED.getType()).setContent(notification);
214 214 }
215 215  
216 216 public static ImGroupMessageSendDTO ofGroupCancelMuted(Long groupId, Long operatorUserId) {
217 217 GroupCancelMutedNotification notification = new GroupCancelMutedNotification();
218 218 notification.setOperatorUserId(operatorUserId);
219 219 return new ImGroupMessageSendDTO().setGroupId(groupId)
220   - .setType(ImMessageTypeEnum.GROUP_CANCEL_MUTED.getType()).setContent(notification);
  220 + .setType(ImContentTypeEnum.GROUP_CANCEL_MUTED.getType()).setContent(notification);
221 221 }
222 222  
223 223 public static ImGroupMessageSendDTO ofGroupBanned(Long groupId, Long operatorUserId, boolean banned) {
... ... @@ -225,7 +225,7 @@ public class ImGroupMessageSendDTO {
225 225 notification.setOperatorUserId(operatorUserId);
226 226 notification.setBanned(banned);
227 227 return new ImGroupMessageSendDTO().setGroupId(groupId)
228   - .setType(ImMessageTypeEnum.GROUP_BANNED.getType()).setContent(notification);
  228 + .setType(ImContentTypeEnum.GROUP_BANNED.getType()).setContent(notification);
229 229 }
230 230  
231 231 }
... ...
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,7 +30,7 @@ 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 */
... ...
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;
... ... @@ -1047,7 +1046,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1047 1046 * @param userId 加入的参与者用户编号
1048 1047 */
1049 1048 private void pushParticipantConnectedNotification(ImRtcCallDO call, Long userId) {
1050   - pushParticipantNotification(call, ImMessageTypeEnum.RTC_PARTICIPANT_CONNECTED.getType(), userId,
  1049 + pushParticipantNotification(call, ImContentTypeEnum.RTC_PARTICIPANT_CONNECTED.getType(), userId,
1051 1050 ImRtcParticipantConnectedNotification.of(call, userId));
1052 1051 }
1053 1052  
... ... @@ -1058,7 +1057,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1058 1057 * @param userId 离开的参与者用户编号
1059 1058 */
1060 1059 private void pushParticipantDisconnectedNotification(ImRtcCallDO call, Long userId) {
1061   - pushParticipantNotification(call, ImMessageTypeEnum.RTC_PARTICIPANT_DISCONNECTED.getType(), userId,
  1060 + pushParticipantNotification(call, ImContentTypeEnum.RTC_PARTICIPANT_DISCONNECTED.getType(), userId,
1062 1061 ImRtcParticipantDisconnectedNotification.of(call, userId));
1063 1062 }
1064 1063  
... ... @@ -1091,7 +1090,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1091 1090 private void pushCallStartNotification(ImRtcCallDO call, AdminUserRespDTO inviter, Set<Long> invitees) {
1092 1091 ImRtcCallStartNotification payload = ImRtcCallStartNotification.of(call, inviter);
1093 1092 Long peerUserId = ImConversationTypeEnum.isGroup(call.getConversationType()) ? null : CollUtil.getFirst(invitees);
1094   - pushCallChatMessage(call, ImMessageTypeEnum.RTC_CALL_START, payload, peerUserId);
  1093 + pushCallChatMessage(call, ImContentTypeEnum.RTC_CALL_START, payload, peerUserId);
1095 1094 }
1096 1095  
1097 1096 /**
... ... @@ -1115,7 +1114,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1115 1114 p -> ObjUtil.notEqual(p.getUserId(), call.getInviterUserId()));
1116 1115 peerUserId = peer != null ? peer.getUserId() : null;
1117 1116 }
1118   - pushCallChatMessage(call, ImMessageTypeEnum.RTC_CALL_END, payload, peerUserId);
  1117 + pushCallChatMessage(call, ImContentTypeEnum.RTC_CALL_END, payload, peerUserId);
1119 1118 }
1120 1119  
1121 1120 /**
... ... @@ -1128,7 +1127,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService {
1128 1127 * @param payload 推送 payload
1129 1128 * @param peerUserId 私聊对端用户编号;群聊忽略,私聊缺失时回退为 senderId
1130 1129 */
1131   - private void pushCallChatMessage(ImRtcCallDO call, ImMessageTypeEnum type, Object payload, Long peerUserId) {
  1130 + private void pushCallChatMessage(ImRtcCallDO call, ImContentTypeEnum type, Object payload, Long peerUserId) {
1132 1131 Long senderId = call.getInviterUserId();
1133 1132 if (ImConversationTypeEnum.isGroup(call.getConversationType())) {
1134 1133 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;
... ... @@ -88,31 +86,30 @@ public class ImWebSocketServiceImpl implements ImWebSocketService {
88 86 }
89 87  
90 88 /**
91   - * 异步发送频道 WebSocket 消息
  89 + * 异步发送 WebSocket 通知
92 90 */
93 91 @Async
94   - public void doSendChannelMessage(Collection<Long> userIds, ImChannelMessageDTO dto) {
  92 + public void doSendNotification(Collection<Long> userIds, ImNotificationWebSocketDTO notification) {
95 93 for (Long userId : getDistinctUserIds(userIds)) {
96 94 try {
97 95 webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
98   - ImChannelMessageDTO.TYPE, dto);
  96 + ImNotificationWebSocketDTO.TYPE, notification);
99 97 } catch (Exception e) {
100   - log.error("[doSendChannelMessage][userId({}) dto({}) 发送失败]", userId, dto, e);
  98 + log.error("[doSendNotification][userId({}) notification({}) 发送失败]", userId, notification, e);
101 99 }
102 100 }
103 101 }
104 102  
105 103 /**
106   - * 异步广播频道 WebSocket 消息给当前所有在线管理端用户;
107   - * 依赖 infra WebSocketSenderApi 按 UserType 广播能力,离线用户由客户端上线 pull 兜底
  104 + * 异步广播 WebSocket 通知
108 105 */
109 106 @Async
110   - public void doBroadcastChannelMessage(ImChannelMessageDTO dto) {
  107 + public void doBroadcastNotification(ImNotificationWebSocketDTO notification) {
111 108 try {
112 109 webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(),
113   - ImChannelMessageDTO.TYPE, dto);
  110 + ImNotificationWebSocketDTO.TYPE, notification);
114 111 } catch (Exception e) {
115   - log.error("[doBroadcastChannelMessage][dto({}) 广播失败]", dto, e);
  112 + log.error("[doBroadcastNotification][notification({}) 广播失败]", notification, e);
116 113 }
117 114 }
118 115  
... ... @@ -121,19 +118,15 @@ public class ImWebSocketServiceImpl implements ImWebSocketService {
121 118 }
122 119  
123 120 /**
124   - * 事务感知的任务调度:
125   - * - 有事务:注册 afterCommit 回调,事务提交后再执行,防止客户端拿到消息去查库时数据还没落盘
126   - * - 无事务:直接执行(如非 @Transactional 方法中的调用)
  121 + * 事务感知的任务调度
127 122 *
128   - * @param task 待执行的推送任务(内部通过 getSelf() 走 @Async 异步执行)
  123 + * @param task 待执行的推送任务
129 124 */
130 125 private void executeAfterTransaction(Runnable task) {
131   - // 情况一:没有事务,直接执行
132 126 if (!TransactionSynchronizationManager.isSynchronizationActive()) {
133 127 task.run();
134 128 return;
135 129 }
136   - // 情况二:有事务,注册 afterCommit 事件,在事务提交后执行
137 130 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
138 131  
139 132 @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 Integer receiptStatus;
66   - /**
67   - * 发送时间
68   - */
69   - private LocalDateTime sendTime;
70   -
71   - // ========== 静态工厂方法 ==========
72   -
73   - /**
74   - * 构建发送消息 DTO
75   - *
76   - * @param message 私聊消息 DO
77   - * @return 私聊 DTO
78   - */
79   - public static ImPrivateMessageDTO ofSend(ImPrivateMessageDO message) {
80   - return BeanUtils.toBean(message, ImPrivateMessageDTO.class);
81   - }
82   -
83   - /**
84   - * 构建已读同步 DTO(多端同步:通知自己的其他终端"我已经读了某个会话")
85   - *
86   - * @param senderId 当前用户编号
87   - * @param receiverId 对方用户编号
88   - * @param readId 已读位置(最大已读消息编号)
89   - * @return 私聊 DTO
90   - */
91   - public static ImPrivateMessageDTO ofRead(Long senderId, Long receiverId, Long readId) {
92   - return new ImPrivateMessageDTO()
93   - .setId(readId).setType(ImMessageTypeEnum.READ.getType())
94   - .setSenderId(senderId).setReceiverId(receiverId);
95   - }
96   -
97   - /**
98   - * 构建已读回执 DTO(通知对方"我已读了你的消息")
99   - *
100   - * @param senderId 已读方的用户编号
101   - * @param receiverId 对方用户编号
102   - * @param readId 已读位置(最大已读消息编号)
103   - * @return 私聊 DTO
104   - */
105   - public static ImPrivateMessageDTO ofReceipt(Long senderId, Long receiverId, Long readId) {
106   - return new ImPrivateMessageDTO()
107   - .setId(readId).setType(ImMessageTypeEnum.RECEIPT.getType())
108   - .setSenderId(senderId).setReceiverId(receiverId);
109   - }
110   -
111   - // ==================== 好友变更相关 ====================
112   -
113   - /**
114   - * 构建好友通知推送 DTO(统一入口)
115   - *
116   - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 FRIEND_* 段
117   - * @param operatorUserId 操作人用户编号;同时作为帧的 senderId 用于定位接收端 friendUserId
118   - * @param receiverUserId 推送目标用户编号
119   - * @param payload 好友通知 payload(继承 {@link BaseFriendNotification})
120   - * @return 私聊 DTO
121   - */
122   - public static ImPrivateMessageDTO ofFriendNotification(Integer type, Long operatorUserId,
123   - Long receiverUserId, BaseFriendNotification payload) {
124   - validateNotification(type, payload, ImMessageTypeEnum.isFriendNotification(type));
125   - return new ImPrivateMessageDTO().setType(type)
126   - .setSenderId(operatorUserId).setReceiverId(receiverUserId)
127   - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now());
128   - }
129   -
130   - // ==================== 群定向私聊通知 ====================
131   -
132   - // TODO DONE @AI:群申请定向通知继续走私聊通道
133   - /**
134   - * 构建群通知推送 DTO(走私聊通道定向推送,不入群消息流)
135   - * <p>
136   - * 用于 GROUP_REQUEST_RECEIVED / GROUP_REQUEST_APPROVED / GROUP_REQUEST_REJECTED 段位;
137   - * 与 {@link cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO} 走 sendGroupMessage 群广播路径不同
138   - *
139   - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 GROUP_REQUEST_* 段
140   - * @param operatorUserId 操作人用户编号;同时作为帧的 senderId
141   - * @param receiverUserId 推送目标用户编号
142   - * @param payload 群事件 payload(继承 {@link BaseGroupNotification})
143   - * @return 私聊 DTO
144   - */
145   - public static ImPrivateMessageDTO ofGroupNotification(Integer type, Long operatorUserId,
146   - Long receiverUserId, BaseGroupNotification payload) {
147   - validateNotification(type, payload, ImMessageTypeEnum.isGroupRequestNotification(type));
148   - return new ImPrivateMessageDTO().setType(type)
149   - .setSenderId(operatorUserId).setReceiverId(receiverUserId)
150   - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now());
151   - }
152   -
153   - // ==================== 实时通话信令 ====================
154   -
155   - /**
156   - * 构建通话信令推送 DTO(走私聊通道仅推参与方,不入消息流)
157   - * <p>
158   - * 用于 RTC_CALL(INVITE / REJECT 等)/ RTC_PARTICIPANT_CONNECTED / RTC_PARTICIPANT_DISCONNECTED
159   - *
160   - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 RTC_* 段
161   - * @param senderId 发送人编号;INVITE 时为发起人,REJECT 时为拒绝者,参与者事件时为加入 / 离开者
162   - * @param receiverUserId 推送目标用户编号
163   - * @param payload 通话事件 payload(任意 RTC 通知 DTO)
164   - * @return 私聊 DTO
165   - */
166   - public static ImPrivateMessageDTO ofRtcNotification(Integer type, Long senderId,
167   - Long receiverUserId, Object payload) {
168   - validateNotification(type, payload, ImMessageTypeEnum.isRtcNotification(type));
169   - return new ImPrivateMessageDTO().setType(type)
170   - .setSenderId(senderId).setReceiverId(receiverUserId)
171   - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now());
172   - }
173   -
174   - private static void validateNotification(Integer type, Object payload, boolean supported) {
175   - Assert.notNull(type, "消息类型不能为空");
176   - Assert.notNull(payload, "消息内容不能为空");
177   - Assert.isTrue(supported, "消息类型不匹配 type={}", type);
178   - }
179   -
180   -}
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 含创建者 + 初始邀请成员)
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupDissolveNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupDissolveNotification.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 * 群解散事件通知
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupInfoUpdateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupInfoUpdateNotification.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/GroupMemberCancelMutedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberCancelMutedNotification.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/GroupMemberEnterNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberEnterNotification.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/GroupMemberInviteNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberInviteNotification.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/GroupMemberKickNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberKickNotification.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/GroupMemberListNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberListNotification.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/GroupMemberMutedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberMutedNotification.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/GroupMemberNicknameUpdateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberNicknameUpdateNotification.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/GroupMemberQuitNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberQuitNotification.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 * 成员退群事件通知
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberSettingUpdateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberSettingUpdateNotification.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/GroupMessagePinNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessagePinNotification.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/GroupMessageUnpinNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessageUnpinNotification.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/GroupMutedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMutedNotification.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/GroupNameUpdateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNameUpdateNotification.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/GroupNoticeUpdateNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNoticeUpdateNotification.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/GroupOwnerTransferNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupOwnerTransferNotification.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/GroupRequestApprovedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestApprovedNotification.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;
... ... @@ -6,7 +6,7 @@ import lombok.EqualsAndHashCode;
6 6 /**
7 7 * 入群申请被同意通知
8 8 * <p>
9   - * 走私聊通道定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除
  9 + * 定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除
10 10 */
11 11 @EqualsAndHashCode(callSuper = true)
12 12 @Data
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestReceivedNotification.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;
... ... @@ -6,7 +6,7 @@ import lombok.EqualsAndHashCode;
6 6 /**
7 7 * 收到新的入群申请通知
8 8 * <p>
9   - * 走私聊通道定向推送给群主 + 全部管理员(多端同步);payload 已携带申请方昵称 / 头像,前端按 requestId 直接 push 进列表
  9 + * 定向推送给群主 + 全部管理员(多端同步);payload 已携带申请方昵称 / 头像,前端按 requestId 直接 push 进列表
10 10 */
11 11 @EqualsAndHashCode(callSuper = true)
12 12 @Data
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestRejectedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestRejectedNotification.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;
... ... @@ -6,7 +6,7 @@ import lombok.EqualsAndHashCode;
6 6 /**
7 7 * 入群申请被拒绝通知
8 8 * <p>
9   - * 走私聊通道定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除
  9 + * 定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除
10 10 */
11 11 @EqualsAndHashCode(callSuper = true)
12 12 @Data
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImChannelMessageDTO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImChannelMessageNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.message;
2 2  
3 3 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 4 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO;
5   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
6 5 import lombok.Data;
7 6 import lombok.experimental.Accessors;
8 7  
9 8 import java.time.LocalDateTime;
10 9  
11 10 /**
12   - * IM 频道消息 WebSocket 推送 DTO
  11 + * IM 频道消息 WebSocket 推送通知
13 12 * <p>
14 13 * 单向:服务端运营推送 → C 端用户;C 端不能向频道发消息。
15 14 * 字段分层:顶层是消息元数据 + 检索维度,content 是 MaterialMessage payload 的 JSON 串。
... ... @@ -18,9 +17,7 @@ import java.time.LocalDateTime;
18 17 */
19 18 @Data
20 19 @Accessors(chain = true)
21   -public class ImChannelMessageDTO {
22   -
23   - public static final String TYPE = "im-channel-message";
  20 +public class ImChannelMessageNotification {
24 21  
25 22 /**
26 23 * 消息编号
... ... @@ -48,23 +45,10 @@ public class ImChannelMessageDTO {
48 45 private LocalDateTime sendTime;
49 46  
50 47 /**
51   - * 由频道消息 DO 构建推送 DTO
52   - */
53   - public static ImChannelMessageDTO ofSend(ImChannelMessageDO message) {
54   - return BeanUtils.toBean(message, ImChannelMessageDTO.class);
55   - }
56   -
57   - /**
58   - * 构建已读同步 DTO;多端同步:通知自己的其他终端「我已经读了某频道」
59   - *
60   - * @param channelId 频道编号
61   - * @param readId 已读位置(最大已读消息编号)
62   - * @return 频道 DTO
  48 + * 由频道消息 DO 构建推送通知
63 49 */
64   - public static ImChannelMessageDTO ofRead(Long channelId, Long readId) {
65   - return new ImChannelMessageDTO()
66   - .setId(readId).setType(ImMessageTypeEnum.READ.getType())
67   - .setChannelId(channelId);
  50 + public static ImChannelMessageNotification ofSend(ImChannelMessageDO message) {
  51 + return BeanUtils.toBean(message, ImChannelMessageNotification.class);
68 52 }
69 53  
70 54 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImGroupMessageNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.message;
2 2  
3 3 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 4 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
5   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
6 5 import lombok.Data;
7 6  
8 7 import java.time.LocalDateTime;
9 8 import java.util.List;
10 9  
11 10 /**
12   - * IM 群聊消息 WebSocket 统一推送 DTO
13   - * <p>
14   - * 发送、已读、回执都通过 {@link #type} 字段区分,
15   - * 并统一复用 {@link #id} 字段表达目标消息或已读位置。
  11 + * IM 群聊消息 WebSocket 统一推送通知
16 12 *
17 13 * @author 芋道源码
18 14 */
19 15 @Data
20   -public class ImGroupMessageDTO {
21   -
22   - public static final String TYPE = "im-group-message";
  16 +public class ImGroupMessageNotification {
23 17  
24 18 /**
25 19 * 消息编号
26   - * <p>
27   - * 普通消息:当前消息 id
28   - * READ:无(群已读不需要)
29   - * RECEIPT:需要回执的目标消息 id
30 20 */
31 21 private Long id;
32 22 /**
... ... @@ -54,6 +44,14 @@ public class ImGroupMessageDTO {
54 44 */
55 45 private Integer status;
56 46 /**
  47 + * 回执状态
  48 + */
  49 + private Integer receiptStatus;
  50 + /**
  51 + * 已读人数
  52 + */
  53 + private Integer readCount;
  54 + /**
57 55 * 发送时间
58 56 */
59 57 private LocalDateTime sendTime;
... ... @@ -66,58 +64,14 @@ public class ImGroupMessageDTO {
66 64 */
67 65 private List<Long> receiverUserIds;
68 66 /**
69   - * 群回执状态
70   - */
71   - private Integer receiptStatus;
72   - /**
73   - * 群回执已读人数
74   - */
75   - private Integer readCount;
76   - /**
77   - * 已读位置
78   - */
79   - private Long readId;
80   -
81   - // ========== 静态工厂方法 ==========
82   -
83   - /**
84   - * 构建发送消息 DTO
  67 + * 构建发送消息通知
85 68 *
86 69 * @param message 群聊消息 DO
87   - * @return 群聊 DTO
88   - */
89   - public static ImGroupMessageDTO ofSend(ImGroupMessageDO message) {
90   - return BeanUtils.toBean(message, ImGroupMessageDTO.class).setReceiverUserIds(null);
91   - }
92   -
93   - /**
94   - * 构建已读同步 DTO(多端同步:通知自己的其他终端"我已经读了某个群")
95   - *
96   - * @param senderId 当前用户编号
97   - * @param groupId 群编号
98   - * @param readId 已读位置(最大已读消息编号)
99   - * @return 群聊 DTO
100   - */
101   - public static ImGroupMessageDTO ofRead(Long senderId, Long groupId, Long readId) {
102   - return new ImGroupMessageDTO()
103   - .setId(readId).setReadId(readId).setType(ImMessageTypeEnum.READ.getType())
104   - .setSenderId(senderId).setGroupId(groupId);
105   - }
106   -
107   - /**
108   - * 构建群回执 DTO(广播回执状态和已读人数)
109   - *
110   - * @param messageId 消息编号
111   - * @param groupId 群编号
112   - * @param readCount 已读人数
113   - * @param receiptStatus 回执状态
114   - * @return 群聊 DTO
  70 + * @return 群聊通知
115 71 */
116   - public static ImGroupMessageDTO ofReceipt(Long messageId, Long groupId,
117   - Integer readCount, Integer receiptStatus) {
118   - return new ImGroupMessageDTO()
119   - .setId(messageId).setType(ImMessageTypeEnum.RECEIPT.getType())
120   - .setGroupId(groupId).setReadCount(readCount).setReceiptStatus(receiptStatus);
  72 + public static ImGroupMessageNotification ofSend(ImGroupMessageDO message) {
  73 + return BeanUtils.toBean(message, ImGroupMessageNotification.class)
  74 + .setReadCount(message.getReadCount() != null ? message.getReadCount() : 0);
121 75 }
122 76  
123 77 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReadNotification.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.message;
  2 +
  3 +import lombok.Data;
  4 +import lombok.experimental.Accessors;
  5 +
  6 +/**
  7 + * IM 消息已读同步通知
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Data
  12 +@Accessors(chain = true)
  13 +public class ImMessageReadNotification {
  14 +
  15 + /**
  16 + * 已读位置(最大已读消息编号)
  17 + */
  18 + private Long id;
  19 + /**
  20 + * 发送人编号
  21 + */
  22 + private Long senderId;
  23 + /**
  24 + * 私聊接收人编号
  25 + */
  26 + private Long receiverId;
  27 + /**
  28 + * 群编号
  29 + */
  30 + private Long groupId;
  31 + /**
  32 + * 频道编号
  33 + */
  34 + private Long channelId;
  35 + /**
  36 + * 已读位置(最大已读消息编号)
  37 + */
  38 + private Long readId;
  39 +
  40 + public static ImMessageReadNotification ofPrivate(Long senderId, Long receiverId, Long readId) {
  41 + return new ImMessageReadNotification()
  42 + .setId(readId).setReadId(readId)
  43 + .setSenderId(senderId).setReceiverId(receiverId);
  44 + }
  45 +
  46 + public static ImMessageReadNotification ofGroup(Long senderId, Long groupId, Long readId) {
  47 + return new ImMessageReadNotification()
  48 + .setId(readId).setReadId(readId)
  49 + .setSenderId(senderId).setGroupId(groupId);
  50 + }
  51 +
  52 + public static ImMessageReadNotification ofChannel(Long channelId, Long readId) {
  53 + return new ImMessageReadNotification()
  54 + .setId(readId).setReadId(readId)
  55 + .setChannelId(channelId);
  56 + }
  57 +
  58 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReceiptNotification.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.message;
  2 +
  3 +import lombok.Data;
  4 +import lombok.experimental.Accessors;
  5 +
  6 +/**
  7 + * IM 消息回执通知
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Data
  12 +@Accessors(chain = true)
  13 +public class ImMessageReceiptNotification {
  14 +
  15 + /**
  16 + * 消息编号
  17 + */
  18 + private Long id;
  19 + /**
  20 + * 已读方的用户编号
  21 + */
  22 + private Long senderId;
  23 + /**
  24 + * 私聊接收人编号
  25 + */
  26 + private Long receiverId;
  27 + /**
  28 + * 群编号
  29 + */
  30 + private Long groupId;
  31 + /**
  32 + * 已读人数
  33 + */
  34 + private Integer readCount;
  35 + /**
  36 + * 回执状态
  37 + */
  38 + private Integer receiptStatus;
  39 +
  40 + public static ImMessageReceiptNotification ofPrivate(Long senderId, Long receiverId, Long readId) {
  41 + return new ImMessageReceiptNotification()
  42 + .setId(readId).setSenderId(senderId).setReceiverId(receiverId);
  43 + }
  44 +
  45 + public static ImMessageReceiptNotification ofGroup(Long messageId, Long groupId,
  46 + Integer readCount, Integer receiptStatus) {
  47 + return new ImMessageReceiptNotification()
  48 + .setId(messageId).setGroupId(groupId)
  49 + .setReadCount(readCount).setReceiptStatus(receiptStatus);
  50 + }
  51 +
  52 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImPrivateMessageNotification.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.message;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  4 +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
  5 +import lombok.Data;
  6 +import lombok.experimental.Accessors;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +/**
  11 + * IM 私聊消息 WebSocket 统一推送通知
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Data
  16 +@Accessors(chain = true)
  17 +public class ImPrivateMessageNotification {
  18 +
  19 + /**
  20 + * 消息编号
  21 + */
  22 + private Long id;
  23 + /**
  24 + * 客户端消息编号
  25 + */
  26 + private String clientMessageId;
  27 + /**
  28 + * 发送人编号
  29 + */
  30 + private Long senderId;
  31 + /**
  32 + * 接收人编号
  33 + */
  34 + private Long receiverId;
  35 + /**
  36 + * 消息类型
  37 + */
  38 + private Integer type;
  39 + /**
  40 + * 消息内容
  41 + */
  42 + private String content;
  43 + /**
  44 + * 消息状态
  45 + */
  46 + private Integer status;
  47 + /**
  48 + * 回执状态
  49 + */
  50 + private Integer receiptStatus;
  51 + /**
  52 + * 发送时间
  53 + */
  54 + private LocalDateTime sendTime;
  55 +
  56 + // ========== 静态工厂方法 ==========
  57 +
  58 + /**
  59 + * 构建发送消息通知
  60 + *
  61 + * @param message 私聊消息 DO
  62 + * @return 私聊通知
  63 + */
  64 + public static ImPrivateMessageNotification ofSend(ImPrivateMessageDO message) {
  65 + return BeanUtils.toBean(message, ImPrivateMessageNotification.class);
  66 + }
  67 +
  68 +}
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/package-info.java 0 → 100644
  1 +/**
  2 + * IM WebSocket 在线通知对象。
  3 + *
  4 + * <p>
  5 + * 本包只放 WebSocket 外层通知对象,固定使用 im-notification 作为推送 type。
  6 + * 具体业务 payload 放在子包中:
  7 + * <ul>
  8 + * <li>{@code message}:私聊、群聊、频道消息通知,以及消息内容结构;</li>
  9 + * <li>{@code friend}:好友关系和好友申请通知;</li>
  10 + * <li>{@code group}:群资料、群成员、加群申请通知;</li>
  11 + * <li>{@code rtc}:实时通话通知。</li>
  12 + * </ul>
  13 + */
  14 +package cn.iocoder.yudao.module.im.service.websocket.notification;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallEndNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc;
2 2  
3 3 import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO;
4 4 import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallEndReasonEnum;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc;
2 2  
3 3 import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO;
4 4 import cn.iocoder.yudao.module.im.enums.rtc.ImRtcParticipantStatusEnum;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallStartNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc;
2 2  
3 3 import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO;
4 4 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantConnectedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc;
2 2  
3 3 import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantDisconnectedNotification.java
1   -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc;
  1 +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc;
2 2  
3 3 import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/util/ImMessageUtils.java
... ... @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.convert.Convert;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
8   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage;
  7 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  8 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage;
9 9  
10 10 import java.util.Collection;
11 11 import java.util.LinkedHashMap;
... ... @@ -39,9 +39,9 @@ public class ImMessageUtils {
39 39 * @param content 消息内容
40 40 */
41 41 public static void validateUserMessageContent(Integer type, String content) {
42   - ImMessageTypeEnum messageType;
  42 + ImContentTypeEnum messageType;
43 43 try {
44   - messageType = ImMessageTypeEnum.validate(type);
  44 + messageType = ImContentTypeEnum.validate(type);
45 45 } catch (IllegalArgumentException e) {
46 46 throw exception(MESSAGE_CONTENT_INVALID);
47 47 }
... ... @@ -52,23 +52,23 @@ public class ImMessageUtils {
52 52 if (map == null) {
53 53 throw exception(MESSAGE_CONTENT_INVALID);
54 54 }
55   - if (ImMessageTypeEnum.TEXT == messageType) {
  55 + if (ImContentTypeEnum.TEXT == messageType) {
56 56 validateTextContent(map);
57   - } else if (ImMessageTypeEnum.IMAGE == messageType || ImMessageTypeEnum.FACE == messageType) {
  57 + } else if (ImContentTypeEnum.IMAGE == messageType || ImContentTypeEnum.FACE == messageType) {
58 58 validateUrl(getString(map, "url"));
59   - } else if (ImMessageTypeEnum.VOICE == messageType) {
  59 + } else if (ImContentTypeEnum.VOICE == messageType) {
60 60 validateUrl(getString(map, "url"));
61 61 validatePositiveNumber(map.get("duration"));
62   - } else if (ImMessageTypeEnum.VIDEO == messageType) {
  62 + } else if (ImContentTypeEnum.VIDEO == messageType) {
63 63 validateUrl(getString(map, "url"));
64   - } else if (ImMessageTypeEnum.FILE == messageType) {
  64 + } else if (ImContentTypeEnum.FILE == messageType) {
65 65 validateUrl(getString(map, "url"));
66 66 validateNotBlank(getString(map, "name"));
67   - } else if (ImMessageTypeEnum.CARD == messageType) {
  67 + } else if (ImContentTypeEnum.CARD == messageType) {
68 68 validateCardContent(map);
69   - } else if (ImMessageTypeEnum.MERGE == messageType) {
  69 + } else if (ImContentTypeEnum.MERGE == messageType) {
70 70 validateMergeContent(map);
71   - } else if (ImMessageTypeEnum.MATERIAL == messageType) {
  71 + } else if (ImContentTypeEnum.MATERIAL == messageType) {
72 72 validateMaterialContent(map);
73 73 }
74 74 }
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java
... ... @@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMemberMapper;
11 11 import cn.iocoder.yudao.module.im.dal.mysql.message.ImGroupMessageMapper;
12 12 import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
13 13 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
14   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  14 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
15 15 import jakarta.annotation.Resource;
16 16 import org.junit.jupiter.api.BeforeEach;
17 17 import org.junit.jupiter.api.Test;
... ... @@ -194,10 +194,10 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest {
194 194 @Test
195 195 public void testSelectMessageTypeDistribution_mergePrivateAndGroup() {
196 196 // 准备:私聊 type=0 ×1,群聊 type=0 ×2、type=1 ×1
197   - privateMessageMapper.insert(buildPrivate(1L, 2L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.TEXT.getType()));
198   - groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.TEXT.getType()));
199   - groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.TEXT.getType()));
200   - groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.IMAGE.getType()));
  197 + privateMessageMapper.insert(buildPrivate(1L, 2L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.TEXT.getType()));
  198 + groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.TEXT.getType()));
  199 + groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.TEXT.getType()));
  200 + groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.IMAGE.getType()));
201 201  
202 202 // 调用
203 203 List<Map<String, Object>> dist = mapper.selectMessageTypeDistribution(WINDOW_BEGIN, WINDOW_END);
... ... @@ -205,8 +205,8 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest {
205 205 // 断言:type=TEXT(0) → 3;type=IMAGE(1) → 1
206 206 Map<Object, Long> byType = dist.stream().collect(java.util.stream.Collectors.toMap(
207 207 m -> ((Number) m.get("type")).intValue(), m -> ((Number) m.get("count")).longValue()));
208   - assertEquals(3L, byType.get(ImMessageTypeEnum.TEXT.getType()));
209   - assertEquals(1L, byType.get(ImMessageTypeEnum.IMAGE.getType()));
  208 + assertEquals(3L, byType.get(ImContentTypeEnum.TEXT.getType()));
  209 + assertEquals(1L, byType.get(ImContentTypeEnum.IMAGE.getType()));
210 210 }
211 211  
212 212 @Test
... ... @@ -243,7 +243,7 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest {
243 243 return ImPrivateMessageDO.builder()
244 244 .clientMessageId("uuid-" + System.nanoTime())
245 245 .senderId(senderId).receiverId(receiverId)
246   - .type(ImMessageTypeEnum.TEXT.getType())
  246 + .type(ImContentTypeEnum.TEXT.getType())
247 247 .content("{}")
248 248 .status(ImMessageStatusEnum.NORMAL.getStatus())
249 249 .sendTime(sendTime).build();
... ... @@ -253,7 +253,7 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest {
253 253 return new ImGroupMessageDO()
254 254 .setClientMessageId("uuid-" + System.nanoTime())
255 255 .setSenderId(senderId).setGroupId(groupId)
256   - .setType(ImMessageTypeEnum.TEXT.getType())
  256 + .setType(ImContentTypeEnum.TEXT.getType())
257 257 .setContent("{}")
258 258 .setStatus(ImMessageStatusEnum.NORMAL.getStatus())
259 259 .setSendTime(sendTime);
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImplTest.java
... ... @@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.im.enums.friend.ImFriendRequestHandleResultEnum;
12 12 import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum;
13 13 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
14 14 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
15   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
16 15 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
17 16 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
18 17 import org.junit.jupiter.api.Test;
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java
... ... @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.im.dal.mysql.friend.ImFriendMapper;
10 10 import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService;
11 11 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO;
12 12 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
13   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
14 13 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
15 14 import org.junit.jupiter.api.Test;
16 15 import org.mockito.ArgumentCaptor;
... ... @@ -158,7 +157,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
158 157 verify(imFriendMapper, never()).insert(any(ImFriendDO.class));
159 158 verify(imFriendMapper, never()).updateById(any(ImFriendDO.class));
160 159 verify(imFriendMapper, never()).updateReAddFields(anyLong(), anyInt(), any(LocalDateTime.class),
161   - anyBoolean(), anyBoolean(), anyBoolean(), any(), any());
  160 + any(LocalDateTime.class), anyBoolean(), anyBoolean(), anyBoolean(), any(), any());
162 161 }
163 162  
164 163 @Test
... ... @@ -173,7 +172,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
173 172  
174 173 // 断言:恢复 ENABLE,并清空 deleteTime
175 174 verify(imFriendMapper).updateReAddFields(eq(10L), eq(CommonStatusEnum.ENABLE.getStatus()),
176   - any(LocalDateTime.class), eq(false), eq(false), eq(false), isNull(), isNull());
  175 + any(LocalDateTime.class), any(LocalDateTime.class), eq(false), eq(false), eq(false), isNull(), isNull());
177 176 verify(imFriendMapper, never()).insert(any(ImFriendDO.class));
178 177 }
179 178  
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImplTest.java
... ... @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
9 9 import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMemberMapper;
10 10 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
11 11 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
12   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
  12 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification;
13 13 import org.junit.jupiter.api.Test;
14 14 import org.mockito.ArgumentCaptor;
15 15 import org.mockito.InjectMocks;
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImplTest.java
... ... @@ -13,11 +13,10 @@ 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 17 import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService;
18 18 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
19 19 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
20   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
21 20 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
22 21 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
23 22 import org.junit.jupiter.api.Test;
... ... @@ -84,7 +83,7 @@ public class ImGroupRequestServiceImplTest extends BaseMockitoUnitTest {
84 83 // 推 1510 自由进群
85 84 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
86 85 verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture());
87   - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType());
  86 + assertEquals(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType());
88 87 }
89 88  
90 89 @Test
... ... @@ -207,7 +206,7 @@ public class ImGroupRequestServiceImplTest extends BaseMockitoUnitTest {
207 206 eq(ImGroupAddSourceEnum.SEARCH.getSource()), isNull());
208 207 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
209 208 verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture());
210   - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType());
  209 + assertEquals(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType());
211 210 // 1505 推送给申请人 + owner,去重后两条
212 211 verify(websocketService, times(2)).sendPrivateMessageAsync(anyLong(), any(ImPrivateMessageDTO.class));
213 212 }
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java
... ... @@ -19,13 +19,13 @@ import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
19 19 import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper;
20 20 import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum;
21 21 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
22   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  22 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
23 23 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
24 24 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
25 25 import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService;
26 26 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
27 27 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
28   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
  28 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification;
29 29 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
30 30 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
31 31 import org.junit.jupiter.api.Test;
... ... @@ -100,7 +100,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
100 100 // 验证:推送 GROUP_CREATE 通知(payload memberUserIds 含创建者自己)
101 101 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
102 102 verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture());
103   - assertEquals(ImMessageTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType());
  103 + assertEquals(ImContentTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType());
104 104 }
105 105  
106 106 @Test
... ... @@ -132,7 +132,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
132 132 // 验证:推送 GROUP_CREATE 通知,payload memberUserIds 含全员(创建者 + 邀请)
133 133 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
134 134 verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture());
135   - assertEquals(ImMessageTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType());
  135 + assertEquals(ImContentTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType());
136 136 }
137 137  
138 138 @Test
... ... @@ -205,7 +205,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
205 205 // 推送 GROUP_NAME_UPDATE 通知给全员
206 206 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
207 207 verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture());
208   - assertEquals(ImMessageTypeEnum.GROUP_NAME_UPDATE.getType(), dtoCaptor.getValue().getType());
  208 + assertEquals(ImContentTypeEnum.GROUP_NAME_UPDATE.getType(), dtoCaptor.getValue().getType());
209 209 }
210 210 }
211 211  
... ... @@ -234,7 +234,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
234 234 // 推送 GROUP_DISSOLVE 通知(send-before-remove,sendGroupMessage 内部查 active 自动覆盖全员,含群主多端同步)
235 235 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
236 236 verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture());
237   - assertEquals(ImMessageTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType());
  237 + assertEquals(ImContentTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType());
238 238 }
239 239 }
240 240  
... ... @@ -276,7 +276,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
276 276 // 断言:使用管理员编号发通知并完成清理
277 277 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
278 278 verify(groupMessageService).sendGroupMessage(eq(99L), dtoCaptor.capture());
279   - assertEquals(ImMessageTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType());
  279 + assertEquals(ImContentTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType());
280 280 verify(groupMemberService).removeGroupMembersByGroupId(10L);
281 281 }
282 282 }
... ... @@ -345,7 +345,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
345 345 verify(webSocketService, never()).sendGroupMessageAsync(anyCollection(), any(ImGroupMessageDTO.class));
346 346 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
347 347 verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture());
348   - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType());
  348 + assertEquals(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType());
349 349 }
350 350 }
351 351  
... ... @@ -429,7 +429,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
429 429 eq(ImGroupAddSourceEnum.INVITE.getSource()), eq(1L));
430 430 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
431 431 verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture());
432   - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType());
  432 + assertEquals(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType());
433 433 }
434 434 }
435 435  
... ... @@ -564,7 +564,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
564 564 // 推送 GROUP_MEMBER_QUIT 通知给全员(含 quitter,前端自判清群)
565 565 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
566 566 verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture());
567   - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_QUIT.getType(), dtoCaptor.getValue().getType());
  567 + assertEquals(ImContentTypeEnum.GROUP_MEMBER_QUIT.getType(), dtoCaptor.getValue().getType());
568 568 }
569 569 }
570 570  
... ... @@ -642,7 +642,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest {
642 642 // 推送 GROUP_MEMBER_KICK 通知给全员(含被踢者,前端自判清群)
643 643 ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class);
644 644 verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture());
645   - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_KICK.getType(), dtoCaptor.getValue().getType());
  645 + assertEquals(ImContentTypeEnum.GROUP_MEMBER_KICK.getType(), dtoCaptor.getValue().getType());
646 646 }
647 647 }
648 648  
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java
... ... @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
14 14 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
15 15 import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
16 16 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
17   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  17 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
18 18 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
19 19 import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
20 20 import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
... ... @@ -22,8 +22,8 @@ import cn.iocoder.yudao.module.im.service.group.ImGroupService;
22 22 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
23 23 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
24 24 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
25   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
26   -import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage;
  25 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification;
  26 +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.RecallMessage;
27 27 import org.junit.jupiter.api.Test;
28 28 import org.mockito.ArgumentCaptor;
29 29 import org.mockito.InjectMocks;
... ... @@ -70,7 +70,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
70 70 ImGroupMessageSendReqVO reqVO = new ImGroupMessageSendReqVO();
71 71 reqVO.setClientMessageId("test-uuid-group-001");
72 72 reqVO.setGroupId(10L);
73   - reqVO.setType(ImMessageTypeEnum.TEXT.getType());
  73 + reqVO.setType(ImContentTypeEnum.TEXT.getType());
74 74 reqVO.setContent("{\"content\":\"群聊你好\"}");
75 75 return reqVO;
76 76 }
... ... @@ -85,6 +85,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
85 85  
86 86 // 准备
87 87 ImGroupMessageSendReqVO reqVO = buildSendReqVO();
  88 + reqVO.setReceipt(true);
88 89 when(groupMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-group-001"))
89 90 .thenReturn(null);
90 91 ImGroupDO group = new ImGroupDO();
... ... @@ -112,7 +113,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
112 113 assertEquals(1L, result.getSenderId());
113 114 assertEquals(10L, result.getGroupId());
114 115 assertEquals(ImMessageStatusEnum.NORMAL.getStatus(), result.getStatus());
115   - assertEquals(ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus(), result.getReceiptStatus());
  116 + assertEquals(ImMessageReceiptStatusEnum.PENDING.getStatus(), result.getReceiptStatus());
116 117  
117 118 // 验证推送给 3 个群成员(含发送者自己,用于多端同步)
118 119 verify(imWebSocketService).sendGroupMessageAsync(argThat((Collection<Long> ids) ->
... ... @@ -889,7 +890,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
889 890 public void testSendGroupMessage_dto_persistsAndSerializesPojoContent() {
890 891 // 准备:persistent=true 类型 + POJO content
891 892 ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO()
892   - .setGroupId(10L).setType(ImMessageTypeEnum.RECALL.getType())
  893 + .setGroupId(10L).setType(ImContentTypeEnum.RECALL.getType())
893 894 .setContent(new RecallMessage().setMessageId(50L));
894 895 when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L));
895 896  
... ... @@ -901,7 +902,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
901 902 ImGroupMessageDO message = captor.getValue();
902 903 assertEquals(1L, message.getSenderId());
903 904 assertEquals(10L, message.getGroupId());
904   - assertEquals(ImMessageTypeEnum.RECALL.getType(), message.getType());
  905 + assertEquals(ImContentTypeEnum.RECALL.getType(), message.getType());
905 906 assertEquals("{\"messageId\":50}", message.getContent());
906 907 assertEquals(ImMessageStatusEnum.NORMAL.getStatus(), message.getStatus());
907 908 assertEquals(ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus(), message.getReceiptStatus());
... ... @@ -913,7 +914,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
913 914 public void testSendGroupMessage_dto_receiptPending() {
914 915 // 准备:dto.receipt=true → receiptStatus=PENDING
915 916 ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO()
916   - .setGroupId(10L).setType(ImMessageTypeEnum.RECALL.getType())
  917 + .setGroupId(10L).setType(ImContentTypeEnum.RECALL.getType())
917 918 .setContent("{\"messageId\":50}").setReceipt(true);
918 919 when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L));
919 920  
... ... @@ -928,7 +929,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
928 929 public void testSendGroupMessage_dto_nonPersistentTypeNotInserted() {
929 930 // 准备:persistent=false 类型(RECEIPT 回执)→ 不入库,仅推送
930 931 ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO()
931   - .setGroupId(10L).setType(ImMessageTypeEnum.RECEIPT.getType());
  932 + .setGroupId(10L).setType(ImContentTypeEnum.RECEIPT.getType());
932 933 when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L, 2L));
933 934  
934 935 groupMessageService.sendGroupMessage(1L, dto);
... ... @@ -942,7 +943,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
942 943 // 准备:调用方传入显式 targets(解散场景成员已被批量 DISABLE,必须按移除前快照推送)
943 944 Set<Long> targets = Set.of(1L, 2L, 3L);
944 945 ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO()
945   - .setGroupId(10L).setType(ImMessageTypeEnum.GROUP_DISSOLVE.getType()).setContent("{}");
  946 + .setGroupId(10L).setType(ImContentTypeEnum.GROUP_DISSOLVE.getType()).setContent("{}");
946 947  
947 948 groupMessageService.sendGroupMessage(1L, targets, dto);
948 949  
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java
... ... @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
9 9 import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
10 10 import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum;
11 11 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
12   -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  12 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
13 13 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
14 14 import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService;
15 15 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
... ... @@ -380,7 +380,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
380 380 public void testSendPrivateMessage_dto_persistsAndSerializesPojoContent() {
381 381 // 准备:persistent=true 类型 + POJO content
382 382 ImPrivateMessageSendDTO dto = new ImPrivateMessageSendDTO()
383   - .setReceiverId(2L).setType(ImMessageTypeEnum.RECALL.getType())
  383 + .setReceiverId(2L).setType(ImContentTypeEnum.RECALL.getType())
384 384 .setContent(new RecallMessage().setMessageId(50L));
385 385  
386 386 privateMessageService.sendPrivateMessage(1L, dto);
... ... @@ -391,7 +391,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
391 391 ImPrivateMessageDO message = captor.getValue();
392 392 assertEquals(1L, message.getSenderId());
393 393 assertEquals(2L, message.getReceiverId());
394   - assertEquals(ImMessageTypeEnum.RECALL.getType(), message.getType());
  394 + assertEquals(ImContentTypeEnum.RECALL.getType(), message.getType());
395 395 assertEquals("{\"messageId\":50}", message.getContent());
396 396 assertEquals(ImMessageStatusEnum.NORMAL.getStatus(), message.getStatus());
397 397 assertNotNull(message.getClientMessageId());
... ... @@ -405,7 +405,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
405 405 public void testSendPrivateMessage_dto_nonPersistentTypeNotInserted() {
406 406 // 准备:persistent=false 类型(FRIEND_DELETE 通知)→ 不入库;仅推 sender 多端,receiver 不感知
407 407 ImPrivateMessageSendDTO dto = new ImPrivateMessageSendDTO()
408   - .setReceiverId(2L).setType(ImMessageTypeEnum.FRIEND_DELETE.getType());
  408 + .setReceiverId(2L).setType(ImContentTypeEnum.FRIEND_DELETE.getType());
409 409  
410 410 privateMessageService.sendPrivateMessage(1L, dto);
411 411  
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImplTest.java
... ... @@ -20,7 +20,6 @@ import cn.iocoder.yudao.module.im.enums.rtc.ImRtcParticipantStatusEnum;
20 20 import cn.iocoder.yudao.module.im.framework.config.ImProperties;
21 21 import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
22 22 import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService;
23   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
24 23 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
25 24 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
26 25 import org.junit.jupiter.api.Test;
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImplTest.java
... ... @@ -4,8 +4,11 @@ import cn.hutool.core.collection.ListUtil;
4 4 import cn.hutool.extra.spring.SpringUtil;
5 5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 6 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
7   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO;
8   -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO;
  7 +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum;
  8 +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum;
  9 +import cn.iocoder.yudao.module.im.service.websocket.notification.ImNotificationWebSocketDTO;
  10 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification;
  11 +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImPrivateMessageNotification;
9 12 import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
10 13 import org.junit.jupiter.api.AfterEach;
11 14 import org.junit.jupiter.api.Test;
... ... @@ -21,6 +24,7 @@ import java.util.List;
21 24  
22 25 import static org.junit.jupiter.api.Assertions.assertEquals;
23 26 import static org.mockito.ArgumentMatchers.eq;
  27 +import static org.mockito.ArgumentMatchers.argThat;
24 28 import static org.mockito.Mockito.*;
25 29  
26 30 /**
... ... @@ -44,10 +48,10 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest {
44 48 }
45 49 }
46 50  
47   - // ========== sendPrivateMessageAsync ==========
  51 + // ========== sendNotificationAsync ==========
48 52  
49 53 @Test
50   - public void testSendPrivateMessageAsync_noTransactionSendsImmediately() {
  54 + public void testSendNotificationAsync_private_noTransactionSendsImmediately() {
51 55 try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
52 56 springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class)))
53 57 .thenReturn(imWebSocketService);
... ... @@ -60,12 +64,14 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest {
60 64  
61 65 // 断言
62 66 verify(webSocketSenderApi).sendObject(
63   - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImPrivateMessageDTO.TYPE), eq(dto));
  67 + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE),
  68 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.PRIVATE,
  69 + ImContentTypeEnum.TEXT, dto)));
64 70 }
65 71 }
66 72  
67 73 @Test
68   - public void testSendPrivateMessageAsync_inTransactionDeferredUntilCommit() {
  74 + public void testSendNotificationAsync_private_inTransactionDeferredUntilCommit() {
69 75 try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
70 76 springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class)))
71 77 .thenReturn(imWebSocketService);
... ... @@ -89,43 +95,51 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest {
89 95  
90 96 // 断言:提交后推送
91 97 verify(webSocketSenderApi).sendObject(
92   - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImPrivateMessageDTO.TYPE), eq(dto));
  98 + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE),
  99 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.PRIVATE,
  100 + ImContentTypeEnum.TEXT, dto)));
93 101 } finally {
94 102 TransactionSynchronizationManager.clear();
95 103 }
96 104 }
97 105 }
98 106  
99   - // ========== sendGroupMessageAsync ==========
  107 + // ========== sendNotificationAsync ==========
100 108  
101 109 @Test
102   - public void testSendGroupMessageAsync_fanOutToAllUsers() {
  110 + public void testSendNotificationAsync_group_fanOutToAllUsers() {
103 111 try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
104 112 springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class)))
105 113 .thenReturn(imWebSocketService);
106 114  
107   - ImGroupMessageDTO dto = new ImGroupMessageDTO();
  115 + ImGroupMessageNotification dto = new ImGroupMessageNotification();
108 116 dto.setGroupId(10L);
109 117 dto.setSenderId(1L);
110 118  
111 119 imWebSocketService.sendGroupMessageAsync(ListUtil.of(1L, 2L, 3L), dto);
112 120  
113 121 verify(webSocketSenderApi).sendObject(
114   - eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImGroupMessageDTO.TYPE), eq(dto));
  122 + eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImNotificationWebSocketDTO.TYPE),
  123 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP,
  124 + ImContentTypeEnum.TEXT, dto)));
115 125 verify(webSocketSenderApi).sendObject(
116   - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImGroupMessageDTO.TYPE), eq(dto));
  126 + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE),
  127 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP,
  128 + ImContentTypeEnum.TEXT, dto)));
117 129 verify(webSocketSenderApi).sendObject(
118   - eq(UserTypeEnum.ADMIN.getValue()), eq(3L), eq(ImGroupMessageDTO.TYPE), eq(dto));
  130 + eq(UserTypeEnum.ADMIN.getValue()), eq(3L), eq(ImNotificationWebSocketDTO.TYPE),
  131 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP,
  132 + ImContentTypeEnum.TEXT, dto)));
119 133 }
120 134 }
121 135  
122 136 @Test
123   - public void testSendGroupMessageAsync_senderExceptionDoesNotBreakOthers() {
  137 + public void testSendNotificationAsync_group_senderExceptionDoesNotBreakOthers() {
124 138 try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
125 139 springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class)))
126 140 .thenReturn(imWebSocketService);
127 141  
128   - ImGroupMessageDTO dto = new ImGroupMessageDTO();
  142 + ImGroupMessageNotification dto = new ImGroupMessageNotification();
129 143 dto.setGroupId(10L);
130 144 // 给 1 号用户推送时抛异常,不能影响 2/3 号
131 145 doThrow(new RuntimeException("user offline"))
... ... @@ -143,8 +157,8 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest {
143 157 public void testDoSendGroupMessage_emptyUserIds_noSend() {
144 158 ImGroupMessageDTO dto = new ImGroupMessageDTO().setGroupId(10L);
145 159  
146   - imWebSocketService.doSendGroupMessage(Collections.emptyList(), dto);
147   - imWebSocketService.doSendGroupMessage(null, dto);
  160 + imWebSocketService.doSendNotification(Collections.emptyList(), notification);
  161 + imWebSocketService.doSendNotification(null, notification);
148 162  
149 163 verifyNoInteractions(webSocketSenderApi);
150 164 }
... ... @@ -153,17 +167,21 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest {
153 167 public void testDoSendGroupMessage_distinctUserIds() {
154 168 ImGroupMessageDTO dto = new ImGroupMessageDTO().setGroupId(10L);
155 169  
156   - imWebSocketService.doSendGroupMessage(Arrays.asList(1L, 2L, 1L, null), dto);
  170 + imWebSocketService.doSendNotification(Arrays.asList(1L, 2L, 1L, null), notification);
157 171  
158 172 verify(webSocketSenderApi).sendObject(
159   - eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImGroupMessageDTO.TYPE), eq(dto));
  173 + eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImNotificationWebSocketDTO.TYPE),
  174 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP,
  175 + ImContentTypeEnum.TEXT, dto)));
160 176 verify(webSocketSenderApi).sendObject(
161   - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImGroupMessageDTO.TYPE), eq(dto));
  177 + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE),
  178 + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP,
  179 + ImContentTypeEnum.TEXT, dto)));
162 180 verifyNoMoreInteractions(webSocketSenderApi);
163 181 }
164 182  
165 183 @Test
166   - public void testSendPrivateMessageAsync_exceptionSwallowed() {
  184 + public void testSendNotificationAsync_private_exceptionSwallowed() {
167 185 try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
168 186 springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class)))
169 187 .thenReturn(imWebSocketService);
... ... @@ -181,12 +199,12 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest {
181 199 }
182 200  
183 201 @Test
184   - public void testSendGroupMessageAsync_singleUserDefaultOverload() {
  202 + public void testSendNotificationAsync_group_singleUserDefaultOverload() {
185 203 try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
186 204 springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class)))
187 205 .thenReturn(imWebSocketService);
188 206  
189   - ImGroupMessageDTO dto = new ImGroupMessageDTO();
  207 + ImGroupMessageNotification dto = new ImGroupMessageNotification();
190 208 dto.setGroupId(10L);
191 209  
192 210 imWebSocketService.sendGroupMessageAsync(42L, dto);
... ...