From 3dd717939354799e4f3e97c7df8512209effa368 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 16 Jun 2026 11:38:58 +0800 Subject: [PATCH] refactor: 扁平化 IM WebSocket 通知推送 API --- sql/mysql/ruoyi-vue-pro.sql | 74 +++++++++++++++++++++++++++++++++++++------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/channel/ImChannelMessageRespVO.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerRespVO.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerRespVO.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/ImStatisticsManagerController.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/vo/ImStatisticsManagerMessageTypeRespVO.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/group/ImGroupMessageSendReqVO.java | 6 +++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageSendReqVO.java | 6 +++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImChannelMessageDO.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImGroupMessageDO.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImPrivateMessageDO.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java | 29 +++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FaceMessage.java | 39 +++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java | 33 +++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java | 24 ++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MaterialMessage.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MergeMessage.java | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/QuoteMessage.java | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/RecallMessage.java | 18 ++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java | 21 +++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java | 41 +++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java | 422 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImConversationTypeEnum.java | 5 +++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java | 422 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java | 7 +++---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java | 21 ++++++++++----------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageServiceImpl.java | 9 +++++---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java | 16 +++++++++------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java | 16 +++++++++------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImGroupMessageSendDTO.java | 50 +++++++++++++++++++++++++------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImPrivateMessageSendDTO.java | 6 +++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java | 15 +++++++-------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/statistics/ImStatisticsManagerService.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketService.java | 74 +++++++++++++++++++------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImpl.java | 29 +++++++++++------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImChannelMessageDTO.java | 70 ---------------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java | 123 --------------------------------------------------------------------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImPrivateMessageDTO.java | 180 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/AudioMessage.java | 29 ----------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/CardMessage.java | 44 -------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java | 39 --------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FileMessage.java | 33 --------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/ImageMessage.java | 37 ------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/LocationMessage.java | 24 ------------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MaterialMessage.java | 51 --------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MergeMessage.java | 64 ---------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/QuoteMessage.java | 50 -------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/RecallMessage.java | 18 ------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/TextMessage.java | 21 --------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/VideoMessage.java | 41 ----------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/BaseFriendNotification.java | 24 ------------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendAddNotification.java | 13 ------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendBlockNotification.java | 13 ------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendDeleteNotification.java | 18 ------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendInfoUpdatedNotification.java | 16 ---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestApprovedNotification.java | 18 ------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestNotification.java | 37 ------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestRejectedNotification.java | 22 ---------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUnblockNotification.java | 13 ------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUpdateNotification.java | 27 --------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/BaseGroupNotification.java | 16 ---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminAddNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminRemoveNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupBannedNotification.java | 16 ---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCancelMutedNotification.java | 13 ------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCreateNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupDissolveNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupInfoUpdateNotification.java | 20 -------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberCancelMutedNotification.java | 18 ------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberEnterNotification.java | 25 ------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberInviteNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberKickNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberListNotification.java | 20 -------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberMutedNotification.java | 24 ------------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberNicknameUpdateNotification.java | 16 ---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberQuitNotification.java | 7 ------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberSettingUpdateNotification.java | 22 ---------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessagePinNotification.java | 64 ---------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessageUnpinNotification.java | 16 ---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMutedNotification.java | 11 ----------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNameUpdateNotification.java | 20 -------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNoticeUpdateNotification.java | 20 -------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupOwnerTransferNotification.java | 16 ---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestApprovedNotification.java | 28 ---------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java | 51 --------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestRejectedNotification.java | 32 -------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java | 76 ---------------------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java | 165 --------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java | 61 ------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java | 61 ------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java | 51 --------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/ImNotificationWebSocketDTO.java | 33 +++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/BaseFriendNotification.java | 24 ++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendAddNotification.java | 13 +++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendBlockNotification.java | 13 +++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendDeleteNotification.java | 18 ++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendInfoUpdatedNotification.java | 16 ++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestApprovedNotification.java | 18 ++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestNotification.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestRejectedNotification.java | 22 ++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUnblockNotification.java | 13 +++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUpdateNotification.java | 27 +++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/BaseGroupNotification.java | 16 ++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminAddNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminRemoveNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupBannedNotification.java | 16 ++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCancelMutedNotification.java | 13 +++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCreateNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupDissolveNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupInfoUpdateNotification.java | 20 ++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberCancelMutedNotification.java | 18 ++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberEnterNotification.java | 25 +++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberInviteNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberKickNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberListNotification.java | 20 ++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberMutedNotification.java | 24 ++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberNicknameUpdateNotification.java | 16 ++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberQuitNotification.java | 7 +++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberSettingUpdateNotification.java | 22 ++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessagePinNotification.java | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessageUnpinNotification.java | 16 ++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMutedNotification.java | 11 +++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNameUpdateNotification.java | 20 ++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNoticeUpdateNotification.java | 20 ++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupOwnerTransferNotification.java | 16 ++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestApprovedNotification.java | 28 ++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestReceivedNotification.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestRejectedNotification.java | 32 ++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImChannelMessageNotification.java | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImGroupMessageNotification.java | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReadNotification.java | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReceiptNotification.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImPrivateMessageNotification.java | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/package-info.java | 14 ++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallEndNotification.java | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallNotification.java | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallStartNotification.java | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantConnectedNotification.java | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantDisconnectedNotification.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/util/ImMessageUtils.java | 24 ++++++++++++------------ yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java | 18 +++++++++--------- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImplTest.java | 1 - yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java | 5 ++--- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImplTest.java | 2 +- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImplTest.java | 7 +++---- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java | 22 +++++++++++----------- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java | 21 +++++++++++---------- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java | 8 ++++---- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImplTest.java | 1 - yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImplTest.java | 64 +++++++++++++++++++++++++++++++++++++++++----------------------- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/util/ImMessageUtilsTest.java | 2 +- 157 files changed, 2603 insertions(+), 2641 deletions(-) create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FaceMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MaterialMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MergeMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/QuoteMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/RecallMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImChannelMessageDTO.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImPrivateMessageDTO.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/AudioMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/CardMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FileMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/ImageMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/LocationMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MaterialMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MergeMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/QuoteMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/RecallMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/TextMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/VideoMessage.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/BaseFriendNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendAddNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendBlockNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendDeleteNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendInfoUpdatedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestApprovedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestRejectedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUnblockNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUpdateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/BaseGroupNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminAddNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminRemoveNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupBannedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCancelMutedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCreateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupDissolveNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupInfoUpdateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberCancelMutedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberEnterNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberInviteNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberKickNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberListNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberMutedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberNicknameUpdateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberQuitNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberSettingUpdateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessagePinNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessageUnpinNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMutedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNameUpdateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNoticeUpdateNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupOwnerTransferNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestApprovedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestRejectedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/ImNotificationWebSocketDTO.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/BaseFriendNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendAddNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendBlockNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendDeleteNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendInfoUpdatedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestApprovedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestRejectedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUnblockNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUpdateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/BaseGroupNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminAddNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminRemoveNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupBannedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCancelMutedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCreateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupDissolveNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupInfoUpdateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberCancelMutedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberEnterNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberInviteNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberKickNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberListNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberMutedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberNicknameUpdateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberQuitNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberSettingUpdateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessagePinNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessageUnpinNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMutedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNameUpdateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNoticeUpdateNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupOwnerTransferNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestApprovedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestReceivedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestRejectedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImChannelMessageNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImGroupMessageNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReadNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReceiptNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImPrivateMessageNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/package-info.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallEndNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallStartNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantConnectedNotification.java create mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantDisconnectedNotification.java diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index f6773c7..4f70c5c 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -1396,39 +1396,39 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT 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'); INSERT 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'); INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); INSERT 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'); INSERT 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'); INSERT 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 INSERT 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'); INSERT 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'); INSERT 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'); -INSERT 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'); -INSERT 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'); -INSERT 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'); +INSERT 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'); +INSERT 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'); +INSERT 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'); INSERT 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'); INSERT 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'); COMMIT; @@ -1689,7 +1689,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat 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); 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); 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'); -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); +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); 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); 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); 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); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/channel/ImChannelMessageRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/channel/ImChannelMessageRespVO.java index 9f76ed2..cf1bd64 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/channel/ImChannelMessageRespVO.java +++ b/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 { private String materialCoverUrl; @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "125") - private Integer type; // 参见 ImMessageTypeEnum 枚举类 + private Integer type; // 参见 ImContentTypeEnum 枚举类 @Schema(description = "消息内容;payload JSON 快照") private String content; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java index 86d236d..121ac90 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java +++ b/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 { private Long senderId; @Schema(description = "消息类型", example = "1") - private Integer type; // 参见 ImMessageTypeEnum 枚举类 + private Integer type; // 参见 ImContentTypeEnum 枚举类 @Schema(description = "消息内容", example = "你好") private String content; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerRespVO.java index a231a0e..fcc964a 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerRespVO.java +++ b/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 { private String senderNickname; @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer type; // 参见 ImMessageTypeEnum 枚举类 + private Integer type; // 参见 ImContentTypeEnum 枚举类 @Schema(description = "消息内容(JSON 格式)", requiredMode = Schema.RequiredMode.REQUIRED) private String content; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java index e6a72da..6fa711b 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java +++ b/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 { private Long receiverId; @Schema(description = "消息类型", example = "1") - private Integer type; // 参见 ImMessageTypeEnum 枚举类 + private Integer type; // 参见 ImContentTypeEnum 枚举类 @Schema(description = "消息内容", example = "你好") private String content; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerRespVO.java index 895aded..941ef8c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerRespVO.java +++ b/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 { private String receiverNickname; @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer type; // 参见 ImMessageTypeEnum 枚举类 + private Integer type; // 参见 ImContentTypeEnum 枚举类 @Schema(description = "消息内容(JSON 格式)", requiredMode = Schema.RequiredMode.REQUIRED) private String content; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/ImStatisticsManagerController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/ImStatisticsManagerController.java index 82403e3..0a5f1d5 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/ImStatisticsManagerController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/ImStatisticsManagerController.java @@ -112,7 +112,7 @@ public class ImStatisticsManagerController { } @GetMapping("/message-type-distribution") - @Operation(summary = "获得消息类型分布(最近 30 天)") + @Operation(summary = "获得内容类型分布(最近 30 天)") @PreAuthorize("@ss.hasPermission('im:manager:statistics:query')") public CommonResult> getMessageTypeDistribution() { LocalDateTime endTime = LocalDate.now().plusDays(1).atStartOfDay(); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/vo/ImStatisticsManagerMessageTypeRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/vo/ImStatisticsManagerMessageTypeRespVO.java index 2da0827..fce2275 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/statistics/vo/ImStatisticsManagerMessageTypeRespVO.java +++ b/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; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - IM 数据看板消息类型分布项 Response VO") +@Schema(description = "管理后台 - IM 数据看板内容类型分布项 Response VO") @Data public class ImStatisticsManagerMessageTypeRespVO { @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - private Integer type; // 参见 ImMessageTypeEnum 枚举类 + private Integer type; // 参见 ImContentTypeEnum 枚举类 @Schema(description = "消息数", requiredMode = Schema.RequiredMode.REQUIRED, example = "8000") private Long value; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/group/ImGroupMessageSendReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/group/ImGroupMessageSendReqVO.java index f02d919..813e35a 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/group/ImGroupMessageSendReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/group/ImGroupMessageSendReqVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.im.controller.admin.message.vo.group; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.AssertTrue; @@ -28,7 +28,7 @@ public class ImGroupMessageSendReqVO { @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @NotNull(message = "消息类型不能为空") - @InEnum(ImMessageTypeEnum.class) + @InEnum(ImContentTypeEnum.class) private Integer type; @Schema(description = "消息内容,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"content\":\"你好\"}") @@ -47,7 +47,7 @@ public class ImGroupMessageSendReqVO { @AssertTrue(message = "消息类型不允许") @JsonIgnore public boolean isTypeNormal() { - return type == null || ImMessageTypeEnum.validate(type).isNormal(); + return type == null || ImContentTypeEnum.validate(type).isNormal(); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageSendReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageSendReqVO.java index 860a61e..6552234 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageSendReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/privates/ImPrivateMessageSendReqVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.im.controller.admin.message.vo.privates; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.AssertTrue; @@ -26,7 +26,7 @@ public class ImPrivateMessageSendReqVO { @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @NotNull(message = "消息类型不能为空") - @InEnum(ImMessageTypeEnum.class) + @InEnum(ImContentTypeEnum.class) private Integer type; @Schema(description = "消息内容,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"content\":\"你好\"}") @@ -42,7 +42,7 @@ public class ImPrivateMessageSendReqVO { @AssertTrue(message = "消息类型不允许") @JsonIgnore public boolean isTypeNormal() { - return type == null || ImMessageTypeEnum.validate(type).isNormal(); + return type == null || ImContentTypeEnum.validate(type).isNormal(); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImChannelMessageDO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImChannelMessageDO.java index 2572828..d71ee7c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImChannelMessageDO.java +++ b/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; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelDO; import cn.iocoder.yudao.module.im.dal.dataobject.channel.ImChannelMaterialDO; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -54,7 +54,7 @@ public class ImChannelMessageDO extends BaseDO { /** * 消息类型 *

- * 枚举 {@link ImMessageTypeEnum} + * 枚举 {@link ImContentTypeEnum} */ private Integer type; /** diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImGroupMessageDO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImGroupMessageDO.java index f68ee07..bdab8a8 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImGroupMessageDO.java +++ b/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; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -54,7 +54,7 @@ public class ImGroupMessageDO extends BaseDO { /** * 消息类型 *

- * 枚举 {@link ImMessageTypeEnum} + * 枚举 {@link ImContentTypeEnum} */ private Integer type; /** diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImPrivateMessageDO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImPrivateMessageDO.java index 855b054..808c1ee 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImPrivateMessageDO.java +++ b/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; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -50,7 +50,7 @@ public class ImPrivateMessageDO extends BaseDO { /** * 消息类型 *

- * 枚举 {@link ImMessageTypeEnum} + * 枚举 {@link ImContentTypeEnum} */ private Integer type; /** diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java new file mode 100644 index 0000000..2422467 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 语音消息内容 + */ +@Data +public class AudioMessage { + + /** + * 语音文件 URL + */ + private String url; + /** + * 语音时长(秒) + */ + private Integer duration; + /** + * 文件大小(字节) + */ + private Long size; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java new file mode 100644 index 0000000..d99ed12 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum; +import lombok.Data; + +/** + * 名片消息内容 + *

+ * 支持两类名片,按 targetType 区分: + * 1. 用户名片(targetType = PRIVATE):targetId = 用户编号,name = 用户昵称 + * 2. 群名片(targetType = GROUP):targetId = 群编号,name = 群名,可带 memberCount + */ +@Data +public class CardMessage { + + /** + * 名片对象类型 + *

+ * 枚举 {@link ImConversationTypeEnum} + */ + private Integer targetType; + /** + * 目标对象编号:PRIVATE 时 = 用户编号;GROUP 时 = 群编号 + */ + private Long targetId; + /** + * 显示名快照:PRIVATE 时 = 用户昵称;GROUP 时 = 群名 + */ + private String name; + /** + * 头像(快照) + */ + private String avatar; + /** + * 群成员数(仅 targetType = GROUP;接收端展示「N 人群聊」) + */ + private Integer memberCount; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FaceMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FaceMessage.java new file mode 100644 index 0000000..6d6a642 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FaceMessage.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 表情消息内容 + *

+ * 承载「贴图 / 自定义表情包」类消息;Unicode emoji(😀😂)仍走 TEXT + */ +@Data +public class FaceMessage { + + /** + * 表情图 URL + */ + private String url; + /** + * 渲染宽度(像素,可选) + *

+ * 客户端渲染时按此尺寸占位,避免图片加载完成后的布局抖动;缺失时由客户端 CSS max-width 兜底 + */ + private Integer width; + /** + * 渲染高度(像素,可选) + */ + private Integer height; + /** + * 表情名(可选) + *

+ * 系统表情包通常带名字(如「狗头」「捂脸」),用户私有表情包通常为空 + */ + private String name; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java new file mode 100644 index 0000000..bd4fcc3 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 文件消息内容 + */ +@Data +public class FileMessage { + + /** + * 文件 URL + */ + private String url; + /** + * 文件名 + */ + private String name; + /** + * 文件大小(字节) + */ + private Long size; + /** + * 文件类型(扩展名) + */ + private String type; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java new file mode 100644 index 0000000..052342a --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 图片消息内容 + */ +@Data +public class ImageMessage { + + /** + * 图片 URL + */ + private String url; + /** + * 缩略图 URL + */ + private String thumbnailUrl; + /** + * 图片宽度 + */ + private Integer width; + /** + * 图片高度 + */ + private Integer height; + /** + * 图片大小(字节) + */ + private Long size; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java new file mode 100644 index 0000000..fdbb7c7 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 位置消息内容 + */ +@Data +public class LocationMessage { + + /** + * 位置描述 + */ + private String description; + /** + * 经度 + */ + private Double longitude; + /** + * 纬度 + */ + private Double latitude; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MaterialMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MaterialMessage.java new file mode 100644 index 0000000..41fbdce --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MaterialMessage.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 频道素材消息 payload + *

+ * 对应 {@link cn.iocoder.yudao.module.im.enums.ImContentTypeEnum#MATERIAL}(type=125)。 + * 客户端按本字段集渲染图文卡片; + * 富文本正文不在本 payload 中传递,点击详情时另调 /im/channel/material/get-content?id= 按需拉取。 + */ +@Data +@Accessors(chain = true) +public class MaterialMessage { + + /** + * 素材编号 + */ + private Long materialId; + /** + * 频道编号 + *

+ * 冗余到 payload 内;转发到私聊 / 群聊后客户端用本字段定位频道,渲染卡片底部的频道头像 + 名称 + */ + private Long channelId; + /** + * 素材内容类型 + *

+ * 枚举 {@link cn.iocoder.yudao.module.im.enums.channel.ImChannelMaterialTypeEnum} + * 客户端按本字段判定点击行为:CONTENT 走站内详情页拉富文本;LINK 跳 url + */ + private Integer type; + /** + * 标题 + */ + private String title; + /** + * 封面图 + */ + private String coverUrl; + /** + * 摘要 + */ + private String summary; + /** + * 跳转链接 + */ + private String url; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MergeMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MergeMessage.java new file mode 100644 index 0000000..9bc675b --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/MergeMessage.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; +import lombok.Data; + +import java.util.List; + +/** + * 合并转发消息内容 + *

+ * payload 内嵌完整快照,原消息撤回 / 删除不影响已转发的合并消息 + */ +@Data +public class MergeMessage { + + /** + * 合并标题 + */ + private String title; + /** + * 内嵌的完整消息快照 + */ + private List messages; + + /** + * 单条内嵌消息快照 + */ + @Data + public static class Item { + + /** + * 原消息编号 + */ + private Long messageId; + /** + * 发送人编号 + */ + private Long senderId; + /** + * 发送人昵称快照;接收方可能不在原会话里,无法实时查到 + */ + private String senderNickname; + /** + * 发送人头像快照 + */ + private String senderAvatar; + /** + * 消息类型 + *

+ * 枚举 {@link ImContentTypeEnum} + */ + private Integer type; + /** + * 原消息 content(JSON) + */ + private String content; + /** + * 发送时间戳(毫秒) + */ + private Long sendTime; + + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/QuoteMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/QuoteMessage.java new file mode 100644 index 0000000..a06d417 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/QuoteMessage.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 引用消息内容 + *

+ * 客户端在 content.quote 里写入 messageId 表达"引用了哪条消息",服务端反查原消息后重算 QuoteMessage 覆盖客户端写入, + * 避免伪造发送人 / 类型 / 摘要 + * + * @see TextMessage 等等消息内容里 quote 字段 + */ +@Data +@Accessors(chain = true) +public class QuoteMessage { + + /** + * content JSON 里 quote 字段名 + */ + public static final String FIELD_NAME = "quote"; + + /** + * QuoteMessage 里 messageId 字段名 + */ + public static final String FIELD_MESSAGE_ID = "messageId"; + + /** + * 被引用消息编号 + */ + private Long messageId; + /** + * 被引用消息发送人编号 + *

+ * 关联 AdminUserDO 的 id 字段 + */ + private Long senderId; + /** + * 被引用消息类型 + *

+ * 枚举 {@link ImContentTypeEnum} + */ + private Integer type; + /** + * 原消息完整 content(JSON);服务端复制时会 removeQuote 防嵌套 + */ + private String content; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/RecallMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/RecallMessage.java new file mode 100644 index 0000000..a9ba575 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/RecallMessage.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 撤回提示消息内容 + */ +@Data +@Accessors(chain = true) +public class RecallMessage { + + /** + * 被撤回的原消息编号 + */ + private Long messageId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java new file mode 100644 index 0000000..4d8a66c --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 文本消息内容 + */ +@Data +public class TextMessage { + + /** + * 文本内容 + */ + private String content; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java new file mode 100644 index 0000000..5bceef1 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.message.content; + +import lombok.Data; + +/** + * 视频消息内容 + */ +@Data +public class VideoMessage { + + /** + * 视频文件 URL + */ + private String url; + /** + * 视频封面 URL + */ + private String coverUrl; + /** + * 视频时长(秒) + */ + private Integer duration; + /** + * 视频宽度 + */ + private Integer width; + /** + * 视频高度 + */ + private Integer height; + /** + * 文件大小(字节) + */ + private Long size; + + /** + * 引用消息(可选) + */ + private QuoteMessage quote; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java index 141f6b8..26e3d98 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java @@ -154,7 +154,7 @@ public interface ImStatisticsManagerMapper { @Param("endTime") LocalDateTime endTime); /** - * 区间内消息类型分布(私聊+群聊合并) + * 区间内内容类型分布(私聊+群聊合并) * * @return [{type: 0, count: 123}, ...] */ diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java new file mode 100644 index 0000000..4dffd36 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java @@ -0,0 +1,422 @@ +package cn.iocoder.yudao.module.im.enums; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; +import java.util.Set; + +/** + * IM 内容类型枚举 + * + * @author 芋道源码 + */ +@Getter +@RequiredArgsConstructor +public enum ImContentTypeEnum implements ArrayValuable { + + // ========== 用户聊天消息(101-105 直接复用 OpenIM 段位编号) ========== + /** + * 对应 OpenIM:Text 101 + * 对应自己的类:TextMessage + */ + TEXT(101, "文本", true, true), + /** + * 对应 OpenIM:Picture 102 + * 对应自己的类:ImageMessage + */ + IMAGE(102, "图片", true, true), + /** + * 对应 OpenIM:Sound 103 + * 对应自己的类:AudioMessage + */ + VOICE(103, "语音", true, true), + /** + * 对应 OpenIM:Video 104 + * 对应自己的类:VideoMessage + */ + VIDEO(104, "视频", true, true), + /** + * 对应 OpenIM:File 105 + * 对应自己的类:FileMessage + */ + FILE(105, "文件", true, true), + /** + * 对应 OpenIM:Merger 107 + * 对应自己的类:MergeMessage + */ + MERGE(107, "合并转发", true, true), + /** + * 对应 OpenIM:Card 108(OpenIM 仅用户名片;本系统扩展为用户 / 群双类型,按 targetType 区分) + * 对应自己的类:CardMessage + * 场景:把用户名片 / 群名片推荐给其他会话;用户名片点击打开 UserInfoCard,群名片点击「已加群跳会话 / 未加群弹申请加群」 + */ + CARD(108, "名片", true, true), + /** + * 对应 OpenIM:Face 115 + * 对应自己的类:FaceMessage + * 场景:表情贴图(运营配置的系统表情包 + 用户私有表情包);Unicode emoji 仍走 TEXT + */ + FACE(115, "表情", true, true), + + // ========== 频道消息扩展段(125+;OpenIM 122 之后未占用,本系统在 125 起步给频道 / 公众号类消息扩展) ========== + /** + * 对应 OpenIM:无(125 段位 OpenIM 未占用,作为频道消息扩展起始位) + * 对应自己的类:MaterialMessage + * 场景:频道运营推送的素材消息;当前形态为图文卡片(title + coverUrl + summary + url) + * 详情:url 非空跳 url;url 为空时客户端按 materialId 拉 /get-content 渲染富文本正文 + */ + MATERIAL(125, "素材", true, true), + + // ========== 信号类(2101 / 2200 直接复用 OpenIM 段位编号;2201 自有扩展) ========== + /** + * 对应 OpenIM:RevokeNotification 2101 + * 对应自己的类:RecallMessage + */ + RECALL(2101, "撤回", true, false), + /** + * 对应 OpenIM:HasReadReceipt 2200 + * 对应自己的类:无(payload 走 ImXxxMessageDTO 顶层字段) + */ + RECEIPT(2200, "回执", false, false), + /** + * 对应 OpenIM:无(自有扩展,OpenIM 走 ConversationChangeNotification 1300 路径) + * 对应自己的类:无(payload 走 ImXxxMessageDTO 顶层字段) + */ + READ(2201, "已读", false, false), + + // ========== 实时通话信令(1601-1605 段位与 OpenIM 对齐;1610+ 自有扩展) ========== + /** + * 对应 OpenIM:SignalingNotification 1601(通话信令统一入口) + * 对应自己的类:ImRtcCallNotification + * 场景:通话信令;不入库,走 imWebSocketService 仅推参与方;status 复用参与者状态枚举区分 INVITING / JOINED / REJECTED / NO_ANSWER / LEFT + */ + RTC_CALL(1601, "通话信令", false, false), + /** + * 对应 OpenIM:RoomParticipantsConnectedNotification 1602 + * 对应自己的类:ImRtcParticipantConnectedNotification + * 场景:通话参与者加入;LiveKit webhook participant_joined 触发;私聊推 peer 多端 + inviter 多端,群聊全群广播;不入库 + */ + RTC_PARTICIPANT_CONNECTED(1602, "通话参与者加入", false, false), + /** + * 对应 OpenIM:RoomParticipantsDisconnectedNotification 1603 + * 对应自己的类:ImRtcParticipantDisconnectedNotification + * 场景:通话参与者离开;LiveKit webhook participant_left 触发;推送范围同 1602;不入库 + */ + RTC_PARTICIPANT_DISCONNECTED(1603, "通话参与者离开", false, false), + // 1604-1609 OpenIM 已用 / 留作扩展,本系统暂不使用 + /** + * 对应 OpenIM:无(自有扩展,OpenIM 通话事件不入消息流) + * 对应自己的类:ImRtcCallStartNotification + * 场景:通话开始;群聊入 im_group_message 全群广播,前端渲染聊天 tip「{inviterNickname} 发起了语音通话」; + * 私聊入 im_private_message 定向给被叫,仅用于会话列表预览展示「[语音通话]」(不渲染聊天 tip) + *

+ * 与 RTC_CALL_END(1611) 两段式配对:START 一定先于 END 入库(START 在 invite 接口事务里、END 在 cancel/leave 接口事务里,自然按请求顺序串行) + */ + RTC_CALL_START(1610, "通话开始", true, false), + /** + * 对应 OpenIM:无(自有扩展,OpenIM 通话事件不入消息流) + * 对应自己的类:ImRtcCallEndNotification + * 场景:通话结束;入 im_private_message / im_group_message;私聊渲染准气泡,群聊渲染 tip「语音通话已经结束」 + *

+ * 与 RTC_CALL_START(1610) 两段式配对 + */ + RTC_CALL_END(1611, "通话结束", true, false), + + // ========== 好友通知(1201-1210 直接复用 OpenIM 段位编号) ========== + /** + * 对应 OpenIM:FriendApplicationApprovedNotification 1201 + * 对应自己的类:FriendRequestApprovedNotification + * 场景:B 同意 A 的好友申请,推给 A 多端 + */ + FRIEND_REQUEST_APPROVED(1201, "好友申请被同意", false, false), + /** + * 对应 OpenIM:FriendApplicationRejectedNotification 1202 + * 对应自己的类:FriendRequestRejectedNotification + * 场景:B 拒绝 A 的好友申请,推给 A 多端 + */ + FRIEND_REQUEST_REJECTED(1202, "好友申请被拒绝", false, false), + /** + * 对应 OpenIM:FriendApplicationNotification 1203 + * 对应自己的类:FriendRequestNotification + * 场景:A 申请加 B,推给 B 多端,前端落到「新的朋友」列表 + */ + FRIEND_REQUEST_RECEIVED(1203, "收到新的好友申请", false, false), + /** + * 对应 OpenIM:FriendAddedNotification 1204(OpenIM friendAdded.isSendMsg=false 默认不入消息流;本系统改为入库当会话气泡) + * 对应自己的类:FriendAddNotification + * 场景:双方建立好友关系,单条入库(sender=fromUserId, receiver=toUserId);双向 WebSocket 自动覆盖双方多端 + * 注意:silentReAddFriend 单边语义场景,发送时显式 setPersistent(false) 覆盖默认值 + */ + FRIEND_ADD(1204, "新增好友", true, false), + /** + * 对应 OpenIM:FriendDeletedNotification 1205 + * 对应自己的类:FriendDeleteNotification + * 场景:A 删除 B,推给 A、B 双方多端 + */ + FRIEND_DELETE(1205, "好友被删除", false, false), + // 1206 对应 OpenIM FriendRemarkSetNotification;本系统并入 FRIEND_UPDATE(1210) 统一推送,单一字段变更不再独立通道 + /** + * 对应 OpenIM:BlackAddedNotification 1207 + * 对应自己的类:FriendBlockNotification + * 场景:A 拉黑 B,仅推 A 多端 + */ + FRIEND_BLOCK(1207, "加入黑名单", false, false), + /** + * 对应 OpenIM:BlackDeletedNotification 1208 + * 对应自己的类:FriendUnblockNotification + * 场景:A 移出 B 的黑名单,仅推 A 多端 + */ + FRIEND_UNBLOCK(1208, "移出黑名单", false, false), + /** + * 对应 OpenIM:FriendInfoUpdatedNotification 1209 + * 对应自己的类:FriendInfoUpdatedNotification + * 场景:B 改了昵称 / 头像后,推给 B 的所有好友 + * 触发:system 模块发 AdminUserProfileUpdateMessage,IM 消费者 AdminUserProfileUpdateConsumer 批量推此通知 + */ + FRIEND_INFO_UPDATED(1209, "好友资料变更", false, false), + /** + * 对应 OpenIM:FriendsInfoUpdateNotification 1210(窄化到 silent / pinned 单边属性) + * 对应自己的类:FriendUpdateNotification + * 场景:A 改了 silent / pinned 等单边属性,推 A 多端 + */ + FRIEND_UPDATE(1210, "好友信息批量更新", false, false), + + // ========== 群事件(1501-1520 直接复用 OpenIM 段位编号;1530+ 我们独有扩展) ========== + // 1500 对应 OpenIM GroupNotificationBegin 起始位,仅作占位,不使用 + /** + * 对应 OpenIM:sdkws.GroupCreatedTips(GroupCreatedNotification 1501) + * 对应自己的类:GroupCreateNotification + * 场景:用户创建群(同时邀请初始成员),全员广播(含创建者多端同步 + 初始成员) + */ + GROUP_CREATE(1501, "群创建", true, false), + /** + * 对应 OpenIM:sdkws.GroupInfoSetTips(GroupInfoSetNotification 1502,NAME / NOTICE 之外字段的 generic 兜底) + * 对应自己的类:GroupInfoUpdateNotification + * 场景:群主修改群头像 / 简介等字段后全员广播 + */ + GROUP_INFO_UPDATE(1502, "群信息变更", true, false), + /** + * 对应 OpenIM:sdkws.JoinGroupApplicationTips(JoinGroupApplicationNotification 1503) + * 对应自己的类:GroupRequestReceivedNotification + * 场景:用户申请加群 / 普通成员邀请待审批,定向私聊推送给群主 + 全部管理员(多端同步);不入群消息流 + */ + GROUP_REQUEST_RECEIVED(1503, "收到新的入群申请", false, false), + /** + * 对应 OpenIM:sdkws.MemberQuitTips(MemberQuitNotification 1504) + * 对应自己的类:GroupMemberQuitNotification + * 场景:成员主动退群(send-before-remove),全员广播(含 quitter);quitter 自判 operatorUserId === self → removeGroup + */ + GROUP_MEMBER_QUIT(1504, "成员退群", true, false), + /** + * 对应 OpenIM:sdkws.GroupApplicationAcceptedTips(GroupApplicationAcceptedNotification 1505) + * 对应自己的类:GroupRequestApprovedNotification + * 场景:群主 / 管理员同意申请,定向私聊推送给申请人 + 群主 + 全部管理员;申请人侧弹 toast,admin 侧 pendingRequestCount-1;不入群消息流 + */ + GROUP_REQUEST_APPROVED(1505, "入群申请被同意", false, false), + /** + * 对应 OpenIM:sdkws.GroupApplicationRejectedTips(GroupApplicationRejectedNotification 1506) + * 对应自己的类:GroupRequestRejectedNotification + * 场景:群主 / 管理员拒绝申请,定向私聊推送给申请人 + 群主 + 全部管理员;不入群消息流 + */ + GROUP_REQUEST_REJECTED(1506, "入群申请被拒绝", false, false), + /** + * 对应 OpenIM:sdkws.GroupOwnerTransferredTips(GroupOwnerTransferredNotification 1507) + * 对应自己的类:GroupOwnerTransferNotification + * 场景:群主转让,全员广播;前端 transferOwner 把 ownerUserId 切到新值 + 旧群主 role → NORMAL / 新群主 role → OWNER + */ + GROUP_OWNER_TRANSFER(1507, "群主转让", true, false), + /** + * 对应 OpenIM:sdkws.MemberKickedTips(MemberKickedNotification 1508) + * 对应自己的类:GroupMemberKickNotification + * 场景:群主 / 管理员移出成员(send-before-remove),全员广播(含被踢者);被踢者自判 memberUserIds 含 self → removeGroup + */ + GROUP_MEMBER_KICK(1508, "成员被移出", true, false), + /** + * 对应 OpenIM:sdkws.MemberInvitedTips(MemberInvitedNotification 1509) + * 对应自己的类:GroupMemberInviteNotification + * 场景:成员邀请新人入群,全员广播(含被邀请者);被邀请人前端按 memberUserIds 含自己自判,初次拉取 fetchGroupInfo + fetchGroupMembers + */ + GROUP_MEMBER_INVITE(1509, "成员加入", true, false), + /** + * 对应 OpenIM:sdkws.MemberEnterTips(MemberEnterNotification 1510) + * 对应自己的类:GroupMemberEnterNotification + * 场景:用户经搜索 / 二维码 / 分享链接自由进群(FREE 模式或审批通过后),全员广播;前端按 entrantUserId 局部添加成员 + */ + GROUP_MEMBER_ENTER(1510, "自由进群", true, false), + /** + * 对应 OpenIM:sdkws.GroupDismissedTips(GroupDismissedNotification 1511) + * 对应自己的类:GroupDissolveNotification + * 场景:群主解散群(send-before-remove),全员广播(含群主多端同步);前端 removeGroup 清群;离场用户离线 pull 通过 quit 路径(send_time < quit_time)也能拉到 + */ + GROUP_DISSOLVE(1511, "群解散", true, false), + /** + * 对应 OpenIM:sdkws.GroupMemberMutedTips(GroupMemberMutedNotification 1512) + * 对应自己的类:GroupMemberMutedNotification + * 场景:群主 / 管理员禁言某成员,全员广播 + */ + GROUP_MEMBER_MUTED(1512, "成员禁言", true, false), + /** + * 对应 OpenIM:sdkws.GroupMemberCancelMutedTips(GroupMemberCancelMutedNotification 1513) + * 对应自己的类:GroupMemberCancelMutedNotification + * 场景:群主 / 管理员取消某成员禁言,全员广播 + */ + GROUP_MEMBER_CANCEL_MUTED(1513, "成员取消禁言", true, false), + /** + * 对应 OpenIM:sdkws.GroupMutedTips(GroupMutedNotification 1514) + * 对应自己的类:GroupMutedNotification + * 场景:群主 / 管理员开启全群禁言,全员广播 + */ + GROUP_MUTED(1514, "全群禁言", true, false), + /** + * 对应 OpenIM:sdkws.GroupCancelMutedTips(GroupCancelMutedNotification 1515) + * 对应自己的类:GroupCancelMutedNotification + * 场景:群主 / 管理员取消全群禁言,全员广播 + */ + GROUP_CANCEL_MUTED(1515, "全群取消禁言", true, false), + /** + * 对应 OpenIM:sdkws.GroupMemberInfoSetTips(GroupMemberInfoSetNotification 1516,窄化到 displayUserName) + * 对应自己的类:GroupMemberNicknameUpdateNotification + * 场景:成员修改自己在群里的昵称,全员广播;前端按 displayUserName 局部更新对应 member + */ + GROUP_MEMBER_NICKNAME_UPDATE(1516, "成员昵称变更", true, false), + /** + * 对应 OpenIM:GroupMemberSetToAdminNotification 1517 + * 对应自己的类:GroupAdminAddNotification + * 场景:群主设置管理员,全员广播;前端 updateMembersRole 把对应成员 role 提升为 ADMIN + */ + GROUP_ADMIN_ADD(1517, "添加管理员", true, false), + /** + * 对应 OpenIM:GroupMemberSetToOrdinaryUserNotification 1518 + * 对应自己的类:GroupAdminRemoveNotification + * 场景:群主撤销管理员,全员广播;前端 updateMembersRole 把对应成员 role 降级为 NORMAL + */ + GROUP_ADMIN_REMOVE(1518, "撤销管理员", true, false), + /** + * 对应 OpenIM:sdkws.GroupInfoSetAnnouncementTips(GroupInfoSetAnnouncementNotification 1519) + * 对应自己的类:GroupNoticeUpdateNotification + * 场景:群主修改群公告后全员广播 + */ + GROUP_NOTICE_UPDATE(1519, "群公告变更", true, false), + /** + * 对应 OpenIM:sdkws.GroupInfoSetNameTips(GroupInfoSetNameNotification 1520) + * 对应自己的类:GroupNameUpdateNotification + * 场景:群主修改群名后全员广播 + */ + GROUP_NAME_UPDATE(1520, "群名变更", true, false), + + // 1530+ 我们独有扩展段(OpenIM 1500-1520 段位无对应物) + /** + * 对应 OpenIM:无直接对应(OpenIM 走 ConversationChangeNotification 1300 单聊路径) + * 对应自己的类:GroupMemberSettingUpdateNotification + * 场景:用户改自己的群免打扰 / 群备注,仅推该用户其他在线终端做多端同步 + */ + GROUP_MEMBER_SETTING_UPDATE(1530, "群成员个人设置变更", false, false), + /** + * 对应 OpenIM:无(OpenIM 无群消息置顶功能,自有扩展) + * 对应自己的类:GroupMessagePinNotification + * 场景:群主 / 管理员置顶一条群消息,全员广播;payload 直接带消息对象,前端把 message push 进 group.pinnedMessages + */ + GROUP_MESSAGE_PIN(1531, "群消息置顶", true, false), + /** + * 对应 OpenIM:无(OpenIM 无群消息置顶功能,自有扩展) + * 对应自己的类:GroupMessageUnpinNotification + * 场景:群主 / 管理员取消置顶,全员广播;前端按 messageId 从 group.pinnedMessages 移除 + */ + GROUP_MESSAGE_UNPIN(1532, "群消息取消置顶", true, false), + /** + * 对应 OpenIM:无(OpenIM 无群封禁概念,自有扩展) + * 对应自己的类:GroupBannedNotification + * 场景:管理后台封禁 / 解封群,全员广播;前端按 banned 字段切换输入栏封禁覆盖层 + */ + GROUP_BANNED(1533, "群封禁变更", true, false); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImContentTypeEnum::getType).toArray(Integer[]::new); + + private static final Set FRIEND_NOTIFICATION_TYPES = CollUtil.newHashSet( + FRIEND_REQUEST_APPROVED.type, + FRIEND_REQUEST_REJECTED.type, + FRIEND_REQUEST_RECEIVED.type, + FRIEND_ADD.type, + FRIEND_DELETE.type, + FRIEND_BLOCK.type, + FRIEND_UNBLOCK.type, + FRIEND_INFO_UPDATED.type, + FRIEND_UPDATE.type); + + private static final Set GROUP_REQUEST_NOTIFICATION_TYPES = CollUtil.newHashSet( + GROUP_REQUEST_RECEIVED.type, + GROUP_REQUEST_APPROVED.type, + GROUP_REQUEST_REJECTED.type); + + private static final Set RTC_NOTIFICATION_TYPES = CollUtil.newHashSet( + RTC_CALL.type, + RTC_PARTICIPANT_CONNECTED.type, + RTC_PARTICIPANT_DISCONNECTED.type); + + /** + * 类型 + */ + private final Integer type; + /** + * 名字 + */ + private final String name; + /** + * 是否入库 + *

+ * true:插入 im_xxx_message 消息表,离线 pull 能拉到; + * false:仅 WebSocket 推送,离线丢弃;状态由专用存储维护(如 READ 走 Redis 游标) + */ + private final boolean persistent; + /** + * 是不是用户聊天消息(normal vs event 二分) + *

+ * true:用户主动发的聊天消息,计入会话未读数(接收方非激活会话时 unreadCount + 1);用户发送入口仅允许这类; + * false:系统事件 / 信号 / 提示,不参与未读计数 + */ + private final boolean normal; + + @Override + public Integer[] array() { + return ARRAYS; + } + + /** + * 校验 type 已注册,并返回对应枚举;未注册立刻抛异常,避免新增 type 时漏配 persistent / normal 属性 + * + * @param type 消息类型 + * @return 枚举实例 + */ + public static ImContentTypeEnum validate(Integer type) { + ImContentTypeEnum result = ArrayUtil.firstMatch(item -> item.type.equals(type), values()); + Assert.notNull(result, "未注册的消息类型 type={}", type); + return result; + } + + /** + * 判断是否为好友通知 + */ + public static boolean isFriendNotification(Integer type) { + return type != null && FRIEND_NOTIFICATION_TYPES.contains(type); + } + + /** + * 判断是否为群申请定向通知 + */ + public static boolean isGroupRequestNotification(Integer type) { + return type != null && GROUP_REQUEST_NOTIFICATION_TYPES.contains(type); + } + + /** + * 判断是否为通话信令通知 + */ + public static boolean isRtcNotification(Integer type) { + return type != null && RTC_NOTIFICATION_TYPES.contains(type); + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImConversationTypeEnum.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImConversationTypeEnum.java index 0f3f446..eb3c053 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImConversationTypeEnum.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImConversationTypeEnum.java @@ -16,6 +16,7 @@ import java.util.Objects; @Getter public enum ImConversationTypeEnum implements ArrayValuable { + NONE(0, "无会话"), // 无会话 PRIVATE(1, "私聊"), // 私聊 GROUP(2, "群聊"), // 群聊 CHANNEL(3, "频道"); // 频道 / 公众号 @@ -36,6 +37,10 @@ public enum ImConversationTypeEnum implements ArrayValuable { return ARRAYS; } + public static boolean isNone(Integer type) { + return Objects.equals(NONE.type, type); + } + public static boolean isPrivate(Integer type) { return Objects.equals(PRIVATE.type, type); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java deleted file mode 100644 index 1c0207e..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java +++ /dev/null @@ -1,422 +0,0 @@ -package cn.iocoder.yudao.module.im.enums.message; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ArrayUtil; -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; -import java.util.Set; - -/** - * IM 消息类型枚举 - * - * @author 芋道源码 - */ -@Getter -@RequiredArgsConstructor -public enum ImMessageTypeEnum implements ArrayValuable { - - // ========== 用户聊天消息(101-105 直接复用 OpenIM 段位编号) ========== - /** - * 对应 OpenIM:Text 101 - * 对应自己的类:TextMessage - */ - TEXT(101, "文本", true, true), - /** - * 对应 OpenIM:Picture 102 - * 对应自己的类:ImageMessage - */ - IMAGE(102, "图片", true, true), - /** - * 对应 OpenIM:Sound 103 - * 对应自己的类:AudioMessage - */ - VOICE(103, "语音", true, true), - /** - * 对应 OpenIM:Video 104 - * 对应自己的类:VideoMessage - */ - VIDEO(104, "视频", true, true), - /** - * 对应 OpenIM:File 105 - * 对应自己的类:FileMessage - */ - FILE(105, "文件", true, true), - /** - * 对应 OpenIM:Merger 107 - * 对应自己的类:MergeMessage - */ - MERGE(107, "合并转发", true, true), - /** - * 对应 OpenIM:Card 108(OpenIM 仅用户名片;本系统扩展为用户 / 群双类型,按 targetType 区分) - * 对应自己的类:CardMessage - * 场景:把用户名片 / 群名片推荐给其他会话;用户名片点击打开 UserInfoCard,群名片点击「已加群跳会话 / 未加群弹申请加群」 - */ - CARD(108, "名片", true, true), - /** - * 对应 OpenIM:Face 115 - * 对应自己的类:FaceMessage - * 场景:表情贴图(运营配置的系统表情包 + 用户私有表情包);Unicode emoji 仍走 TEXT - */ - FACE(115, "表情", true, true), - - // ========== 频道消息扩展段(125+;OpenIM 122 之后未占用,本系统在 125 起步给频道 / 公众号类消息扩展) ========== - /** - * 对应 OpenIM:无(125 段位 OpenIM 未占用,作为频道消息扩展起始位) - * 对应自己的类:MaterialMessage - * 场景:频道运营推送的素材消息;当前形态为图文卡片(title + coverUrl + summary + url) - * 详情:url 非空跳 url;url 为空时客户端按 materialId 拉 /get-content 渲染富文本正文 - */ - MATERIAL(125, "素材", true, true), - - // ========== 信号类(2101 / 2200 直接复用 OpenIM 段位编号;2201 自有扩展) ========== - /** - * 对应 OpenIM:RevokeNotification 2101 - * 对应自己的类:RecallMessage - */ - RECALL(2101, "撤回", true, false), - /** - * 对应 OpenIM:HasReadReceipt 2200 - * 对应自己的类:无(payload 走 ImXxxMessageDTO 顶层字段) - */ - RECEIPT(2200, "回执", false, false), - /** - * 对应 OpenIM:无(自有扩展,OpenIM 走 ConversationChangeNotification 1300 路径) - * 对应自己的类:无(payload 走 ImXxxMessageDTO 顶层字段) - */ - READ(2201, "已读", false, false), - - // ========== 实时通话信令(1601-1605 段位与 OpenIM 对齐;1610+ 自有扩展) ========== - /** - * 对应 OpenIM:SignalingNotification 1601(通话信令统一入口) - * 对应自己的类:ImRtcCallNotification - * 场景:通话信令;不入库,走 imWebSocketService 仅推参与方;status 复用参与者状态枚举区分 INVITING / JOINED / REJECTED / NO_ANSWER / LEFT - */ - RTC_CALL(1601, "通话信令", false, false), - /** - * 对应 OpenIM:RoomParticipantsConnectedNotification 1602 - * 对应自己的类:ImRtcParticipantConnectedNotification - * 场景:通话参与者加入;LiveKit webhook participant_joined 触发;私聊推 peer 多端 + inviter 多端,群聊全群广播;不入库 - */ - RTC_PARTICIPANT_CONNECTED(1602, "通话参与者加入", false, false), - /** - * 对应 OpenIM:RoomParticipantsDisconnectedNotification 1603 - * 对应自己的类:ImRtcParticipantDisconnectedNotification - * 场景:通话参与者离开;LiveKit webhook participant_left 触发;推送范围同 1602;不入库 - */ - RTC_PARTICIPANT_DISCONNECTED(1603, "通话参与者离开", false, false), - // 1604-1609 OpenIM 已用 / 留作扩展,本系统暂不使用 - /** - * 对应 OpenIM:无(自有扩展,OpenIM 通话事件不入消息流) - * 对应自己的类:ImRtcCallStartNotification - * 场景:通话开始;群聊入 im_group_message 全群广播,前端渲染聊天 tip「{inviterNickname} 发起了语音通话」; - * 私聊入 im_private_message 定向给被叫,仅用于会话列表预览展示「[语音通话]」(不渲染聊天 tip) - *

- * 与 RTC_CALL_END(1611) 两段式配对:START 一定先于 END 入库(START 在 invite 接口事务里、END 在 cancel/leave 接口事务里,自然按请求顺序串行) - */ - RTC_CALL_START(1610, "通话开始", true, false), - /** - * 对应 OpenIM:无(自有扩展,OpenIM 通话事件不入消息流) - * 对应自己的类:ImRtcCallEndNotification - * 场景:通话结束;入 im_private_message / im_group_message;私聊渲染准气泡,群聊渲染 tip「语音通话已经结束」 - *

- * 与 RTC_CALL_START(1610) 两段式配对 - */ - RTC_CALL_END(1611, "通话结束", true, false), - - // ========== 好友通知(1201-1210 直接复用 OpenIM 段位编号) ========== - /** - * 对应 OpenIM:FriendApplicationApprovedNotification 1201 - * 对应自己的类:FriendRequestApprovedNotification - * 场景:B 同意 A 的好友申请,推给 A 多端 - */ - FRIEND_REQUEST_APPROVED(1201, "好友申请被同意", false, false), - /** - * 对应 OpenIM:FriendApplicationRejectedNotification 1202 - * 对应自己的类:FriendRequestRejectedNotification - * 场景:B 拒绝 A 的好友申请,推给 A 多端 - */ - FRIEND_REQUEST_REJECTED(1202, "好友申请被拒绝", false, false), - /** - * 对应 OpenIM:FriendApplicationNotification 1203 - * 对应自己的类:FriendRequestNotification - * 场景:A 申请加 B,推给 B 多端,前端落到「新的朋友」列表 - */ - FRIEND_REQUEST_RECEIVED(1203, "收到新的好友申请", false, false), - /** - * 对应 OpenIM:FriendAddedNotification 1204(OpenIM friendAdded.isSendMsg=false 默认不入消息流;本系统改为入库当会话气泡) - * 对应自己的类:FriendAddNotification - * 场景:双方建立好友关系,单条入库(sender=fromUserId, receiver=toUserId);双向 WebSocket 自动覆盖双方多端 - * 注意:silentReAddFriend 单边语义场景,发送时显式 setPersistent(false) 覆盖默认值 - */ - FRIEND_ADD(1204, "新增好友", true, false), - /** - * 对应 OpenIM:FriendDeletedNotification 1205 - * 对应自己的类:FriendDeleteNotification - * 场景:A 删除 B,推给 A、B 双方多端 - */ - FRIEND_DELETE(1205, "好友被删除", false, false), - // 1206 对应 OpenIM FriendRemarkSetNotification;本系统并入 FRIEND_UPDATE(1210) 统一推送,单一字段变更不再独立通道 - /** - * 对应 OpenIM:BlackAddedNotification 1207 - * 对应自己的类:FriendBlockNotification - * 场景:A 拉黑 B,仅推 A 多端 - */ - FRIEND_BLOCK(1207, "加入黑名单", false, false), - /** - * 对应 OpenIM:BlackDeletedNotification 1208 - * 对应自己的类:FriendUnblockNotification - * 场景:A 移出 B 的黑名单,仅推 A 多端 - */ - FRIEND_UNBLOCK(1208, "移出黑名单", false, false), - /** - * 对应 OpenIM:FriendInfoUpdatedNotification 1209 - * 对应自己的类:FriendInfoUpdatedNotification - * 场景:B 改了昵称 / 头像后,推给 B 的所有好友 - * 触发:system 模块发 AdminUserProfileUpdateMessage,IM 消费者 AdminUserProfileUpdateConsumer 批量推此通知 - */ - FRIEND_INFO_UPDATED(1209, "好友资料变更", false, false), - /** - * 对应 OpenIM:FriendsInfoUpdateNotification 1210(窄化到 silent / pinned 单边属性) - * 对应自己的类:FriendUpdateNotification - * 场景:A 改了 silent / pinned 等单边属性,推 A 多端 - */ - FRIEND_UPDATE(1210, "好友信息批量更新", false, false), - - // ========== 群事件(1501-1520 直接复用 OpenIM 段位编号;1530+ 我们独有扩展) ========== - // 1500 对应 OpenIM GroupNotificationBegin 起始位,仅作占位,不使用 - /** - * 对应 OpenIM:sdkws.GroupCreatedTips(GroupCreatedNotification 1501) - * 对应自己的类:GroupCreateNotification - * 场景:用户创建群(同时邀请初始成员),全员广播(含创建者多端同步 + 初始成员) - */ - GROUP_CREATE(1501, "群创建", true, false), - /** - * 对应 OpenIM:sdkws.GroupInfoSetTips(GroupInfoSetNotification 1502,NAME / NOTICE 之外字段的 generic 兜底) - * 对应自己的类:GroupInfoUpdateNotification - * 场景:群主修改群头像 / 简介等字段后全员广播 - */ - GROUP_INFO_UPDATE(1502, "群信息变更", true, false), - /** - * 对应 OpenIM:sdkws.JoinGroupApplicationTips(JoinGroupApplicationNotification 1503) - * 对应自己的类:GroupRequestReceivedNotification - * 场景:用户申请加群 / 普通成员邀请待审批,定向私聊推送给群主 + 全部管理员(多端同步);不入群消息流 - */ - GROUP_REQUEST_RECEIVED(1503, "收到新的入群申请", false, false), - /** - * 对应 OpenIM:sdkws.MemberQuitTips(MemberQuitNotification 1504) - * 对应自己的类:GroupMemberQuitNotification - * 场景:成员主动退群(send-before-remove),全员广播(含 quitter);quitter 自判 operatorUserId === self → removeGroup - */ - GROUP_MEMBER_QUIT(1504, "成员退群", true, false), - /** - * 对应 OpenIM:sdkws.GroupApplicationAcceptedTips(GroupApplicationAcceptedNotification 1505) - * 对应自己的类:GroupRequestApprovedNotification - * 场景:群主 / 管理员同意申请,定向私聊推送给申请人 + 群主 + 全部管理员;申请人侧弹 toast,admin 侧 pendingRequestCount-1;不入群消息流 - */ - GROUP_REQUEST_APPROVED(1505, "入群申请被同意", false, false), - /** - * 对应 OpenIM:sdkws.GroupApplicationRejectedTips(GroupApplicationRejectedNotification 1506) - * 对应自己的类:GroupRequestRejectedNotification - * 场景:群主 / 管理员拒绝申请,定向私聊推送给申请人 + 群主 + 全部管理员;不入群消息流 - */ - GROUP_REQUEST_REJECTED(1506, "入群申请被拒绝", false, false), - /** - * 对应 OpenIM:sdkws.GroupOwnerTransferredTips(GroupOwnerTransferredNotification 1507) - * 对应自己的类:GroupOwnerTransferNotification - * 场景:群主转让,全员广播;前端 transferOwner 把 ownerUserId 切到新值 + 旧群主 role → NORMAL / 新群主 role → OWNER - */ - GROUP_OWNER_TRANSFER(1507, "群主转让", true, false), - /** - * 对应 OpenIM:sdkws.MemberKickedTips(MemberKickedNotification 1508) - * 对应自己的类:GroupMemberKickNotification - * 场景:群主 / 管理员移出成员(send-before-remove),全员广播(含被踢者);被踢者自判 memberUserIds 含 self → removeGroup - */ - GROUP_MEMBER_KICK(1508, "成员被移出", true, false), - /** - * 对应 OpenIM:sdkws.MemberInvitedTips(MemberInvitedNotification 1509) - * 对应自己的类:GroupMemberInviteNotification - * 场景:成员邀请新人入群,全员广播(含被邀请者);被邀请人前端按 memberUserIds 含自己自判,初次拉取 fetchGroupInfo + fetchGroupMembers - */ - GROUP_MEMBER_INVITE(1509, "成员加入", true, false), - /** - * 对应 OpenIM:sdkws.MemberEnterTips(MemberEnterNotification 1510) - * 对应自己的类:GroupMemberEnterNotification - * 场景:用户经搜索 / 二维码 / 分享链接自由进群(FREE 模式或审批通过后),全员广播;前端按 entrantUserId 局部添加成员 - */ - GROUP_MEMBER_ENTER(1510, "自由进群", true, false), - /** - * 对应 OpenIM:sdkws.GroupDismissedTips(GroupDismissedNotification 1511) - * 对应自己的类:GroupDissolveNotification - * 场景:群主解散群(send-before-remove),全员广播(含群主多端同步);前端 removeGroup 清群;离场用户离线 pull 通过 quit 路径(send_time < quit_time)也能拉到 - */ - GROUP_DISSOLVE(1511, "群解散", true, false), - /** - * 对应 OpenIM:sdkws.GroupMemberMutedTips(GroupMemberMutedNotification 1512) - * 对应自己的类:GroupMemberMutedNotification - * 场景:群主 / 管理员禁言某成员,全员广播 - */ - GROUP_MEMBER_MUTED(1512, "成员禁言", true, false), - /** - * 对应 OpenIM:sdkws.GroupMemberCancelMutedTips(GroupMemberCancelMutedNotification 1513) - * 对应自己的类:GroupMemberCancelMutedNotification - * 场景:群主 / 管理员取消某成员禁言,全员广播 - */ - GROUP_MEMBER_CANCEL_MUTED(1513, "成员取消禁言", true, false), - /** - * 对应 OpenIM:sdkws.GroupMutedTips(GroupMutedNotification 1514) - * 对应自己的类:GroupMutedNotification - * 场景:群主 / 管理员开启全群禁言,全员广播 - */ - GROUP_MUTED(1514, "全群禁言", true, false), - /** - * 对应 OpenIM:sdkws.GroupCancelMutedTips(GroupCancelMutedNotification 1515) - * 对应自己的类:GroupCancelMutedNotification - * 场景:群主 / 管理员取消全群禁言,全员广播 - */ - GROUP_CANCEL_MUTED(1515, "全群取消禁言", true, false), - /** - * 对应 OpenIM:sdkws.GroupMemberInfoSetTips(GroupMemberInfoSetNotification 1516,窄化到 displayUserName) - * 对应自己的类:GroupMemberNicknameUpdateNotification - * 场景:成员修改自己在群里的昵称,全员广播;前端按 displayUserName 局部更新对应 member - */ - GROUP_MEMBER_NICKNAME_UPDATE(1516, "成员昵称变更", true, false), - /** - * 对应 OpenIM:GroupMemberSetToAdminNotification 1517 - * 对应自己的类:GroupAdminAddNotification - * 场景:群主设置管理员,全员广播;前端 updateMembersRole 把对应成员 role 提升为 ADMIN - */ - GROUP_ADMIN_ADD(1517, "添加管理员", true, false), - /** - * 对应 OpenIM:GroupMemberSetToOrdinaryUserNotification 1518 - * 对应自己的类:GroupAdminRemoveNotification - * 场景:群主撤销管理员,全员广播;前端 updateMembersRole 把对应成员 role 降级为 NORMAL - */ - GROUP_ADMIN_REMOVE(1518, "撤销管理员", true, false), - /** - * 对应 OpenIM:sdkws.GroupInfoSetAnnouncementTips(GroupInfoSetAnnouncementNotification 1519) - * 对应自己的类:GroupNoticeUpdateNotification - * 场景:群主修改群公告后全员广播 - */ - GROUP_NOTICE_UPDATE(1519, "群公告变更", true, false), - /** - * 对应 OpenIM:sdkws.GroupInfoSetNameTips(GroupInfoSetNameNotification 1520) - * 对应自己的类:GroupNameUpdateNotification - * 场景:群主修改群名后全员广播 - */ - GROUP_NAME_UPDATE(1520, "群名变更", true, false), - - // 1530+ 我们独有扩展段(OpenIM 1500-1520 段位无对应物) - /** - * 对应 OpenIM:无直接对应(OpenIM 走 ConversationChangeNotification 1300 单聊路径) - * 对应自己的类:GroupMemberSettingUpdateNotification - * 场景:用户改自己的群免打扰 / 群备注,仅推该用户其他在线终端做多端同步 - */ - GROUP_MEMBER_SETTING_UPDATE(1530, "群成员个人设置变更", false, false), - /** - * 对应 OpenIM:无(OpenIM 无群消息置顶功能,自有扩展) - * 对应自己的类:GroupMessagePinNotification - * 场景:群主 / 管理员置顶一条群消息,全员广播;payload 直接带消息对象,前端把 message push 进 group.pinnedMessages - */ - GROUP_MESSAGE_PIN(1531, "群消息置顶", true, false), - /** - * 对应 OpenIM:无(OpenIM 无群消息置顶功能,自有扩展) - * 对应自己的类:GroupMessageUnpinNotification - * 场景:群主 / 管理员取消置顶,全员广播;前端按 messageId 从 group.pinnedMessages 移除 - */ - GROUP_MESSAGE_UNPIN(1532, "群消息取消置顶", true, false), - /** - * 对应 OpenIM:无(OpenIM 无群封禁概念,自有扩展) - * 对应自己的类:GroupBannedNotification - * 场景:管理后台封禁 / 解封群,全员广播;前端按 banned 字段切换输入栏封禁覆盖层 - */ - GROUP_BANNED(1533, "群封禁变更", true, false); - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImMessageTypeEnum::getType).toArray(Integer[]::new); - - private static final Set FRIEND_NOTIFICATION_TYPES = CollUtil.newHashSet( - FRIEND_REQUEST_APPROVED.type, - FRIEND_REQUEST_REJECTED.type, - FRIEND_REQUEST_RECEIVED.type, - FRIEND_ADD.type, - FRIEND_DELETE.type, - FRIEND_BLOCK.type, - FRIEND_UNBLOCK.type, - FRIEND_INFO_UPDATED.type, - FRIEND_UPDATE.type); - - private static final Set GROUP_REQUEST_NOTIFICATION_TYPES = CollUtil.newHashSet( - GROUP_REQUEST_RECEIVED.type, - GROUP_REQUEST_APPROVED.type, - GROUP_REQUEST_REJECTED.type); - - private static final Set RTC_NOTIFICATION_TYPES = CollUtil.newHashSet( - RTC_CALL.type, - RTC_PARTICIPANT_CONNECTED.type, - RTC_PARTICIPANT_DISCONNECTED.type); - - /** - * 类型 - */ - private final Integer type; - /** - * 名字 - */ - private final String name; - /** - * 是否入库 - *

- * true:插入 im_xxx_message 消息表,离线 pull 能拉到; - * false:仅 WebSocket 推送,离线丢弃;状态由专用存储维护(如 READ 走 Redis 游标) - */ - private final boolean persistent; - /** - * 是不是用户聊天消息(normal vs event 二分) - *

- * true:用户主动发的聊天消息,计入会话未读数(接收方非激活会话时 unreadCount + 1);用户发送入口仅允许这类; - * false:系统事件 / 信号 / 提示,不参与未读计数 - */ - private final boolean normal; - - @Override - public Integer[] array() { - return ARRAYS; - } - - /** - * 校验 type 已注册,并返回对应枚举;未注册立刻抛异常,避免新增 type 时漏配 persistent / normal 属性 - * - * @param type 消息类型 - * @return 枚举实例 - */ - public static ImMessageTypeEnum validate(Integer type) { - ImMessageTypeEnum result = ArrayUtil.firstMatch(item -> item.type.equals(type), values()); - Assert.notNull(result, "未注册的消息类型 type={}", type); - return result; - } - - /** - * 判断是否为好友通知 - */ - public static boolean isFriendNotification(Integer type) { - return type != null && FRIEND_NOTIFICATION_TYPES.contains(type); - } - - /** - * 判断是否为群申请定向通知 - */ - public static boolean isGroupRequestNotification(Integer type) { - return type != null && GROUP_REQUEST_NOTIFICATION_TYPES.contains(type); - } - - /** - * 判断是否为通话信令通知 - */ - public static boolean isRtcNotification(Integer type) { - return type != null && RTC_NOTIFICATION_TYPES.contains(type); - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java index 0a682cf..57262a1 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendRequestApprovedNotification; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendRequestNotification; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.FriendRequestRejectedNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestApprovedNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.friend.FriendRequestRejectedNotification; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java index ff23b13..9a4f4dd 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService; import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.BaseGroupNotification; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestApprovedNotification; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestReceivedNotification; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestRejectedNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.group.BaseGroupNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestApprovedNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestReceivedNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.group.GroupRequestRejectedNotification; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; @@ -97,7 +96,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { // 3. 情况二:群开启了审批,创建或复用一条主动申请记录 ImGroupRequestDO request = createOrResetApplyRequest(groupId, userId, reqVO); - // 4. 1503 私聊定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像 + // 4. 1503 定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像 AdminUserRespDTO applyUser = adminUserApi.getUser(userId); GroupRequestReceivedNotification payload = buildRequestNotification(group, request, applyUser); for (Long receiverUserId : getGroupMemberListByOwnerAndAdminUserIds(group)) { @@ -139,12 +138,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { groupMemberService.addGroupMember(request.getGroupId(), request.getUserId(), ImGroupMemberRoleEnum.NORMAL.getRole(), request.getAddSource(), request.getInviterUserId()); - // 5.1 1505 私聊推送给申请人 + 群主 + 全部管理员(每端单推) + // 5.1 1505 定向推送给申请人 + 群主 + 全部管理员(每端单推) GroupRequestApprovedNotification payload = (GroupRequestApprovedNotification) new GroupRequestApprovedNotification() .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId()) .setOperatorUserId(userId); broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload, - ImMessageTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId); + ImContentTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId); // 5.2 群事件:主动申请 → 1510 自由进群;被邀请 → 1509 成员加入 if (request.getInviterUserId() == null) { groupMessageService.sendGroupMessage(userId, @@ -174,12 +173,12 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { throw exception(GROUP_REQUEST_HANDLED); } - // 3. 1506 私聊推送给申请人 + 群主 + 全部管理员 + // 3. 1506 定向推送给申请人 + 群主 + 全部管理员 GroupRequestRejectedNotification payload = (GroupRequestRejectedNotification) new GroupRequestRejectedNotification() .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId()) .setHandleContent(handleContent).setOperatorUserId(userId); broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload, - ImMessageTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId); + ImContentTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId); } @Override @@ -395,7 +394,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { } /** - * 1505 / 1506 受众:申请人 + 群主 + 全部管理员;每端单独推一帧,前端按 receiver 是否申请人区分文案 + * 1505 / 1506 受众:申请人 + 群主 + 全部管理员 */ private void broadcastToOwnerAdminsAndApplicant(Long groupId, Long applicantUserId, BaseGroupNotification payload, Integer messageType, Long operatorUserId) { diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java index 1361710..21e72f1 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum; import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.friend.ImFriendService; import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService; @@ -436,7 +436,7 @@ public class ImGroupServiceImpl implements ImGroupService { if (message == null || ObjUtil.notEqual(message.getGroupId(), groupId)) { throw exception(MESSAGE_NOT_IN_GROUP); } - if (!ImMessageTypeEnum.validate(message.getType()).isNormal() + if (!ImContentTypeEnum.validate(message.getType()).isNormal() || ImMessageStatusEnum.RECALL.getStatus().equals(message.getStatus())) { throw exception(MESSAGE_NOT_IN_GROUP); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageServiceImpl.java index ab6edf5..1b30850 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImChannelMessageServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO; import cn.iocoder.yudao.module.im.dal.mysql.message.ImChannelMessageMapper; import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.service.channel.ImChannelMaterialService; import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.MaterialMessage; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImChannelMessageNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReadNotification; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.MaterialMessage; import jakarta.annotation.Resource; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -116,7 +117,7 @@ public class ImChannelMessageServiceImpl implements ImChannelMessageService { String payloadJson = JsonUtils.toJsonString(payload); // 2.2 落库 1 行 message;reqVO 同名字段(materialId / receiverUserIds)自动拷贝,剩余字段补 set ImChannelMessageDO message = BeanUtils.toBean(reqVO, ImChannelMessageDO.class).setChannelId(material.getChannelId()) - .setType(ImMessageTypeEnum.MATERIAL.getType()).setContent(payloadJson).setSendTime(LocalDateTime.now()); + .setType(ImContentTypeEnum.MATERIAL.getType()).setContent(payloadJson).setSendTime(LocalDateTime.now()); channelMessageMapper.insert(message); // 3. 异步推 WebSocket:指定用户走点对点;全员(receiverUserIds 为空)走广播 diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java index 102ff71..f8fc29a 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService; import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService; @@ -28,9 +28,11 @@ import cn.iocoder.yudao.module.im.service.group.ImGroupService; import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReadNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReceiptNotification; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.RecallMessage; import cn.iocoder.yudao.module.im.util.ImMessageUtils; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -93,7 +95,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { // 1.4 禁言校验 validateMuteStatus(group, senderMember); // 1.5 文本消息敏感词过滤 - if (ImMessageTypeEnum.TEXT.getType().equals(reqVO.getType())) { + if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) { sensitiveWordService.validateText(reqVO.getContent()); } @@ -142,7 +144,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { .setAtUserIds(dto.getAtUserIds()).setReceiverUserIds(new ArrayList<>(receiverUserIds)) .setReceiptStatus(resolveReceiptStatus(dto.getReceipt())); // 1.3 按 type.persistent 决定是否入库 - if (ImMessageTypeEnum.validate(dto.getType()).isPersistent()) { + if (ImContentTypeEnum.validate(dto.getType()).isPersistent()) { groupMessageMapper.insert(message); } @@ -181,7 +183,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { // 3. 发送撤回事件 return sendGroupMessage(userId, new ImGroupMessageSendDTO().setGroupId(message.getGroupId()) - .setType(ImMessageTypeEnum.RECALL.getType()) + .setType(ImContentTypeEnum.RECALL.getType()) .setReceiverUserIds(message.getReceiverUserIds()) .setContent(new RecallMessage().setMessageId(messageId))); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java index 8b5af38..ffb4f4f 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService; import cn.iocoder.yudao.module.im.service.friend.ImFriendService; import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO; import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReadNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImMessageReceiptNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImPrivateMessageNotification; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.RecallMessage; import cn.iocoder.yudao.module.im.util.ImMessageUtils; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -80,7 +82,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { // 1.3 好友校验 friendService.validateFriend(senderId, reqVO.getReceiverId()); // 1.4 文本消息敏感词过滤 - if (ImMessageTypeEnum.TEXT.getType().equals(reqVO.getType())) { + if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) { sensitiveWordService.validateText(reqVO.getContent()); } @@ -123,7 +125,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { // 1.3 决定是否持久化:dto.persistent 优先;为 null 时按 type 默认 boolean persistent = dto.getPersistent() != null ? dto.getPersistent() - : ImMessageTypeEnum.validate(dto.getType()).isPersistent(); + : ImContentTypeEnum.validate(dto.getType()).isPersistent(); if (persistent) { privateMessageMapper.insert(message); } @@ -177,7 +179,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { // 3. 发送撤回事件 return sendPrivateMessage(userId, new ImPrivateMessageSendDTO().setReceiverId(message.getReceiverId()) - .setType(ImMessageTypeEnum.RECALL.getType()).setContent(new RecallMessage().setMessageId(messageId))); + .setType(ImContentTypeEnum.RECALL.getType()).setContent(new RecallMessage().setMessageId(messageId))); } /** diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImGroupMessageSendDTO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImGroupMessageSendDTO.java index 95f4234..749b5c5 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImGroupMessageSendDTO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImGroupMessageSendDTO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.im.service.message.dto; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.*; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; +import cn.iocoder.yudao.module.im.service.websocket.notification.group.*; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -26,7 +26,7 @@ public class ImGroupMessageSendDTO { /** * 消息类型 *

- * 枚举 {@link ImMessageTypeEnum} + * 枚举 {@link ImContentTypeEnum} */ @NotNull(message = "消息类型不能为空") private Integer type; @@ -53,14 +53,14 @@ public class ImGroupMessageSendDTO { */ private Boolean receipt; - // ========== 群广播事件静态工厂(对应 ImMessageTypeEnum 群事件) ========== + // ========== 群广播事件静态工厂(对应 ImContentTypeEnum 群事件) ========== public static ImGroupMessageSendDTO ofGroupCreate(Long groupId, Long operatorUserId, Collection memberUserIds) { GroupCreateNotification notification = new GroupCreateNotification(); notification.setOperatorUserId(operatorUserId); notification.setMemberUserIds(new ArrayList<>(memberUserIds)); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_CREATE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_CREATE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupInfoUpdate(Long groupId, Long operatorUserId, String oldAvatar, String newAvatar) { @@ -69,14 +69,14 @@ public class ImGroupMessageSendDTO { notification.setOldAvatar(oldAvatar); notification.setNewAvatar(newAvatar); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_INFO_UPDATE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_INFO_UPDATE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberQuit(Long groupId, Long operatorUserId) { GroupMemberQuitNotification notification = new GroupMemberQuitNotification(); notification.setOperatorUserId(operatorUserId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_QUIT.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_QUIT.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupOwnerTransfer(Long groupId, Long operatorUserId, Long newOwnerUserId) { @@ -84,7 +84,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setNewOwnerUserId(newOwnerUserId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_OWNER_TRANSFER.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_OWNER_TRANSFER.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberKick(Long groupId, Long operatorUserId, Collection memberUserIds) { @@ -92,7 +92,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMemberUserIds(new ArrayList<>(memberUserIds)); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_KICK.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_KICK.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberInvite(Long groupId, Long operatorUserId, Collection memberUserIds) { @@ -100,7 +100,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMemberUserIds(new ArrayList<>(memberUserIds)); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberEnter(Long groupId, Long entrantUserId, Integer addSource) { @@ -109,14 +109,14 @@ public class ImGroupMessageSendDTO { notification.setEntrantUserId(entrantUserId); notification.setAddSource(addSource); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupDissolve(Long groupId, Long operatorUserId) { GroupDissolveNotification notification = new GroupDissolveNotification(); notification.setOperatorUserId(operatorUserId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_DISSOLVE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_DISSOLVE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberNicknameUpdate(Long groupId, Long operatorUserId, String displayUserName) { @@ -124,7 +124,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setDisplayUserName(displayUserName); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupAdminAdd(Long groupId, Long operatorUserId, Collection memberUserIds) { @@ -132,7 +132,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMemberUserIds(new ArrayList<>(memberUserIds)); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_ADMIN_ADD.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_ADMIN_ADD.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupAdminRemove(Long groupId, Long operatorUserId, Collection memberUserIds) { @@ -140,7 +140,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMemberUserIds(new ArrayList<>(memberUserIds)); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_ADMIN_REMOVE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_ADMIN_REMOVE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupNoticeUpdate(Long groupId, Long operatorUserId, String oldNotice, String newNotice) { @@ -148,7 +148,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setOldNotice(oldNotice).setNewNotice(newNotice); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_NOTICE_UPDATE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_NOTICE_UPDATE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupNameUpdate(Long groupId, Long operatorUserId, String oldName, String newName) { @@ -156,7 +156,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setOldName(oldName).setNewName(newName); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_NAME_UPDATE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_NAME_UPDATE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberSettingUpdate(Long groupId, Long operatorUserId, Boolean silent, String groupRemark) { @@ -164,7 +164,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setSilent(silent).setGroupRemark(groupRemark); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_SETTING_UPDATE.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_SETTING_UPDATE.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMessagePin(Long groupId, Long operatorUserId, ImGroupMessageDO message) { @@ -176,7 +176,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMessageId(message.getId()).setMessage(pinnedMessage); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MESSAGE_PIN.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MESSAGE_PIN.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMessageUnpin(Long groupId, Long operatorUserId, Long messageId) { @@ -184,7 +184,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMessageId(messageId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MESSAGE_UNPIN.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MESSAGE_UNPIN.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberMuted(Long groupId, Long operatorUserId, @@ -195,7 +195,7 @@ public class ImGroupMessageSendDTO { notification.setMutedUserId(mutedUserId); notification.setMuteEndTime(muteEndTime); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_MUTED.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_MUTED.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMemberCancelMuted(Long groupId, Long operatorUserId, Long mutedUserId) { @@ -203,21 +203,21 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setMutedUserId(mutedUserId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MEMBER_CANCEL_MUTED.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MEMBER_CANCEL_MUTED.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupMuted(Long groupId, Long operatorUserId) { GroupMutedNotification notification = new GroupMutedNotification(); notification.setOperatorUserId(operatorUserId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_MUTED.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_MUTED.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupCancelMuted(Long groupId, Long operatorUserId) { GroupCancelMutedNotification notification = new GroupCancelMutedNotification(); notification.setOperatorUserId(operatorUserId); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_CANCEL_MUTED.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_CANCEL_MUTED.getType()).setContent(notification); } public static ImGroupMessageSendDTO ofGroupBanned(Long groupId, Long operatorUserId, boolean banned) { @@ -225,7 +225,7 @@ public class ImGroupMessageSendDTO { notification.setOperatorUserId(operatorUserId); notification.setBanned(banned); return new ImGroupMessageSendDTO().setGroupId(groupId) - .setType(ImMessageTypeEnum.GROUP_BANNED.getType()).setContent(notification); + .setType(ImContentTypeEnum.GROUP_BANNED.getType()).setContent(notification); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImPrivateMessageSendDTO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImPrivateMessageSendDTO.java index 5f8b025..5758c3b 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImPrivateMessageSendDTO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/dto/ImPrivateMessageSendDTO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.im.service.message.dto; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import lombok.Data; /** @@ -18,7 +18,7 @@ public class ImPrivateMessageSendDTO { /** * 消息类型 *

- * 枚举 {@link ImMessageTypeEnum} + * 枚举 {@link ImContentTypeEnum} */ private Integer type; /** @@ -30,7 +30,7 @@ public class ImPrivateMessageSendDTO { /** * 是否持久化 + 推送给接收方(单边语义开关) *

- * null:默认按 {@link ImMessageTypeEnum#isPersistent()} 决定是否入库 + 双向 WS 推送(保持原行为)
+ * null:默认按 {@link ImContentTypeEnum#isPersistent()} 决定是否入库 + 双向 WS 推送(保持原行为)
* false:覆盖为单边——不入库、仅推 sender 多端,对方不感知(如「你已删除 XXX」这类仅自己可见的 TIP)
* true:覆盖为双向 + 入库 */ diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java index a02f94b..2d5b36a 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.im.dal.mysql.rtc.ImRtcParticipantMapper; import cn.iocoder.yudao.module.im.dal.redis.rtc.ImRtcCallLockRedisDAO; import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallEndReasonEnum; import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallStatusEnum; import cn.iocoder.yudao.module.im.enums.rtc.ImRtcParticipantRoleEnum; @@ -30,8 +30,7 @@ import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService; import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc.*; +import cn.iocoder.yudao.module.im.service.websocket.notification.rtc.*; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; @@ -1047,7 +1046,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { * @param userId 加入的参与者用户编号 */ private void pushParticipantConnectedNotification(ImRtcCallDO call, Long userId) { - pushParticipantNotification(call, ImMessageTypeEnum.RTC_PARTICIPANT_CONNECTED.getType(), userId, + pushParticipantNotification(call, ImContentTypeEnum.RTC_PARTICIPANT_CONNECTED.getType(), userId, ImRtcParticipantConnectedNotification.of(call, userId)); } @@ -1058,7 +1057,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { * @param userId 离开的参与者用户编号 */ private void pushParticipantDisconnectedNotification(ImRtcCallDO call, Long userId) { - pushParticipantNotification(call, ImMessageTypeEnum.RTC_PARTICIPANT_DISCONNECTED.getType(), userId, + pushParticipantNotification(call, ImContentTypeEnum.RTC_PARTICIPANT_DISCONNECTED.getType(), userId, ImRtcParticipantDisconnectedNotification.of(call, userId)); } @@ -1091,7 +1090,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { private void pushCallStartNotification(ImRtcCallDO call, AdminUserRespDTO inviter, Set invitees) { ImRtcCallStartNotification payload = ImRtcCallStartNotification.of(call, inviter); Long peerUserId = ImConversationTypeEnum.isGroup(call.getConversationType()) ? null : CollUtil.getFirst(invitees); - pushCallChatMessage(call, ImMessageTypeEnum.RTC_CALL_START, payload, peerUserId); + pushCallChatMessage(call, ImContentTypeEnum.RTC_CALL_START, payload, peerUserId); } /** @@ -1115,7 +1114,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { p -> ObjUtil.notEqual(p.getUserId(), call.getInviterUserId())); peerUserId = peer != null ? peer.getUserId() : null; } - pushCallChatMessage(call, ImMessageTypeEnum.RTC_CALL_END, payload, peerUserId); + pushCallChatMessage(call, ImContentTypeEnum.RTC_CALL_END, payload, peerUserId); } /** @@ -1128,7 +1127,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { * @param payload 推送 payload * @param peerUserId 私聊对端用户编号;群聊忽略,私聊缺失时回退为 senderId */ - private void pushCallChatMessage(ImRtcCallDO call, ImMessageTypeEnum type, Object payload, Long peerUserId) { + private void pushCallChatMessage(ImRtcCallDO call, ImContentTypeEnum type, Object payload, Long peerUserId) { Long senderId = call.getInviterUserId(); if (ImConversationTypeEnum.isGroup(call.getConversationType())) { ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO().setGroupId(call.getGroupId()) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/statistics/ImStatisticsManagerService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/statistics/ImStatisticsManagerService.java index 5337bff..a21fc03 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/statistics/ImStatisticsManagerService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/statistics/ImStatisticsManagerService.java @@ -80,7 +80,7 @@ public interface ImStatisticsManagerService { Map getGroupMessageDailyCountMap(LocalDateTime beginTime, LocalDateTime endTime); /** - * 获取区间内消息类型分布 Map(key 为消息类型) + * 获取区间内内容类型分布 Map(key 为消息类型) */ Map getMessageTypeCountMap(LocalDateTime beginTime, LocalDateTime endTime); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketService.java index aedcfd3..2e7404c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketService.java @@ -1,82 +1,46 @@ package cn.iocoder.yudao.module.im.service.websocket; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; - import java.util.Collection; import java.util.Collections; /** * IM WebSocket 推送 Service 接口 *

- * 统一封装 WebSocket 消息推送,事务内调用时提交后异步执行。 + * 统一封装 WebSocket 通知推送,事务内调用时提交后异步执行。 * * @author 芋道源码 */ public interface ImWebSocketService { /** - * 异步推送私聊消息给指定用户 - * - * @param userId 目标用户编号 - * @param dto 私聊消息 DTO - */ - default void sendPrivateMessageAsync(Long userId, ImPrivateMessageDTO dto) { - sendPrivateMessageAsync(Collections.singleton(userId), dto); - } - - /** - * 异步批量推送私聊消息给多个用户;用于同一份 DTO 扇出到多个收件人 - *

- * 相比逐个发送,仅注册一次 afterCommit 回调和异步任务。 - * - * @param userIds 目标用户编号列表 - * @param dto 私聊消息 DTO - */ - void sendPrivateMessageAsync(Collection userIds, ImPrivateMessageDTO dto); - - /** - * 异步推送群聊消息给指定用户 - * - * @param userId 目标用户编号 - * @param dto 群聊消息 DTO - */ - default void sendGroupMessageAsync(Long userId, ImGroupMessageDTO dto) { - sendGroupMessageAsync(Collections.singleton(userId), dto); - } - - /** - * 异步批量推送群聊消息给多个用户 - * - * @param userIds 目标用户编号列表 - * @param dto 群聊消息 DTO - */ - void sendGroupMessageAsync(Collection userIds, ImGroupMessageDTO dto); - - /** - * 异步推送频道消息给指定用户 + * 异步推送 WebSocket 通知给指定用户 * - * @param userId 目标用户编号 - * @param dto 频道消息 DTO + * @param userId 目标用户编号 + * @param conversationType 会话类型,参见 ImConversationTypeEnum 枚举类 + * @param contentType 内容类型,参见 ImContentTypeEnum 枚举类 + * @param payload 通知 payload */ - default void sendChannelMessageAsync(Long userId, ImChannelMessageDTO dto) { - sendChannelMessageAsync(Collections.singleton(userId), dto); + default void sendNotificationAsync(Long userId, Integer conversationType, Integer contentType, Object payload) { + sendNotificationAsync(Collections.singleton(userId), conversationType, contentType, payload); } /** - * 异步批量推送频道消息给多个用户 + * 异步批量推送 WebSocket 通知给多个用户 * - * @param userIds 目标用户编号列表 - * @param dto 频道消息 DTO + * @param userIds 目标用户编号列表 + * @param conversationType 会话类型,参见 ImConversationTypeEnum 枚举类 + * @param contentType 内容类型,参见 ImContentTypeEnum 枚举类 + * @param payload 通知 payload */ - void sendChannelMessageAsync(Collection userIds, ImChannelMessageDTO dto); + void sendNotificationAsync(Collection userIds, Integer conversationType, Integer contentType, Object payload); /** - * 异步广播频道消息给当前所有在线管理端用户;用于全员推送 + * 异步广播 WebSocket 通知给当前所有在线管理端用户 * - * @param dto 频道消息 DTO + * @param conversationType 会话类型,参见 ImConversationTypeEnum 枚举类 + * @param contentType 内容类型,参见 ImContentTypeEnum 枚举类 + * @param payload 通知 payload */ - void broadcastChannelMessageAsync(ImChannelMessageDTO dto); + void broadcastNotificationAsync(Integer conversationType, Integer contentType, Object payload); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImpl.java index 2253943..e6ce822 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImpl.java +++ b/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; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImChannelMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; +import cn.iocoder.yudao.module.im.service.websocket.notification.ImNotificationWebSocketDTO; import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -88,31 +86,30 @@ public class ImWebSocketServiceImpl implements ImWebSocketService { } /** - * 异步发送频道 WebSocket 消息 + * 异步发送 WebSocket 通知 */ @Async - public void doSendChannelMessage(Collection userIds, ImChannelMessageDTO dto) { + public void doSendNotification(Collection userIds, ImNotificationWebSocketDTO notification) { for (Long userId : getDistinctUserIds(userIds)) { try { webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId, - ImChannelMessageDTO.TYPE, dto); + ImNotificationWebSocketDTO.TYPE, notification); } catch (Exception e) { - log.error("[doSendChannelMessage][userId({}) dto({}) 发送失败]", userId, dto, e); + log.error("[doSendNotification][userId({}) notification({}) 发送失败]", userId, notification, e); } } } /** - * 异步广播频道 WebSocket 消息给当前所有在线管理端用户; - * 依赖 infra WebSocketSenderApi 按 UserType 广播能力,离线用户由客户端上线 pull 兜底 + * 异步广播 WebSocket 通知 */ @Async - public void doBroadcastChannelMessage(ImChannelMessageDTO dto) { + public void doBroadcastNotification(ImNotificationWebSocketDTO notification) { try { webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), - ImChannelMessageDTO.TYPE, dto); + ImNotificationWebSocketDTO.TYPE, notification); } catch (Exception e) { - log.error("[doBroadcastChannelMessage][dto({}) 广播失败]", dto, e); + log.error("[doBroadcastNotification][notification({}) 广播失败]", notification, e); } } @@ -121,19 +118,15 @@ public class ImWebSocketServiceImpl implements ImWebSocketService { } /** - * 事务感知的任务调度: - * - 有事务:注册 afterCommit 回调,事务提交后再执行,防止客户端拿到消息去查库时数据还没落盘 - * - 无事务:直接执行(如非 @Transactional 方法中的调用) + * 事务感知的任务调度 * - * @param task 待执行的推送任务(内部通过 getSelf() 走 @Async 异步执行) + * @param task 待执行的推送任务 */ private void executeAfterTransaction(Runnable task) { - // 情况一:没有事务,直接执行 if (!TransactionSynchronizationManager.isSynchronizationActive()) { task.run(); return; } - // 情况二:有事务,注册 afterCommit 事件,在事务提交后执行 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImChannelMessageDTO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImChannelMessageDTO.java deleted file mode 100644 index 0478cd2..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImChannelMessageDTO.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto; - -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import lombok.Data; -import lombok.experimental.Accessors; - -import java.time.LocalDateTime; - -/** - * IM 频道消息 WebSocket 推送 DTO - *

- * 单向:服务端运营推送 → C 端用户;C 端不能向频道发消息。 - * 字段分层:顶层是消息元数据 + 检索维度,content 是 MaterialMessage payload 的 JSON 串。 - * - * @author 芋道源码 - */ -@Data -@Accessors(chain = true) -public class ImChannelMessageDTO { - - public static final String TYPE = "im-channel-message"; - - /** - * 消息编号 - */ - private Long id; - /** - * 频道编号 - */ - private Long channelId; - /** - * 关联素材编号 - */ - private Long materialId; - /** - * 消息类型 - */ - private Integer type; - /** - * 消息内容;payload JSON 串 - */ - private String content; - /** - * 发送时间 - */ - private LocalDateTime sendTime; - - /** - * 由频道消息 DO 构建推送 DTO - */ - public static ImChannelMessageDTO ofSend(ImChannelMessageDO message) { - return BeanUtils.toBean(message, ImChannelMessageDTO.class); - } - - /** - * 构建已读同步 DTO;多端同步:通知自己的其他终端「我已经读了某频道」 - * - * @param channelId 频道编号 - * @param readId 已读位置(最大已读消息编号) - * @return 频道 DTO - */ - public static ImChannelMessageDTO ofRead(Long channelId, Long readId) { - return new ImChannelMessageDTO() - .setId(readId).setType(ImMessageTypeEnum.READ.getType()) - .setChannelId(channelId); - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java deleted file mode 100644 index 254df98..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto; - -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * IM 群聊消息 WebSocket 统一推送 DTO - *

- * 发送、已读、回执都通过 {@link #type} 字段区分, - * 并统一复用 {@link #id} 字段表达目标消息或已读位置。 - * - * @author 芋道源码 - */ -@Data -public class ImGroupMessageDTO { - - public static final String TYPE = "im-group-message"; - - /** - * 消息编号 - *

- * 普通消息:当前消息 id - * READ:无(群已读不需要) - * RECEIPT:需要回执的目标消息 id - */ - private Long id; - /** - * 客户端消息编号 - */ - private String clientMessageId; - /** - * 发送人编号 - */ - private Long senderId; - /** - * 群编号 - */ - private Long groupId; - /** - * 消息类型 - */ - private Integer type; - /** - * 消息内容 - */ - private String content; - /** - * 消息状态 - */ - private Integer status; - /** - * 发送时间 - */ - private LocalDateTime sendTime; - /** - * @ 目标用户编号列表 - */ - private List atUserIds; - /** - * 定向接收用户编号列表 - */ - private List receiverUserIds; - /** - * 群回执状态 - */ - private Integer receiptStatus; - /** - * 群回执已读人数 - */ - private Integer readCount; - /** - * 已读位置 - */ - private Long readId; - - // ========== 静态工厂方法 ========== - - /** - * 构建发送消息 DTO - * - * @param message 群聊消息 DO - * @return 群聊 DTO - */ - public static ImGroupMessageDTO ofSend(ImGroupMessageDO message) { - return BeanUtils.toBean(message, ImGroupMessageDTO.class).setReceiverUserIds(null); - } - - /** - * 构建已读同步 DTO(多端同步:通知自己的其他终端"我已经读了某个群") - * - * @param senderId 当前用户编号 - * @param groupId 群编号 - * @param readId 已读位置(最大已读消息编号) - * @return 群聊 DTO - */ - public static ImGroupMessageDTO ofRead(Long senderId, Long groupId, Long readId) { - return new ImGroupMessageDTO() - .setId(readId).setReadId(readId).setType(ImMessageTypeEnum.READ.getType()) - .setSenderId(senderId).setGroupId(groupId); - } - - /** - * 构建群回执 DTO(广播回执状态和已读人数) - * - * @param messageId 消息编号 - * @param groupId 群编号 - * @param readCount 已读人数 - * @param receiptStatus 回执状态 - * @return 群聊 DTO - */ - public static ImGroupMessageDTO ofReceipt(Long messageId, Long groupId, - Integer readCount, Integer receiptStatus) { - return new ImGroupMessageDTO() - .setId(messageId).setType(ImMessageTypeEnum.RECEIPT.getType()) - .setGroupId(groupId).setReadCount(readCount).setReceiptStatus(receiptStatus); - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImPrivateMessageDTO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImPrivateMessageDTO.java deleted file mode 100644 index 823e637..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImPrivateMessageDTO.java +++ /dev/null @@ -1,180 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto; - -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.BaseFriendNotification; -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.BaseGroupNotification; -import lombok.Data; -import lombok.experimental.Accessors; - -import java.time.LocalDateTime; - -/** - * IM 私聊消息 WebSocket 统一推送 DTO - *

- * 发送、已读、回执、撤回都通过 {@link #type} 字段区分, - * 并统一复用 {@link #id} 字段表达目标消息或已读位置。 - * - * @author 芋道源码 - */ -@Data -@Accessors(chain = true) -public class ImPrivateMessageDTO { - - public static final String TYPE = "im-private-message"; - - /** - * 消息编号 - *

- * 普通消息:当前消息 id - * READ:已读位置(我已读到这条消息) - * RECEIPT:已读位置(对方已读到这条消息) - * RECALL:被撤回的原消息 id - */ - private Long id; - /** - * 客户端消息编号 - */ - private String clientMessageId; - /** - * 发送人编号 - */ - private Long senderId; - /** - * 接收人编号 - */ - private Long receiverId; - /** - * 消息类型 - */ - private Integer type; - /** - * 消息内容 - */ - private String content; - /** - * 消息状态 - */ - private Integer status; - /** - * 回执状态 - */ - private Integer receiptStatus; - /** - * 发送时间 - */ - private LocalDateTime sendTime; - - // ========== 静态工厂方法 ========== - - /** - * 构建发送消息 DTO - * - * @param message 私聊消息 DO - * @return 私聊 DTO - */ - public static ImPrivateMessageDTO ofSend(ImPrivateMessageDO message) { - return BeanUtils.toBean(message, ImPrivateMessageDTO.class); - } - - /** - * 构建已读同步 DTO(多端同步:通知自己的其他终端"我已经读了某个会话") - * - * @param senderId 当前用户编号 - * @param receiverId 对方用户编号 - * @param readId 已读位置(最大已读消息编号) - * @return 私聊 DTO - */ - public static ImPrivateMessageDTO ofRead(Long senderId, Long receiverId, Long readId) { - return new ImPrivateMessageDTO() - .setId(readId).setType(ImMessageTypeEnum.READ.getType()) - .setSenderId(senderId).setReceiverId(receiverId); - } - - /** - * 构建已读回执 DTO(通知对方"我已读了你的消息") - * - * @param senderId 已读方的用户编号 - * @param receiverId 对方用户编号 - * @param readId 已读位置(最大已读消息编号) - * @return 私聊 DTO - */ - public static ImPrivateMessageDTO ofReceipt(Long senderId, Long receiverId, Long readId) { - return new ImPrivateMessageDTO() - .setId(readId).setType(ImMessageTypeEnum.RECEIPT.getType()) - .setSenderId(senderId).setReceiverId(receiverId); - } - - // ==================== 好友变更相关 ==================== - - /** - * 构建好友通知推送 DTO(统一入口) - * - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 FRIEND_* 段 - * @param operatorUserId 操作人用户编号;同时作为帧的 senderId 用于定位接收端 friendUserId - * @param receiverUserId 推送目标用户编号 - * @param payload 好友通知 payload(继承 {@link BaseFriendNotification}) - * @return 私聊 DTO - */ - public static ImPrivateMessageDTO ofFriendNotification(Integer type, Long operatorUserId, - Long receiverUserId, BaseFriendNotification payload) { - validateNotification(type, payload, ImMessageTypeEnum.isFriendNotification(type)); - return new ImPrivateMessageDTO().setType(type) - .setSenderId(operatorUserId).setReceiverId(receiverUserId) - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now()); - } - - // ==================== 群定向私聊通知 ==================== - - // TODO DONE @AI:群申请定向通知继续走私聊通道 - /** - * 构建群通知推送 DTO(走私聊通道定向推送,不入群消息流) - *

- * 用于 GROUP_REQUEST_RECEIVED / GROUP_REQUEST_APPROVED / GROUP_REQUEST_REJECTED 段位; - * 与 {@link cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO} 走 sendGroupMessage 群广播路径不同 - * - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 GROUP_REQUEST_* 段 - * @param operatorUserId 操作人用户编号;同时作为帧的 senderId - * @param receiverUserId 推送目标用户编号 - * @param payload 群事件 payload(继承 {@link BaseGroupNotification}) - * @return 私聊 DTO - */ - public static ImPrivateMessageDTO ofGroupNotification(Integer type, Long operatorUserId, - Long receiverUserId, BaseGroupNotification payload) { - validateNotification(type, payload, ImMessageTypeEnum.isGroupRequestNotification(type)); - return new ImPrivateMessageDTO().setType(type) - .setSenderId(operatorUserId).setReceiverId(receiverUserId) - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now()); - } - - // ==================== 实时通话信令 ==================== - - /** - * 构建通话信令推送 DTO(走私聊通道仅推参与方,不入消息流) - *

- * 用于 RTC_CALL(INVITE / REJECT 等)/ RTC_PARTICIPANT_CONNECTED / RTC_PARTICIPANT_DISCONNECTED - * - * @param type 消息类型;取自 {@link ImMessageTypeEnum} 中的 RTC_* 段 - * @param senderId 发送人编号;INVITE 时为发起人,REJECT 时为拒绝者,参与者事件时为加入 / 离开者 - * @param receiverUserId 推送目标用户编号 - * @param payload 通话事件 payload(任意 RTC 通知 DTO) - * @return 私聊 DTO - */ - public static ImPrivateMessageDTO ofRtcNotification(Integer type, Long senderId, - Long receiverUserId, Object payload) { - validateNotification(type, payload, ImMessageTypeEnum.isRtcNotification(type)); - return new ImPrivateMessageDTO().setType(type) - .setSenderId(senderId).setReceiverId(receiverUserId) - .setContent(JsonUtils.toJsonString(payload)).setSendTime(LocalDateTime.now()); - } - - private static void validateNotification(Integer type, Object payload, boolean supported) { - Assert.notNull(type, "消息类型不能为空"); - Assert.notNull(payload, "消息内容不能为空"); - Assert.isTrue(supported, "消息类型不匹配 type={}", type); - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/AudioMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/AudioMessage.java deleted file mode 100644 index dd37cc0..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/AudioMessage.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 语音消息内容 - */ -@Data -public class AudioMessage { - - /** - * 语音文件 URL - */ - private String url; - /** - * 语音时长(秒) - */ - private Integer duration; - /** - * 文件大小(字节) - */ - private Long size; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/CardMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/CardMessage.java deleted file mode 100644 index 39bef39..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/CardMessage.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum; -import lombok.Data; - -/** - * 名片消息内容 - *

- * 支持两类名片,按 targetType 区分: - * 1. 用户名片(targetType = PRIVATE):targetId = 用户编号,name = 用户昵称 - * 2. 群名片(targetType = GROUP):targetId = 群编号,name = 群名,可带 memberCount - */ -@Data -public class CardMessage { - - /** - * 名片对象类型 - *

- * 枚举 {@link ImConversationTypeEnum} - */ - private Integer targetType; - /** - * 目标对象编号:PRIVATE 时 = 用户编号;GROUP 时 = 群编号 - */ - private Long targetId; - /** - * 显示名快照:PRIVATE 时 = 用户昵称;GROUP 时 = 群名 - */ - private String name; - /** - * 头像(快照) - */ - private String avatar; - /** - * 群成员数(仅 targetType = GROUP;接收端展示「N 人群聊」) - */ - private Integer memberCount; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java deleted file mode 100644 index f5c6b6c..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 表情消息内容 - *

- * 承载「贴图 / 自定义表情包」类消息;Unicode emoji(😀😂)仍走 TEXT - */ -@Data -public class FaceMessage { - - /** - * 表情图 URL - */ - private String url; - /** - * 渲染宽度(像素,可选) - *

- * 客户端渲染时按此尺寸占位,避免图片加载完成后的布局抖动;缺失时由客户端 CSS max-width 兜底 - */ - private Integer width; - /** - * 渲染高度(像素,可选) - */ - private Integer height; - /** - * 表情名(可选) - *

- * 系统表情包通常带名字(如「狗头」「捂脸」),用户私有表情包通常为空 - */ - private String name; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FileMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FileMessage.java deleted file mode 100644 index 7feb9ff..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FileMessage.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 文件消息内容 - */ -@Data -public class FileMessage { - - /** - * 文件 URL - */ - private String url; - /** - * 文件名 - */ - private String name; - /** - * 文件大小(字节) - */ - private Long size; - /** - * 文件类型(扩展名) - */ - private String type; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/ImageMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/ImageMessage.java deleted file mode 100644 index bc8e41e..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/ImageMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 图片消息内容 - */ -@Data -public class ImageMessage { - - /** - * 图片 URL - */ - private String url; - /** - * 缩略图 URL - */ - private String thumbnailUrl; - /** - * 图片宽度 - */ - private Integer width; - /** - * 图片高度 - */ - private Integer height; - /** - * 图片大小(字节) - */ - private Long size; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/LocationMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/LocationMessage.java deleted file mode 100644 index 8c36d1a..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/LocationMessage.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 位置消息内容 - */ -@Data -public class LocationMessage { - - /** - * 位置描述 - */ - private String description; - /** - * 经度 - */ - private Double longitude; - /** - * 纬度 - */ - private Double latitude; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MaterialMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MaterialMessage.java deleted file mode 100644 index 9ef4308..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MaterialMessage.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 频道素材消息 payload - *

- * 对应 {@link cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum#MATERIAL}(type=125)。 - * 客户端按本字段集渲染图文卡片; - * 富文本正文不在本 payload 中传递,点击详情时另调 /im/channel/material/get-content?id= 按需拉取。 - */ -@Data -@Accessors(chain = true) -public class MaterialMessage { - - /** - * 素材编号 - */ - private Long materialId; - /** - * 频道编号 - *

- * 冗余到 payload 内;转发到私聊 / 群聊后客户端用本字段定位频道,渲染卡片底部的频道头像 + 名称 - */ - private Long channelId; - /** - * 素材内容类型 - *

- * 枚举 {@link cn.iocoder.yudao.module.im.enums.channel.ImChannelMaterialTypeEnum} - * 客户端按本字段判定点击行为:CONTENT 走站内详情页拉富文本;LINK 跳 url - */ - private Integer type; - /** - * 标题 - */ - private String title; - /** - * 封面图 - */ - private String coverUrl; - /** - * 摘要 - */ - private String summary; - /** - * 跳转链接 - */ - private String url; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MergeMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MergeMessage.java deleted file mode 100644 index 62a051d..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/MergeMessage.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import lombok.Data; - -import java.util.List; - -/** - * 合并转发消息内容 - *

- * payload 内嵌完整快照,原消息撤回 / 删除不影响已转发的合并消息 - */ -@Data -public class MergeMessage { - - /** - * 合并标题 - */ - private String title; - /** - * 内嵌的完整消息快照 - */ - private List messages; - - /** - * 单条内嵌消息快照 - */ - @Data - public static class Item { - - /** - * 原消息编号 - */ - private Long messageId; - /** - * 发送人编号 - */ - private Long senderId; - /** - * 发送人昵称快照;接收方可能不在原会话里,无法实时查到 - */ - private String senderNickname; - /** - * 发送人头像快照 - */ - private String senderAvatar; - /** - * 消息类型 - *

- * 枚举 {@link ImMessageTypeEnum} - */ - private Integer type; - /** - * 原消息 content(JSON) - */ - private String content; - /** - * 发送时间戳(毫秒) - */ - private Long sendTime; - - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/QuoteMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/QuoteMessage.java deleted file mode 100644 index 20fa9f3..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/QuoteMessage.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 引用消息内容 - *

- * 客户端在 content.quote 里写入 messageId 表达"引用了哪条消息",服务端反查原消息后重算 QuoteMessage 覆盖客户端写入, - * 避免伪造发送人 / 类型 / 摘要 - * - * @see TextMessage 等等消息内容里 quote 字段 - */ -@Data -@Accessors(chain = true) -public class QuoteMessage { - - /** - * content JSON 里 quote 字段名 - */ - public static final String FIELD_NAME = "quote"; - - /** - * QuoteMessage 里 messageId 字段名 - */ - public static final String FIELD_MESSAGE_ID = "messageId"; - - /** - * 被引用消息编号 - */ - private Long messageId; - /** - * 被引用消息发送人编号 - *

- * 关联 AdminUserDO 的 id 字段 - */ - private Long senderId; - /** - * 被引用消息类型 - *

- * 枚举 {@link ImMessageTypeEnum} - */ - private Integer type; - /** - * 原消息完整 content(JSON);服务端复制时会 removeQuote 防嵌套 - */ - private String content; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/RecallMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/RecallMessage.java deleted file mode 100644 index 5df78f2..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/RecallMessage.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 撤回提示消息内容 - */ -@Data -@Accessors(chain = true) -public class RecallMessage { - - /** - * 被撤回的原消息编号 - */ - private Long messageId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/TextMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/TextMessage.java deleted file mode 100644 index 9d54b7d..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/TextMessage.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 文本消息内容 - */ -@Data -public class TextMessage { - - /** - * 文本内容 - */ - private String content; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/VideoMessage.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/VideoMessage.java deleted file mode 100644 index a5ba53a..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/VideoMessage.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.message; - -import lombok.Data; - -/** - * 视频消息内容 - */ -@Data -public class VideoMessage { - - /** - * 视频文件 URL - */ - private String url; - /** - * 视频封面 URL - */ - private String coverUrl; - /** - * 视频时长(秒) - */ - private Integer duration; - /** - * 视频宽度 - */ - private Integer width; - /** - * 视频高度 - */ - private Integer height; - /** - * 文件大小(字节) - */ - private Long size; - - /** - * 引用消息(可选) - */ - private QuoteMessage quote; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/BaseFriendNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/BaseFriendNotification.java deleted file mode 100644 index 4ee8f87..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/BaseFriendNotification.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 好友事件通知基类 - *

- * 所有好友事件 payload 共享: - * - operatorUserId 标识"谁触发的",用于多端同步时本端识别"是我自己触发的"还是"对方触发的" - * - friendUserId 标识"好友是谁",前端按它定位 / 更新本地 friend 缓存 - */ -@Data -public abstract class BaseFriendNotification { - - /** - * 操作人用户编号 - */ - private Long operatorUserId; - /** - * 好友用户编号 - */ - private Long friendUserId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendAddNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendAddNotification.java deleted file mode 100644 index 5892174..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendAddNotification.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 新增好友通知 - *

- * 双向建立好友关系后,推送给 A、B 双方多端;前端拉取好友信息入库 - */ -@Data -public class FriendAddNotification extends BaseFriendNotification { - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendBlockNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendBlockNotification.java deleted file mode 100644 index f8cb69e..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendBlockNotification.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 加入黑名单通知 - *

- * A 拉黑 B 后仅推 A 多端;B 端不感知(B 那边 blocked=0 不变) - */ -@Data -public class FriendBlockNotification extends BaseFriendNotification { - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendDeleteNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendDeleteNotification.java deleted file mode 100644 index 7d8ab9f..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendDeleteNotification.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 好友删除通知 - *

- * 仅推送给操作人多端做同步(对端不感知,与单边删除语义对齐);前端清除本地好友 + 按 clear 决定级联清理 - */ -@Data -public class FriendDeleteNotification extends BaseFriendNotification { - - /** - * 是否级联清理本端相关数据(当前包含私聊会话;未来可能扩展更多 clear 项) - */ - private Boolean clear; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendInfoUpdatedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendInfoUpdatedNotification.java deleted file mode 100644 index 8f81489..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendInfoUpdatedNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 好友资料变更通知(对端改了昵称 / 头像) - *

- * 由 AdminUserProfileUpdateConsumer 监听 system 模块的 AdminUserProfileUpdateMessage 后,批量推送给资料被改的人的所有好友; - * 前端 dispatcher 收到后调 loadFriendInfo 重拉资料 - *

- * 此处 friendUserId 表示「资料被更新的那个人」(即对端),与 operatorUserId 一致 - */ -@Data -public class FriendInfoUpdatedNotification extends BaseFriendNotification { - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestApprovedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestApprovedNotification.java deleted file mode 100644 index bc68f4f..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestApprovedNotification.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 好友申请被同意通知 - *

- * 推送给原申请发起方多端;前端按 requestId 把对应申请记录 handleResult 更新为「已同意」 - */ -@Data -public class FriendRequestApprovedNotification extends BaseFriendNotification { - - /** - * 已处理的申请记录编号 - */ - private Long requestId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestNotification.java deleted file mode 100644 index 924e895..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestNotification.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 收到新的好友申请通知 - *

- * 推送给申请的接收方多端;payload 已携带 fromUser 聚合字段,前端按 requestId 直接 push 进列表,无需回拉 - */ -@Data -public class FriendRequestNotification extends BaseFriendNotification { - - /** - * 申请记录编号 - */ - private Long requestId; - /** - * 申请理由 - */ - private String applyContent; - /** - * 添加来源 - */ - private Integer addSource; - - // ========== 聚合自 AdminUser,避免前端再调 system 接口 ========== - - /** - * 申请方昵称 - */ - private String fromNickname; - /** - * 申请方头像 - */ - private String fromAvatar; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestRejectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestRejectedNotification.java deleted file mode 100644 index afe0a18..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendRequestRejectedNotification.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 好友申请被拒绝通知 - *

- * 推送给原申请发起方多端;前端按 requestId 把对应申请记录 handleResult 更新为「已拒绝」 - */ -@Data -public class FriendRequestRejectedNotification extends BaseFriendNotification { - - /** - * 已处理的申请记录编号 - */ - private Long requestId; - /** - * 拒绝理由(可选) - */ - private String handleContent; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUnblockNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUnblockNotification.java deleted file mode 100644 index a57f00d..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUnblockNotification.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 移出黑名单通知 - *

- * A 把 B 移出黑名单后仅推 A 多端 - */ -@Data -public class FriendUnblockNotification extends BaseFriendNotification { - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUpdateNotification.java deleted file mode 100644 index a1a52d6..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/friend/FriendUpdateNotification.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend; - -import lombok.Data; - -/** - * 好友信息批量更新通知(备注 / 免打扰 / 联系人置顶等单边属性) - *

- * A 改了对 B 的备注 / 免打扰 / 置顶等单边属性后仅推 A 多端做同步; - * 一次 update 涉及多个字段时合并为单条通知,避免多通知顺序竞争。 - */ -@Data -public class FriendUpdateNotification extends BaseFriendNotification { - - /** - * 备注;不为空则更新(空串表示清空) - */ - private String displayName; - /** - * 免打扰;不为空则更新 - */ - private Boolean silent; - /** - * 联系人置顶;不为空则更新 - */ - private Boolean pinned; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/BaseGroupNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/BaseGroupNotification.java deleted file mode 100644 index 3e916b1..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/BaseGroupNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群事件通知基类:所有群事件 payload 共享 operatorUserId - */ -@Data -public abstract class BaseGroupNotification { - - /** - * 操作人用户编号 - */ - private Long operatorUserId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminAddNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminAddNotification.java deleted file mode 100644 index cc31ad7..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminAddNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 添加管理员事件通知(memberUserIds 为被设管理员的成员) - */ -public class GroupAdminAddNotification extends GroupMemberListNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminRemoveNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminRemoveNotification.java deleted file mode 100644 index 0f0e8d2..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupAdminRemoveNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 撤销管理员事件通知(memberUserIds 为被撤销管理员的成员) - */ -public class GroupAdminRemoveNotification extends GroupMemberListNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupBannedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupBannedNotification.java deleted file mode 100644 index bdfe9d5..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupBannedNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群封禁 / 解封通知 - */ -@Data -public class GroupBannedNotification extends BaseGroupNotification { - - /** - * 是否封禁 - */ - private Boolean banned; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCancelMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCancelMutedNotification.java deleted file mode 100644 index bddf744..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCancelMutedNotification.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 全群取消禁言通知 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class GroupCancelMutedNotification extends BaseGroupNotification { - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCreateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCreateNotification.java deleted file mode 100644 index b7e6563..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupCreateNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 群创建事件通知(memberUserIds 含创建者 + 初始邀请成员) - */ -public class GroupCreateNotification extends GroupMemberListNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupDissolveNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupDissolveNotification.java deleted file mode 100644 index bec91fa..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupDissolveNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 群解散事件通知 - */ -public class GroupDissolveNotification extends BaseGroupNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupInfoUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupInfoUpdateNotification.java deleted file mode 100644 index 70a073d..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupInfoUpdateNotification.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群信息变更事件通知(当前承载头像变更,NAME / NOTICE 走独立事件) - */ -@Data -public class GroupInfoUpdateNotification extends BaseGroupNotification { - - /** - * 旧群头像 - */ - private String oldAvatar; - /** - * 新群头像 - */ - private String newAvatar; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberCancelMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberCancelMutedNotification.java deleted file mode 100644 index 48df8fc..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberCancelMutedNotification.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 取消成员禁言通知 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class GroupMemberCancelMutedNotification extends BaseGroupNotification { - - /** - * 被取消禁言的用户编号 - */ - private Long mutedUserId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberEnterNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberEnterNotification.java deleted file mode 100644 index 32ff290..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberEnterNotification.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 自由进群事件通知 - *

- * 用户经搜索 / 二维码 / 分享链接自由进群(FREE 模式或审批通过后),全员广播; - * 进群者前端按 entrantUserId === self 自判,初次拉取 fetchGroupInfo + fetchGroupMembers;其余成员局部插入新成员 - */ -@EqualsAndHashCode(callSuper = true) -@Data -public class GroupMemberEnterNotification extends BaseGroupNotification { - - /** - * 进群者用户编号 - */ - private Long entrantUserId; - /** - * 加入来源 - */ - private Integer addSource; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberInviteNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberInviteNotification.java deleted file mode 100644 index 5877ed1..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberInviteNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 成员加入事件通知(memberUserIds 为被邀请人) - */ -public class GroupMemberInviteNotification extends GroupMemberListNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberKickNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberKickNotification.java deleted file mode 100644 index 30bbc34..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberKickNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 成员被移出事件通知(memberUserIds 为被移出成员) - */ -public class GroupMemberKickNotification extends GroupMemberListNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberListNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberListNotification.java deleted file mode 100644 index 4601858..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberListNotification.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -import java.util.List; - -/** - * 群事件成员列表通知基类 - * - * @author 芋道源码 - */ -@Data -public abstract class GroupMemberListNotification extends BaseGroupNotification { - - /** - * 受影响的成员用户编号列表 - */ - private List memberUserIds; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberMutedNotification.java deleted file mode 100644 index 557d901..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberMutedNotification.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -/** - * 成员禁言通知 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class GroupMemberMutedNotification extends BaseGroupNotification { - - /** - * 被禁言的用户编号 - */ - private Long mutedUserId; - /** - * 禁言到期时间 - */ - private LocalDateTime muteEndTime; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberNicknameUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberNicknameUpdateNotification.java deleted file mode 100644 index 0fbe63f..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberNicknameUpdateNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 成员组内昵称变更事件通知 - */ -@Data -public class GroupMemberNicknameUpdateNotification extends BaseGroupNotification { - - /** - * 群内昵称 - */ - private String displayUserName; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberQuitNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberQuitNotification.java deleted file mode 100644 index cab23a5..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberQuitNotification.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -/** - * 成员退群事件通知 - */ -public class GroupMemberQuitNotification extends BaseGroupNotification { -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberSettingUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberSettingUpdateNotification.java deleted file mode 100644 index e7eefcb..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMemberSettingUpdateNotification.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群成员个人设置变更事件通知(个人多端同步) - *

- * silent / groupRemark 字段 null 表示本次未变更,前端按非 null 局部更新 - */ -@Data -public class GroupMemberSettingUpdateNotification extends BaseGroupNotification { - - /** - * 群免打扰 - */ - private Boolean silent; - /** - * 群备注 - */ - private String groupRemark; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessagePinNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessagePinNotification.java deleted file mode 100644 index 6dd5ebc..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessagePinNotification.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 群消息置顶事件通知 - */ -@Data -public class GroupMessagePinNotification extends BaseGroupNotification { - - /** - * 被置顶的消息编号 - */ - private Long messageId; - /** - * 被置顶的消息展示数据 - */ - private PinnedMessage message; - - /** - * 被置顶的消息展示数据 - */ - @Data - public static class PinnedMessage { - - /** - * 消息编号 - */ - private Long id; - /** - * 发送人编号 - */ - private Long senderId; - /** - * 群编号 - */ - private Long groupId; - /** - * 消息类型 - */ - private Integer type; - /** - * 消息内容 - */ - private String content; - /** - * 发送时间 - */ - private LocalDateTime sendTime; - /** - * @ 目标用户编号列表 - */ - private List atUserIds; - /** - * 定向接收用户编号列表 - */ - private List receiverUserIds; - - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessageUnpinNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessageUnpinNotification.java deleted file mode 100644 index 1185b5c..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMessageUnpinNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群消息取消置顶事件通知 - */ -@Data -public class GroupMessageUnpinNotification extends BaseGroupNotification { - - /** - * 被取消置顶的消息编号 - */ - private Long messageId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMutedNotification.java deleted file mode 100644 index 2200766..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupMutedNotification.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 全群禁言通知 - */ -@Data -public class GroupMutedNotification extends BaseGroupNotification { - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNameUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNameUpdateNotification.java deleted file mode 100644 index 689ef24..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNameUpdateNotification.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群名变更事件通知 - */ -@Data -public class GroupNameUpdateNotification extends BaseGroupNotification { - - /** - * 旧群名 - */ - private String oldName; - /** - * 新群名 - */ - private String newName; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNoticeUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNoticeUpdateNotification.java deleted file mode 100644 index c2afa6c..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupNoticeUpdateNotification.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群公告变更事件通知 - */ -@Data -public class GroupNoticeUpdateNotification extends BaseGroupNotification { - - /** - * 旧群公告 - */ - private String oldNotice; - /** - * 新群公告 - */ - private String newNotice; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupOwnerTransferNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupOwnerTransferNotification.java deleted file mode 100644 index 612a764..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupOwnerTransferNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; - -/** - * 群主转让事件通知 - */ -@Data -public class GroupOwnerTransferNotification extends BaseGroupNotification { - - /** - * 新群主用户编号 - */ - private Long newOwnerUserId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestApprovedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestApprovedNotification.java deleted file mode 100644 index 7965192..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestApprovedNotification.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 入群申请被同意通知 - *

- * 走私聊通道定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除 - */ -@EqualsAndHashCode(callSuper = true) -@Data -public class GroupRequestApprovedNotification extends BaseGroupNotification { - - /** - * 已处理的申请记录编号 - */ - private Long requestId; - /** - * 群编号 - */ - private Long groupId; - /** - * 申请人 / 被邀请人用户编号 - */ - private Long userId; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java deleted file mode 100644 index a5d1f90..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 收到新的入群申请通知 - *

- * 走私聊通道定向推送给群主 + 全部管理员(多端同步);payload 已携带申请方昵称 / 头像,前端按 requestId 直接 push 进列表 - */ -@EqualsAndHashCode(callSuper = true) -@Data -public class GroupRequestReceivedNotification extends BaseGroupNotification { - - /** - * 申请记录编号 - */ - private Long requestId; - /** - * 群编号 - */ - private Long groupId; - /** - * 申请人 / 被邀请人用户编号 - */ - private Long userId; - /** - * 邀请人用户编号;NULL 表示用户主动申请 - */ - private Long inviterUserId; - /** - * 申请理由 - */ - private String applyContent; - /** - * 加入来源 - */ - private Integer addSource; - - // ========== 聚合自 AdminUser,避免前端再调 system 接口 ========== - - /** - * 申请方 / 被邀请人昵称 - */ - private String userNickname; - /** - * 申请方 / 被邀请人头像 - */ - private String userAvatar; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestRejectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestRejectedNotification.java deleted file mode 100644 index e302085..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestRejectedNotification.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.group; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 入群申请被拒绝通知 - *

- * 走私聊通道定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除 - */ -@EqualsAndHashCode(callSuper = true) -@Data -public class GroupRequestRejectedNotification extends BaseGroupNotification { - - /** - * 已处理的申请记录编号 - */ - private Long requestId; - /** - * 群编号 - */ - private Long groupId; - /** - * 申请人 / 被邀请人用户编号 - */ - private Long userId; - /** - * 拒绝理由(可选) - */ - private String handleContent; - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java deleted file mode 100644 index f0864e1..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java +++ /dev/null @@ -1,76 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc; - -import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; -import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallEndReasonEnum; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import lombok.Data; - -/** - * RTC_CALL_END 通话结束通知 - *

- * 入 im_private_message / im_group_message;接收方关闭通话窗 + 渲染聊天 tip - *

- * 文案分场景: - * 群聊:「语音通话已经结束」;发起人信息走配对的 {@link ImRtcCallStartNotification} - * 私聊:仿微信准气泡,按 endReason × selfSend 视角转换文案(HANGUP / CANCEL / REJECT / BUSY / ERROR) - *

- * 与 {@link ImRtcCallStartNotification} 两段式配对:START 在 invite 事务里 INSERT,END 在 cancel / leave 事务里 INSERT; - * 两段位于不同请求 / 事务,自增 id 保证聊天流顺序 - * - * @author 芋道源码 - */ -@Data -public class ImRtcCallEndNotification { - - /** - * 业务通话编号 - */ - private String room; - /** - * 会话类型 - */ - private Integer conversationType; - /** - * 媒体类型 - */ - private Integer mediaType; - /** - * 结束原因 - */ - private Integer endReason; - /** - * 通话时长(秒):接通过为 endTime - acceptTime;未接通为 null - */ - private Long durationSeconds; - /** - * 操作者用户编号:HANGUP / CANCEL / REJECT 是触发结束的人;HANGUP webhook 兜底为 null - *

- * 用于前端「被某某挂断」类文案;普通文案不依赖此字段 - */ - private Long operatorUserId; - /** - * 操作者昵称:前端按需展示(被某某挂断 / 头像 tip);操作者为空时随之为空 - */ - private String operatorNickname; - /** - * 操作者头像:前端按需展示;操作者为空时随之为空 - */ - private String operatorAvatar; - - public static ImRtcCallEndNotification of(ImRtcCallDO call, ImRtcCallEndReasonEnum reason, Long durationSeconds, - Long operatorId, AdminUserRespDTO operator) { - ImRtcCallEndNotification notification = new ImRtcCallEndNotification(); - notification.room = call.getRoom(); - notification.conversationType = call.getConversationType(); - notification.mediaType = call.getMediaType(); - notification.endReason = reason.getReason(); - notification.durationSeconds = durationSeconds; - notification.operatorUserId = operatorId; - if (operator != null) { - notification.operatorNickname = operator.getNickname(); - notification.operatorAvatar = operator.getAvatar(); - } - return notification; - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java deleted file mode 100644 index efa8037..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java +++ /dev/null @@ -1,165 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc; - -import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; -import cn.iocoder.yudao.module.im.enums.rtc.ImRtcParticipantStatusEnum; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import lombok.Data; - -import java.util.Collection; -import java.util.List; - -/** - * RTC_CALL 通话信令通知(通话信令统一入口) - *

- * 不入库;走 imWebSocketService 仅推参与方 - *

- * status 字段复用 {@link ImRtcParticipantStatusEnum},表达「本次信令对应的参与者状态变迁」 - * - * @author 芋道源码 - */ -@Data -public class ImRtcCallNotification { - - /** - * 信令对应的参与者状态 - * - * 取值参见 {@link ImRtcParticipantStatusEnum} - */ - private Integer status; - - /** - * 业务通话编号 - */ - private String room; - /** - * 会话类型 - */ - private Integer conversationType; - /** - * 媒体类型 - */ - private Integer mediaType; - /** - * 群编号:群通话场景必填 - */ - private Long groupId; - - // ========== INVITE 专属字段 ========== - - /** - * LiveKit Server WebSocket 地址;INVITE 专属 - */ - private String livekitUrl; - /** - * 该被叫专属的 LiveKit 接听 Token;接通后直接 connect 用;INVITE 专属 - */ - private String token; - /** - * 发起人用户编号;INVITE 专属 - */ - private Long inviterUserId; - /** - * 发起人昵称;INVITE 专属,前端来电界面展示 - */ - private String inviterNickname; - /** - * 发起人头像;INVITE 专属,前端来电界面展示 - */ - private String inviterAvatar; - /** - * 本次被邀请人列表;INVITE 专属,前端来电界面展示「邀请的其他人」 - * - * 注意:包含收件人自身,前端按需过滤 - */ - private List inviteeIds; - - // ========== REJECT 专属字段 ========== - - /** - * 操作者用户编号;REJECT 触发本次状态变迁的人 - */ - private Long operatorUserId; - /** - * 操作者昵称;前端按需展示(被某某拒接);普通文案不依赖 - */ - private String operatorNickname; - /** - * 操作者头像;前端按需展示;普通文案不依赖 - */ - private String operatorAvatar; - - /** - * 构造 INVITE 信令;推被邀请人,invitee 状态变为 INVITING - * - * @param call 通话主表 - * @param inviter 发起人;可空,缺失时 inviterNickname / inviterAvatar 留空 - * @param livekitUrl LiveKit Server WebSocket 地址 - * @param token 被叫的接听 Token;按收件人单独签发 - * @param inviteeIds 本次被邀请人列表;前端来电界面展示「邀请的其他人」用 - * @return INVITE 信令 - */ - public static ImRtcCallNotification ofInvite(ImRtcCallDO call, AdminUserRespDTO inviter, - String livekitUrl, String token, - Collection inviteeIds) { - ImRtcCallNotification notification = baseOf(call, ImRtcParticipantStatusEnum.INVITING.getStatus()); - notification.livekitUrl = livekitUrl; - notification.token = token; - notification.inviterUserId = call.getInviterUserId(); - if (inviter != null) { - notification.inviterNickname = inviter.getNickname(); - notification.inviterAvatar = inviter.getAvatar(); - } - notification.inviteeIds = inviteeIds != null ? new java.util.ArrayList<>(inviteeIds) : null; - return notification; - } - - /** - * 构造 REJECT 信令;仅群通话场景;推主叫 - * - * @param call 通话主表 - * @param operatorUserId 拒接者用户编号 - * @param operator 拒接者;可空,缺失时 operatorNickname / operatorAvatar 留空 - * @return REJECT 信令 - */ - public static ImRtcCallNotification ofReject(ImRtcCallDO call, Long operatorUserId, AdminUserRespDTO operator) { - ImRtcCallNotification notification = baseOf(call, ImRtcParticipantStatusEnum.REJECTED.getStatus()); - notification.operatorUserId = operatorUserId; - if (operator != null) { - notification.operatorNickname = operator.getNickname(); - notification.operatorAvatar = operator.getAvatar(); - } - return notification; - } - - /** - * 构造 NO_ANSWER 信令;仅群通话场景;推主叫;超时未接听语义独立于 REJECT - * - * @param call 通话主表 - * @param operatorUserId 未接听者用户编号 - * @param operator 未接听者;可空,缺失时 operatorNickname / operatorAvatar 留空 - * @return NO_ANSWER 信令 - */ - public static ImRtcCallNotification ofNoAnswer(ImRtcCallDO call, Long operatorUserId, AdminUserRespDTO operator) { - ImRtcCallNotification notification = baseOf(call, ImRtcParticipantStatusEnum.NO_ANSWER.getStatus()); - notification.operatorUserId = operatorUserId; - if (operator != null) { - notification.operatorNickname = operator.getNickname(); - notification.operatorAvatar = operator.getAvatar(); - } - return notification; - } - - /** - * 公共骨架;填充 call 上下文 + status - */ - private static ImRtcCallNotification baseOf(ImRtcCallDO call, Integer status) { - ImRtcCallNotification notification = new ImRtcCallNotification(); - notification.status = status; - notification.room = call.getRoom(); - notification.conversationType = call.getConversationType(); - notification.mediaType = call.getMediaType(); - notification.groupId = call.getGroupId(); - return notification; - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java deleted file mode 100644 index b73346b..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc; - -import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import lombok.Data; - -/** - * RTC_CALL_START 通话开始通知 - *

- * 群聊入 im_group_message 全群广播;前端渲染聊天 tip「{inviterNickname} 发起了语音通话」 - *

- * 私聊入 im_private_message 定向给被叫;前端不渲染聊天 tip,仅用于会话列表预览展示「[语音通话]」(刷新后仍可见) - *

- * 与 {@link ImRtcCallEndNotification} 两段式配对: - * START 在 invite 接口事务里 INSERT,END 在 cancel / leave 接口事务里 INSERT, - * 两段位于不同请求 / 事务,自增 id 保证聊天流顺序;后续如果合并到同一事务里 push,需要额外保证 START 先于 END - * - * @author 芋道源码 - */ -@Data -public class ImRtcCallStartNotification { - - /** - * 业务通话编号 - */ - private String room; - /** - * 会话类型:当前固定 GROUP(私聊无 START) - */ - private Integer conversationType; - /** - * 媒体类型 - */ - private Integer mediaType; - /** - * 发起人用户编号 - */ - private Long inviterUserId; - /** - * 发起人昵称:用于聊天 tip 文案,可空走前端 fallback - */ - private String inviterNickname; - /** - * 发起人头像:可空,预留给点击 tip 展示发起人卡片 - */ - private String inviterAvatar; - - public static ImRtcCallStartNotification of(ImRtcCallDO call, AdminUserRespDTO inviter) { - ImRtcCallStartNotification notification = new ImRtcCallStartNotification(); - notification.room = call.getRoom(); - notification.conversationType = call.getConversationType(); - notification.mediaType = call.getMediaType(); - notification.inviterUserId = call.getInviterUserId(); - if (inviter != null) { - notification.inviterNickname = inviter.getNickname(); - notification.inviterAvatar = inviter.getAvatar(); - } - return notification; - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java deleted file mode 100644 index 4bbfb48..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc; - -import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; -import lombok.Data; - -/** - * RTC_PARTICIPANT_CONNECTED 通话参与者加入通知 - *

- * 不入库;LiveKit webhook participant_joined 触发;私聊推 peer 多端 + inviter 多端,群聊全群广播 - *

- * 前端 callStore 把 userId 追加进 joinedUserIds;胶囊条人数 +1;群聊场景首条 1602 携带通话元信息以便 首次填充胶囊条 - * - * @author 芋道源码 - */ -@Data -public class ImRtcParticipantConnectedNotification { - - /** - * 业务通话编号 - */ - private String room; - /** - * 加入的参与者用户编号 - */ - private Long userId; - /** - * 会话类型 - */ - private Integer conversationType; - /** - * 群编号;群通话场景必填 - */ - private Long groupId; - /** - * 媒体类型;群聊场景的非邀请成员靠这个字段 首次填充胶囊条 - */ - private Integer mediaType; - /** - * 发起人用户编号;群聊场景的非邀请成员靠这个字段 首次填充胶囊条 - */ - private Long inviterUserId; - - /** - * 构造参与者加入通知;按 {@link ImRtcCallDO} 抽通话上下文,仅 userId 是变量 - * - * @param call 通话主表 - * @param userId 加入的参与者用户编号 - * @return 通知载荷 - */ - public static ImRtcParticipantConnectedNotification of(ImRtcCallDO call, Long userId) { - ImRtcParticipantConnectedNotification notification = new ImRtcParticipantConnectedNotification(); - notification.room = call.getRoom(); - notification.userId = userId; - notification.conversationType = call.getConversationType(); - notification.groupId = call.getGroupId(); - notification.mediaType = call.getMediaType(); - notification.inviterUserId = call.getInviterUserId(); - return notification; - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java deleted file mode 100644 index 94168c0..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.im.service.websocket.dto.notification.rtc; - -import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; -import lombok.Data; - -/** - * RTC_PARTICIPANT_DISCONNECTED 通话参与者离开通知 - *

- * 不入库;LiveKit webhook participant_left 触发;推送范围同 {@link ImRtcParticipantConnectedNotification} - *

- * 前端 callStore 把 userId 从 joinedUserIds 移除;胶囊条人数 -1 - * - * @author 芋道源码 - */ -@Data -public class ImRtcParticipantDisconnectedNotification { - - /** - * 业务通话编号 - */ - private String room; - /** - * 离开的参与者用户编号 - */ - private Long userId; - /** - * 会话类型 - */ - private Integer conversationType; - /** - * 群编号;群通话场景必填 - */ - private Long groupId; - - /** - * 构造参与者离开通知;按 {@link ImRtcCallDO} 抽通话上下文,仅 userId 是变量 - * - * @param call 通话主表 - * @param userId 离开的参与者用户编号 - * @return 通知载荷 - */ - public static ImRtcParticipantDisconnectedNotification of(ImRtcCallDO call, Long userId) { - ImRtcParticipantDisconnectedNotification notification = new ImRtcParticipantDisconnectedNotification(); - notification.room = call.getRoom(); - notification.userId = userId; - notification.conversationType = call.getConversationType(); - notification.groupId = call.getGroupId(); - return notification; - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/ImNotificationWebSocketDTO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/ImNotificationWebSocketDTO.java new file mode 100644 index 0000000..38a6d04 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/ImNotificationWebSocketDTO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * IM WebSocket 在线通知外壳 + *

+ * conversationType 定位会话维度;contentType 定位业务内容;payload 承载对应通知对象。 + * 会进入聊天流的私聊、群聊、频道事件走 message 子包;不进入聊天流的好友、加群申请、通话信令走 NONE 会话。 + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class ImNotificationWebSocketDTO { + + public static final String TYPE = "im-notification"; + + /** + * 会话类型,参见 ImConversationTypeEnum 枚举类 + */ + private Integer conversationType; + /** + * 内容类型,参见 ImContentTypeEnum 枚举类 + */ + private Integer contentType; + /** + * 负载数据 + */ + private Object payload; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/BaseFriendNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/BaseFriendNotification.java new file mode 100644 index 0000000..d2d3a22 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/BaseFriendNotification.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 好友事件通知基类 + *

+ * 所有好友事件 payload 共享: + * - operatorUserId 标识"谁触发的",用于多端同步时本端识别"是我自己触发的"还是"对方触发的" + * - friendUserId 标识"好友是谁",前端按它定位 / 更新本地 friend 缓存 + */ +@Data +public abstract class BaseFriendNotification { + + /** + * 操作人用户编号 + */ + private Long operatorUserId; + /** + * 好友用户编号 + */ + private Long friendUserId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendAddNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendAddNotification.java new file mode 100644 index 0000000..781c94c --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendAddNotification.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 新增好友通知 + *

+ * 双向建立好友关系后,推送给 A、B 双方多端;前端拉取好友信息入库 + */ +@Data +public class FriendAddNotification extends BaseFriendNotification { + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendBlockNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendBlockNotification.java new file mode 100644 index 0000000..abc0913 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendBlockNotification.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 加入黑名单通知 + *

+ * A 拉黑 B 后仅推 A 多端;B 端不感知(B 那边 blocked=0 不变) + */ +@Data +public class FriendBlockNotification extends BaseFriendNotification { + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendDeleteNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendDeleteNotification.java new file mode 100644 index 0000000..814c4eb --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendDeleteNotification.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 好友删除通知 + *

+ * 仅推送给操作人多端做同步(对端不感知,与单边删除语义对齐);前端清除本地好友 + 按 clear 决定级联清理 + */ +@Data +public class FriendDeleteNotification extends BaseFriendNotification { + + /** + * 是否级联清理本端相关数据(当前包含私聊会话;未来可能扩展更多 clear 项) + */ + private Boolean clear; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendInfoUpdatedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendInfoUpdatedNotification.java new file mode 100644 index 0000000..60890b0 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendInfoUpdatedNotification.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 好友资料变更通知(对端改了昵称 / 头像) + *

+ * 由 AdminUserProfileUpdateConsumer 监听 system 模块的 AdminUserProfileUpdateMessage 后,批量推送给资料被改的人的所有好友; + * 前端 dispatcher 收到后调 loadFriendInfo 重拉资料 + *

+ * 此处 friendUserId 表示「资料被更新的那个人」(即对端),与 operatorUserId 一致 + */ +@Data +public class FriendInfoUpdatedNotification extends BaseFriendNotification { + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestApprovedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestApprovedNotification.java new file mode 100644 index 0000000..5cb748c --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestApprovedNotification.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 好友申请被同意通知 + *

+ * 推送给原申请发起方多端;前端按 requestId 把对应申请记录 handleResult 更新为「已同意」 + */ +@Data +public class FriendRequestApprovedNotification extends BaseFriendNotification { + + /** + * 已处理的申请记录编号 + */ + private Long requestId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestNotification.java new file mode 100644 index 0000000..5d82e0e --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestNotification.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 收到新的好友申请通知 + *

+ * 推送给申请的接收方多端;payload 已携带 fromUser 聚合字段,前端按 requestId 直接 push 进列表,无需回拉 + */ +@Data +public class FriendRequestNotification extends BaseFriendNotification { + + /** + * 申请记录编号 + */ + private Long requestId; + /** + * 申请理由 + */ + private String applyContent; + /** + * 添加来源 + */ + private Integer addSource; + + // ========== 聚合自 AdminUser,避免前端再调 system 接口 ========== + + /** + * 申请方昵称 + */ + private String fromNickname; + /** + * 申请方头像 + */ + private String fromAvatar; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestRejectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestRejectedNotification.java new file mode 100644 index 0000000..716ba4a --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendRequestRejectedNotification.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 好友申请被拒绝通知 + *

+ * 推送给原申请发起方多端;前端按 requestId 把对应申请记录 handleResult 更新为「已拒绝」 + */ +@Data +public class FriendRequestRejectedNotification extends BaseFriendNotification { + + /** + * 已处理的申请记录编号 + */ + private Long requestId; + /** + * 拒绝理由(可选) + */ + private String handleContent; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUnblockNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUnblockNotification.java new file mode 100644 index 0000000..00c246e --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUnblockNotification.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 移出黑名单通知 + *

+ * A 把 B 移出黑名单后仅推 A 多端 + */ +@Data +public class FriendUnblockNotification extends BaseFriendNotification { + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUpdateNotification.java new file mode 100644 index 0000000..2f3df5b --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/friend/FriendUpdateNotification.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.friend; + +import lombok.Data; + +/** + * 好友信息批量更新通知(备注 / 免打扰 / 联系人置顶等单边属性) + *

+ * A 改了对 B 的备注 / 免打扰 / 置顶等单边属性后仅推 A 多端做同步; + * 一次 update 涉及多个字段时合并为单条通知,避免多通知顺序竞争。 + */ +@Data +public class FriendUpdateNotification extends BaseFriendNotification { + + /** + * 备注;不为空则更新(空串表示清空) + */ + private String displayName; + /** + * 免打扰;不为空则更新 + */ + private Boolean silent; + /** + * 联系人置顶;不为空则更新 + */ + private Boolean pinned; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/BaseGroupNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/BaseGroupNotification.java new file mode 100644 index 0000000..cd97756 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/BaseGroupNotification.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群事件通知基类:所有群事件 payload 共享 operatorUserId + */ +@Data +public abstract class BaseGroupNotification { + + /** + * 操作人用户编号 + */ + private Long operatorUserId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminAddNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminAddNotification.java new file mode 100644 index 0000000..42dfa34 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminAddNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 添加管理员事件通知(memberUserIds 为被设管理员的成员) + */ +public class GroupAdminAddNotification extends GroupMemberListNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminRemoveNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminRemoveNotification.java new file mode 100644 index 0000000..39b67dc --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupAdminRemoveNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 撤销管理员事件通知(memberUserIds 为被撤销管理员的成员) + */ +public class GroupAdminRemoveNotification extends GroupMemberListNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupBannedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupBannedNotification.java new file mode 100644 index 0000000..f72a79b --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupBannedNotification.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群封禁 / 解封通知 + */ +@Data +public class GroupBannedNotification extends BaseGroupNotification { + + /** + * 是否封禁 + */ + private Boolean banned; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCancelMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCancelMutedNotification.java new file mode 100644 index 0000000..0dbc4b6 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCancelMutedNotification.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 全群取消禁言通知 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GroupCancelMutedNotification extends BaseGroupNotification { + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCreateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCreateNotification.java new file mode 100644 index 0000000..2d10bab --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupCreateNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 群创建事件通知(memberUserIds 含创建者 + 初始邀请成员) + */ +public class GroupCreateNotification extends GroupMemberListNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupDissolveNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupDissolveNotification.java new file mode 100644 index 0000000..acff6b0 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupDissolveNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 群解散事件通知 + */ +public class GroupDissolveNotification extends BaseGroupNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupInfoUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupInfoUpdateNotification.java new file mode 100644 index 0000000..976c0b7 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupInfoUpdateNotification.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群信息变更事件通知(当前承载头像变更,NAME / NOTICE 走独立事件) + */ +@Data +public class GroupInfoUpdateNotification extends BaseGroupNotification { + + /** + * 旧群头像 + */ + private String oldAvatar; + /** + * 新群头像 + */ + private String newAvatar; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberCancelMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberCancelMutedNotification.java new file mode 100644 index 0000000..70719ef --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberCancelMutedNotification.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 取消成员禁言通知 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GroupMemberCancelMutedNotification extends BaseGroupNotification { + + /** + * 被取消禁言的用户编号 + */ + private Long mutedUserId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberEnterNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberEnterNotification.java new file mode 100644 index 0000000..337c744 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberEnterNotification.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 自由进群事件通知 + *

+ * 用户经搜索 / 二维码 / 分享链接自由进群(FREE 模式或审批通过后),全员广播; + * 进群者前端按 entrantUserId === self 自判,初次拉取 fetchGroupInfo + fetchGroupMembers;其余成员局部插入新成员 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class GroupMemberEnterNotification extends BaseGroupNotification { + + /** + * 进群者用户编号 + */ + private Long entrantUserId; + /** + * 加入来源 + */ + private Integer addSource; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberInviteNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberInviteNotification.java new file mode 100644 index 0000000..7455845 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberInviteNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 成员加入事件通知(memberUserIds 为被邀请人) + */ +public class GroupMemberInviteNotification extends GroupMemberListNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberKickNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberKickNotification.java new file mode 100644 index 0000000..24ff486 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberKickNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 成员被移出事件通知(memberUserIds 为被移出成员) + */ +public class GroupMemberKickNotification extends GroupMemberListNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberListNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberListNotification.java new file mode 100644 index 0000000..5a57254 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberListNotification.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +import java.util.List; + +/** + * 群事件成员列表通知基类 + * + * @author 芋道源码 + */ +@Data +public abstract class GroupMemberListNotification extends BaseGroupNotification { + + /** + * 受影响的成员用户编号列表 + */ + private List memberUserIds; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberMutedNotification.java new file mode 100644 index 0000000..a636249 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberMutedNotification.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 成员禁言通知 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GroupMemberMutedNotification extends BaseGroupNotification { + + /** + * 被禁言的用户编号 + */ + private Long mutedUserId; + /** + * 禁言到期时间 + */ + private LocalDateTime muteEndTime; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberNicknameUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberNicknameUpdateNotification.java new file mode 100644 index 0000000..869fc2b --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberNicknameUpdateNotification.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 成员组内昵称变更事件通知 + */ +@Data +public class GroupMemberNicknameUpdateNotification extends BaseGroupNotification { + + /** + * 群内昵称 + */ + private String displayUserName; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberQuitNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberQuitNotification.java new file mode 100644 index 0000000..663f104 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberQuitNotification.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +/** + * 成员退群事件通知 + */ +public class GroupMemberQuitNotification extends BaseGroupNotification { +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberSettingUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberSettingUpdateNotification.java new file mode 100644 index 0000000..05f0215 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMemberSettingUpdateNotification.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群成员个人设置变更事件通知(个人多端同步) + *

+ * silent / groupRemark 字段 null 表示本次未变更,前端按非 null 局部更新 + */ +@Data +public class GroupMemberSettingUpdateNotification extends BaseGroupNotification { + + /** + * 群免打扰 + */ + private Boolean silent; + /** + * 群备注 + */ + private String groupRemark; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessagePinNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessagePinNotification.java new file mode 100644 index 0000000..1717b1b --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessagePinNotification.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 群消息置顶事件通知 + */ +@Data +public class GroupMessagePinNotification extends BaseGroupNotification { + + /** + * 被置顶的消息编号 + */ + private Long messageId; + /** + * 被置顶的消息展示数据 + */ + private PinnedMessage message; + + /** + * 被置顶的消息展示数据 + */ + @Data + public static class PinnedMessage { + + /** + * 消息编号 + */ + private Long id; + /** + * 发送人编号 + */ + private Long senderId; + /** + * 群编号 + */ + private Long groupId; + /** + * 消息类型 + */ + private Integer type; + /** + * 消息内容 + */ + private String content; + /** + * 发送时间 + */ + private LocalDateTime sendTime; + /** + * @ 目标用户编号列表 + */ + private List atUserIds; + /** + * 定向接收用户编号列表 + */ + private List receiverUserIds; + + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessageUnpinNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessageUnpinNotification.java new file mode 100644 index 0000000..8051967 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMessageUnpinNotification.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群消息取消置顶事件通知 + */ +@Data +public class GroupMessageUnpinNotification extends BaseGroupNotification { + + /** + * 被取消置顶的消息编号 + */ + private Long messageId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMutedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMutedNotification.java new file mode 100644 index 0000000..dc49a29 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupMutedNotification.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 全群禁言通知 + */ +@Data +public class GroupMutedNotification extends BaseGroupNotification { + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNameUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNameUpdateNotification.java new file mode 100644 index 0000000..00fcc74 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNameUpdateNotification.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群名变更事件通知 + */ +@Data +public class GroupNameUpdateNotification extends BaseGroupNotification { + + /** + * 旧群名 + */ + private String oldName; + /** + * 新群名 + */ + private String newName; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNoticeUpdateNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNoticeUpdateNotification.java new file mode 100644 index 0000000..ecd3e34 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupNoticeUpdateNotification.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群公告变更事件通知 + */ +@Data +public class GroupNoticeUpdateNotification extends BaseGroupNotification { + + /** + * 旧群公告 + */ + private String oldNotice; + /** + * 新群公告 + */ + private String newNotice; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupOwnerTransferNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupOwnerTransferNotification.java new file mode 100644 index 0000000..b4e8564 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupOwnerTransferNotification.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; + +/** + * 群主转让事件通知 + */ +@Data +public class GroupOwnerTransferNotification extends BaseGroupNotification { + + /** + * 新群主用户编号 + */ + private Long newOwnerUserId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestApprovedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestApprovedNotification.java new file mode 100644 index 0000000..2e083f2 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestApprovedNotification.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 入群申请被同意通知 + *

+ * 定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class GroupRequestApprovedNotification extends BaseGroupNotification { + + /** + * 已处理的申请记录编号 + */ + private Long requestId; + /** + * 群编号 + */ + private Long groupId; + /** + * 申请人 / 被邀请人用户编号 + */ + private Long userId; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestReceivedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestReceivedNotification.java new file mode 100644 index 0000000..29b5aa3 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestReceivedNotification.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 收到新的入群申请通知 + *

+ * 定向推送给群主 + 全部管理员(多端同步);payload 已携带申请方昵称 / 头像,前端按 requestId 直接 push 进列表 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class GroupRequestReceivedNotification extends BaseGroupNotification { + + /** + * 申请记录编号 + */ + private Long requestId; + /** + * 群编号 + */ + private Long groupId; + /** + * 申请人 / 被邀请人用户编号 + */ + private Long userId; + /** + * 邀请人用户编号;NULL 表示用户主动申请 + */ + private Long inviterUserId; + /** + * 申请理由 + */ + private String applyContent; + /** + * 加入来源 + */ + private Integer addSource; + + // ========== 聚合自 AdminUser,避免前端再调 system 接口 ========== + + /** + * 申请方 / 被邀请人昵称 + */ + private String userNickname; + /** + * 申请方 / 被邀请人头像 + */ + private String userAvatar; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestRejectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestRejectedNotification.java new file mode 100644 index 0000000..dd6e153 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/group/GroupRequestRejectedNotification.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.group; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 入群申请被拒绝通知 + *

+ * 定向推送给申请人 + 群主 + 全部管理员;admin 侧据此把 unhandledCount 减 1 并从未处理列表移除 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class GroupRequestRejectedNotification extends BaseGroupNotification { + + /** + * 已处理的申请记录编号 + */ + private Long requestId; + /** + * 群编号 + */ + private Long groupId; + /** + * 申请人 / 被邀请人用户编号 + */ + private Long userId; + /** + * 拒绝理由(可选) + */ + private String handleContent; + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImChannelMessageNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImChannelMessageNotification.java new file mode 100644 index 0000000..af7e4c2 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImChannelMessageNotification.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.message; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImChannelMessageDO; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +/** + * IM 频道消息 WebSocket 推送通知 + *

+ * 单向:服务端运营推送 → C 端用户;C 端不能向频道发消息。 + * 字段分层:顶层是消息元数据 + 检索维度,content 是 MaterialMessage payload 的 JSON 串。 + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class ImChannelMessageNotification { + + /** + * 消息编号 + */ + private Long id; + /** + * 频道编号 + */ + private Long channelId; + /** + * 关联素材编号 + */ + private Long materialId; + /** + * 消息类型 + */ + private Integer type; + /** + * 消息内容;payload JSON 串 + */ + private String content; + /** + * 发送时间 + */ + private LocalDateTime sendTime; + + /** + * 由频道消息 DO 构建推送通知 + */ + public static ImChannelMessageNotification ofSend(ImChannelMessageDO message) { + return BeanUtils.toBean(message, ImChannelMessageNotification.class); + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImGroupMessageNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImGroupMessageNotification.java new file mode 100644 index 0000000..cbefa05 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImGroupMessageNotification.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.message; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * IM 群聊消息 WebSocket 统一推送通知 + * + * @author 芋道源码 + */ +@Data +public class ImGroupMessageNotification { + + /** + * 消息编号 + */ + private Long id; + /** + * 客户端消息编号 + */ + private String clientMessageId; + /** + * 发送人编号 + */ + private Long senderId; + /** + * 群编号 + */ + private Long groupId; + /** + * 消息类型 + */ + private Integer type; + /** + * 消息内容 + */ + private String content; + /** + * 消息状态 + */ + private Integer status; + /** + * 回执状态 + */ + private Integer receiptStatus; + /** + * 已读人数 + */ + private Integer readCount; + /** + * 发送时间 + */ + private LocalDateTime sendTime; + /** + * @ 目标用户编号列表 + */ + private List atUserIds; + /** + * 定向接收用户编号列表 + */ + private List receiverUserIds; + /** + * 构建发送消息通知 + * + * @param message 群聊消息 DO + * @return 群聊通知 + */ + public static ImGroupMessageNotification ofSend(ImGroupMessageDO message) { + return BeanUtils.toBean(message, ImGroupMessageNotification.class) + .setReadCount(message.getReadCount() != null ? message.getReadCount() : 0); + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReadNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReadNotification.java new file mode 100644 index 0000000..c066fa0 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReadNotification.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.message; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * IM 消息已读同步通知 + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class ImMessageReadNotification { + + /** + * 已读位置(最大已读消息编号) + */ + private Long id; + /** + * 发送人编号 + */ + private Long senderId; + /** + * 私聊接收人编号 + */ + private Long receiverId; + /** + * 群编号 + */ + private Long groupId; + /** + * 频道编号 + */ + private Long channelId; + /** + * 已读位置(最大已读消息编号) + */ + private Long readId; + + public static ImMessageReadNotification ofPrivate(Long senderId, Long receiverId, Long readId) { + return new ImMessageReadNotification() + .setId(readId).setReadId(readId) + .setSenderId(senderId).setReceiverId(receiverId); + } + + public static ImMessageReadNotification ofGroup(Long senderId, Long groupId, Long readId) { + return new ImMessageReadNotification() + .setId(readId).setReadId(readId) + .setSenderId(senderId).setGroupId(groupId); + } + + public static ImMessageReadNotification ofChannel(Long channelId, Long readId) { + return new ImMessageReadNotification() + .setId(readId).setReadId(readId) + .setChannelId(channelId); + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReceiptNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReceiptNotification.java new file mode 100644 index 0000000..f82df9f --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImMessageReceiptNotification.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.message; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * IM 消息回执通知 + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class ImMessageReceiptNotification { + + /** + * 消息编号 + */ + private Long id; + /** + * 已读方的用户编号 + */ + private Long senderId; + /** + * 私聊接收人编号 + */ + private Long receiverId; + /** + * 群编号 + */ + private Long groupId; + /** + * 已读人数 + */ + private Integer readCount; + /** + * 回执状态 + */ + private Integer receiptStatus; + + public static ImMessageReceiptNotification ofPrivate(Long senderId, Long receiverId, Long readId) { + return new ImMessageReceiptNotification() + .setId(readId).setSenderId(senderId).setReceiverId(receiverId); + } + + public static ImMessageReceiptNotification ofGroup(Long messageId, Long groupId, + Integer readCount, Integer receiptStatus) { + return new ImMessageReceiptNotification() + .setId(messageId).setGroupId(groupId) + .setReadCount(readCount).setReceiptStatus(receiptStatus); + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImPrivateMessageNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImPrivateMessageNotification.java new file mode 100644 index 0000000..0a88591 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/message/ImPrivateMessageNotification.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.message; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +/** + * IM 私聊消息 WebSocket 统一推送通知 + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class ImPrivateMessageNotification { + + /** + * 消息编号 + */ + private Long id; + /** + * 客户端消息编号 + */ + private String clientMessageId; + /** + * 发送人编号 + */ + private Long senderId; + /** + * 接收人编号 + */ + private Long receiverId; + /** + * 消息类型 + */ + private Integer type; + /** + * 消息内容 + */ + private String content; + /** + * 消息状态 + */ + private Integer status; + /** + * 回执状态 + */ + private Integer receiptStatus; + /** + * 发送时间 + */ + private LocalDateTime sendTime; + + // ========== 静态工厂方法 ========== + + /** + * 构建发送消息通知 + * + * @param message 私聊消息 DO + * @return 私聊通知 + */ + public static ImPrivateMessageNotification ofSend(ImPrivateMessageDO message) { + return BeanUtils.toBean(message, ImPrivateMessageNotification.class); + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/package-info.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/package-info.java new file mode 100644 index 0000000..7c2c251 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/package-info.java @@ -0,0 +1,14 @@ +/** + * IM WebSocket 在线通知对象。 + * + *

+ * 本包只放 WebSocket 外层通知对象,固定使用 im-notification 作为推送 type。 + * 具体业务 payload 放在子包中: + *

+ */ +package cn.iocoder.yudao.module.im.service.websocket.notification; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallEndNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallEndNotification.java new file mode 100644 index 0000000..8c616db --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallEndNotification.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc; + +import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; +import cn.iocoder.yudao.module.im.enums.rtc.ImRtcCallEndReasonEnum; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.Data; + +/** + * RTC_CALL_END 通话结束通知 + *

+ * 入 im_private_message / im_group_message;接收方关闭通话窗 + 渲染聊天 tip + *

+ * 文案分场景: + * 群聊:「语音通话已经结束」;发起人信息走配对的 {@link ImRtcCallStartNotification} + * 私聊:仿微信准气泡,按 endReason × selfSend 视角转换文案(HANGUP / CANCEL / REJECT / BUSY / ERROR) + *

+ * 与 {@link ImRtcCallStartNotification} 两段式配对:START 在 invite 事务里 INSERT,END 在 cancel / leave 事务里 INSERT; + * 两段位于不同请求 / 事务,自增 id 保证聊天流顺序 + * + * @author 芋道源码 + */ +@Data +public class ImRtcCallEndNotification { + + /** + * 业务通话编号 + */ + private String room; + /** + * 会话类型 + */ + private Integer conversationType; + /** + * 媒体类型 + */ + private Integer mediaType; + /** + * 结束原因 + */ + private Integer endReason; + /** + * 通话时长(秒):接通过为 endTime - acceptTime;未接通为 null + */ + private Long durationSeconds; + /** + * 操作者用户编号:HANGUP / CANCEL / REJECT 是触发结束的人;HANGUP webhook 兜底为 null + *

+ * 用于前端「被某某挂断」类文案;普通文案不依赖此字段 + */ + private Long operatorUserId; + /** + * 操作者昵称:前端按需展示(被某某挂断 / 头像 tip);操作者为空时随之为空 + */ + private String operatorNickname; + /** + * 操作者头像:前端按需展示;操作者为空时随之为空 + */ + private String operatorAvatar; + + public static ImRtcCallEndNotification of(ImRtcCallDO call, ImRtcCallEndReasonEnum reason, Long durationSeconds, + Long operatorId, AdminUserRespDTO operator) { + ImRtcCallEndNotification notification = new ImRtcCallEndNotification(); + notification.room = call.getRoom(); + notification.conversationType = call.getConversationType(); + notification.mediaType = call.getMediaType(); + notification.endReason = reason.getReason(); + notification.durationSeconds = durationSeconds; + notification.operatorUserId = operatorId; + if (operator != null) { + notification.operatorNickname = operator.getNickname(); + notification.operatorAvatar = operator.getAvatar(); + } + return notification; + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallNotification.java new file mode 100644 index 0000000..e25f389 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallNotification.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc; + +import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; +import cn.iocoder.yudao.module.im.enums.rtc.ImRtcParticipantStatusEnum; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.Data; + +import java.util.Collection; +import java.util.List; + +/** + * RTC_CALL 通话信令通知(通话信令统一入口) + *

+ * 不入库;走 imWebSocketService 仅推参与方 + *

+ * status 字段复用 {@link ImRtcParticipantStatusEnum},表达「本次信令对应的参与者状态变迁」 + * + * @author 芋道源码 + */ +@Data +public class ImRtcCallNotification { + + /** + * 信令对应的参与者状态 + * + * 取值参见 {@link ImRtcParticipantStatusEnum} + */ + private Integer status; + + /** + * 业务通话编号 + */ + private String room; + /** + * 会话类型 + */ + private Integer conversationType; + /** + * 媒体类型 + */ + private Integer mediaType; + /** + * 群编号:群通话场景必填 + */ + private Long groupId; + + // ========== INVITE 专属字段 ========== + + /** + * LiveKit Server WebSocket 地址;INVITE 专属 + */ + private String livekitUrl; + /** + * 该被叫专属的 LiveKit 接听 Token;接通后直接 connect 用;INVITE 专属 + */ + private String token; + /** + * 发起人用户编号;INVITE 专属 + */ + private Long inviterUserId; + /** + * 发起人昵称;INVITE 专属,前端来电界面展示 + */ + private String inviterNickname; + /** + * 发起人头像;INVITE 专属,前端来电界面展示 + */ + private String inviterAvatar; + /** + * 本次被邀请人列表;INVITE 专属,前端来电界面展示「邀请的其他人」 + * + * 注意:包含收件人自身,前端按需过滤 + */ + private List inviteeIds; + + // ========== REJECT 专属字段 ========== + + /** + * 操作者用户编号;REJECT 触发本次状态变迁的人 + */ + private Long operatorUserId; + /** + * 操作者昵称;前端按需展示(被某某拒接);普通文案不依赖 + */ + private String operatorNickname; + /** + * 操作者头像;前端按需展示;普通文案不依赖 + */ + private String operatorAvatar; + + /** + * 构造 INVITE 信令;推被邀请人,invitee 状态变为 INVITING + * + * @param call 通话主表 + * @param inviter 发起人;可空,缺失时 inviterNickname / inviterAvatar 留空 + * @param livekitUrl LiveKit Server WebSocket 地址 + * @param token 被叫的接听 Token;按收件人单独签发 + * @param inviteeIds 本次被邀请人列表;前端来电界面展示「邀请的其他人」用 + * @return INVITE 信令 + */ + public static ImRtcCallNotification ofInvite(ImRtcCallDO call, AdminUserRespDTO inviter, + String livekitUrl, String token, + Collection inviteeIds) { + ImRtcCallNotification notification = baseOf(call, ImRtcParticipantStatusEnum.INVITING.getStatus()); + notification.livekitUrl = livekitUrl; + notification.token = token; + notification.inviterUserId = call.getInviterUserId(); + if (inviter != null) { + notification.inviterNickname = inviter.getNickname(); + notification.inviterAvatar = inviter.getAvatar(); + } + notification.inviteeIds = inviteeIds != null ? new java.util.ArrayList<>(inviteeIds) : null; + return notification; + } + + /** + * 构造 REJECT 信令;仅群通话场景;推主叫 + * + * @param call 通话主表 + * @param operatorUserId 拒接者用户编号 + * @param operator 拒接者;可空,缺失时 operatorNickname / operatorAvatar 留空 + * @return REJECT 信令 + */ + public static ImRtcCallNotification ofReject(ImRtcCallDO call, Long operatorUserId, AdminUserRespDTO operator) { + ImRtcCallNotification notification = baseOf(call, ImRtcParticipantStatusEnum.REJECTED.getStatus()); + notification.operatorUserId = operatorUserId; + if (operator != null) { + notification.operatorNickname = operator.getNickname(); + notification.operatorAvatar = operator.getAvatar(); + } + return notification; + } + + /** + * 构造 NO_ANSWER 信令;仅群通话场景;推主叫;超时未接听语义独立于 REJECT + * + * @param call 通话主表 + * @param operatorUserId 未接听者用户编号 + * @param operator 未接听者;可空,缺失时 operatorNickname / operatorAvatar 留空 + * @return NO_ANSWER 信令 + */ + public static ImRtcCallNotification ofNoAnswer(ImRtcCallDO call, Long operatorUserId, AdminUserRespDTO operator) { + ImRtcCallNotification notification = baseOf(call, ImRtcParticipantStatusEnum.NO_ANSWER.getStatus()); + notification.operatorUserId = operatorUserId; + if (operator != null) { + notification.operatorNickname = operator.getNickname(); + notification.operatorAvatar = operator.getAvatar(); + } + return notification; + } + + /** + * 公共骨架;填充 call 上下文 + status + */ + private static ImRtcCallNotification baseOf(ImRtcCallDO call, Integer status) { + ImRtcCallNotification notification = new ImRtcCallNotification(); + notification.status = status; + notification.room = call.getRoom(); + notification.conversationType = call.getConversationType(); + notification.mediaType = call.getMediaType(); + notification.groupId = call.getGroupId(); + return notification; + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallStartNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallStartNotification.java new file mode 100644 index 0000000..a7a8596 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcCallStartNotification.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc; + +import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.Data; + +/** + * RTC_CALL_START 通话开始通知 + *

+ * 群聊入 im_group_message 全群广播;前端渲染聊天 tip「{inviterNickname} 发起了语音通话」 + *

+ * 私聊入 im_private_message 定向给被叫;前端不渲染聊天 tip,仅用于会话列表预览展示「[语音通话]」(刷新后仍可见) + *

+ * 与 {@link ImRtcCallEndNotification} 两段式配对: + * START 在 invite 接口事务里 INSERT,END 在 cancel / leave 接口事务里 INSERT, + * 两段位于不同请求 / 事务,自增 id 保证聊天流顺序;后续如果合并到同一事务里 push,需要额外保证 START 先于 END + * + * @author 芋道源码 + */ +@Data +public class ImRtcCallStartNotification { + + /** + * 业务通话编号 + */ + private String room; + /** + * 会话类型:当前固定 GROUP(私聊无 START) + */ + private Integer conversationType; + /** + * 媒体类型 + */ + private Integer mediaType; + /** + * 发起人用户编号 + */ + private Long inviterUserId; + /** + * 发起人昵称:用于聊天 tip 文案,可空走前端 fallback + */ + private String inviterNickname; + /** + * 发起人头像:可空,预留给点击 tip 展示发起人卡片 + */ + private String inviterAvatar; + + public static ImRtcCallStartNotification of(ImRtcCallDO call, AdminUserRespDTO inviter) { + ImRtcCallStartNotification notification = new ImRtcCallStartNotification(); + notification.room = call.getRoom(); + notification.conversationType = call.getConversationType(); + notification.mediaType = call.getMediaType(); + notification.inviterUserId = call.getInviterUserId(); + if (inviter != null) { + notification.inviterNickname = inviter.getNickname(); + notification.inviterAvatar = inviter.getAvatar(); + } + return notification; + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantConnectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantConnectedNotification.java new file mode 100644 index 0000000..dee51c9 --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantConnectedNotification.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc; + +import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; +import lombok.Data; + +/** + * RTC_PARTICIPANT_CONNECTED 通话参与者加入通知 + *

+ * 不入库;LiveKit webhook participant_joined 触发;私聊推 peer 多端 + inviter 多端,群聊全群广播 + *

+ * 前端 callStore 把 userId 追加进 joinedUserIds;胶囊条人数 +1;群聊场景首条 1602 携带通话元信息以便 首次填充胶囊条 + * + * @author 芋道源码 + */ +@Data +public class ImRtcParticipantConnectedNotification { + + /** + * 业务通话编号 + */ + private String room; + /** + * 加入的参与者用户编号 + */ + private Long userId; + /** + * 会话类型 + */ + private Integer conversationType; + /** + * 群编号;群通话场景必填 + */ + private Long groupId; + /** + * 媒体类型;群聊场景的非邀请成员靠这个字段 首次填充胶囊条 + */ + private Integer mediaType; + /** + * 发起人用户编号;群聊场景的非邀请成员靠这个字段 首次填充胶囊条 + */ + private Long inviterUserId; + + /** + * 构造参与者加入通知;按 {@link ImRtcCallDO} 抽通话上下文,仅 userId 是变量 + * + * @param call 通话主表 + * @param userId 加入的参与者用户编号 + * @return 通知载荷 + */ + public static ImRtcParticipantConnectedNotification of(ImRtcCallDO call, Long userId) { + ImRtcParticipantConnectedNotification notification = new ImRtcParticipantConnectedNotification(); + notification.room = call.getRoom(); + notification.userId = userId; + notification.conversationType = call.getConversationType(); + notification.groupId = call.getGroupId(); + notification.mediaType = call.getMediaType(); + notification.inviterUserId = call.getInviterUserId(); + return notification; + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantDisconnectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantDisconnectedNotification.java new file mode 100644 index 0000000..4aec61b --- /dev/null +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/notification/rtc/ImRtcParticipantDisconnectedNotification.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.im.service.websocket.notification.rtc; + +import cn.iocoder.yudao.module.im.dal.dataobject.rtc.ImRtcCallDO; +import lombok.Data; + +/** + * RTC_PARTICIPANT_DISCONNECTED 通话参与者离开通知 + *

+ * 不入库;LiveKit webhook participant_left 触发;推送范围同 {@link ImRtcParticipantConnectedNotification} + *

+ * 前端 callStore 把 userId 从 joinedUserIds 移除;胶囊条人数 -1 + * + * @author 芋道源码 + */ +@Data +public class ImRtcParticipantDisconnectedNotification { + + /** + * 业务通话编号 + */ + private String room; + /** + * 离开的参与者用户编号 + */ + private Long userId; + /** + * 会话类型 + */ + private Integer conversationType; + /** + * 群编号;群通话场景必填 + */ + private Long groupId; + + /** + * 构造参与者离开通知;按 {@link ImRtcCallDO} 抽通话上下文,仅 userId 是变量 + * + * @param call 通话主表 + * @param userId 离开的参与者用户编号 + * @return 通知载荷 + */ + public static ImRtcParticipantDisconnectedNotification of(ImRtcCallDO call, Long userId) { + ImRtcParticipantDisconnectedNotification notification = new ImRtcParticipantDisconnectedNotification(); + notification.room = call.getRoom(); + notification.userId = userId; + notification.conversationType = call.getConversationType(); + notification.groupId = call.getGroupId(); + return notification; + } + +} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/util/ImMessageUtils.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/util/ImMessageUtils.java index 1ff958a..bdfa83f 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/util/ImMessageUtils.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/util/ImMessageUtils.java @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage; import java.util.Collection; import java.util.LinkedHashMap; @@ -39,9 +39,9 @@ public class ImMessageUtils { * @param content 消息内容 */ public static void validateUserMessageContent(Integer type, String content) { - ImMessageTypeEnum messageType; + ImContentTypeEnum messageType; try { - messageType = ImMessageTypeEnum.validate(type); + messageType = ImContentTypeEnum.validate(type); } catch (IllegalArgumentException e) { throw exception(MESSAGE_CONTENT_INVALID); } @@ -52,23 +52,23 @@ public class ImMessageUtils { if (map == null) { throw exception(MESSAGE_CONTENT_INVALID); } - if (ImMessageTypeEnum.TEXT == messageType) { + if (ImContentTypeEnum.TEXT == messageType) { validateTextContent(map); - } else if (ImMessageTypeEnum.IMAGE == messageType || ImMessageTypeEnum.FACE == messageType) { + } else if (ImContentTypeEnum.IMAGE == messageType || ImContentTypeEnum.FACE == messageType) { validateUrl(getString(map, "url")); - } else if (ImMessageTypeEnum.VOICE == messageType) { + } else if (ImContentTypeEnum.VOICE == messageType) { validateUrl(getString(map, "url")); validatePositiveNumber(map.get("duration")); - } else if (ImMessageTypeEnum.VIDEO == messageType) { + } else if (ImContentTypeEnum.VIDEO == messageType) { validateUrl(getString(map, "url")); - } else if (ImMessageTypeEnum.FILE == messageType) { + } else if (ImContentTypeEnum.FILE == messageType) { validateUrl(getString(map, "url")); validateNotBlank(getString(map, "name")); - } else if (ImMessageTypeEnum.CARD == messageType) { + } else if (ImContentTypeEnum.CARD == messageType) { validateCardContent(map); - } else if (ImMessageTypeEnum.MERGE == messageType) { + } else if (ImContentTypeEnum.MERGE == messageType) { validateMergeContent(map); - } else if (ImMessageTypeEnum.MATERIAL == messageType) { + } else if (ImContentTypeEnum.MATERIAL == messageType) { validateMaterialContent(map); } } diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java index d967aed..07b1549 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java +++ b/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; import cn.iocoder.yudao.module.im.dal.mysql.message.ImGroupMessageMapper; import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import jakarta.annotation.Resource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -194,10 +194,10 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest { @Test public void testSelectMessageTypeDistribution_mergePrivateAndGroup() { // 准备:私聊 type=0 ×1,群聊 type=0 ×2、type=1 ×1 - privateMessageMapper.insert(buildPrivate(1L, 2L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.TEXT.getType())); - groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.TEXT.getType())); - groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.TEXT.getType())); - groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImMessageTypeEnum.IMAGE.getType())); + privateMessageMapper.insert(buildPrivate(1L, 2L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.TEXT.getType())); + groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.TEXT.getType())); + groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.TEXT.getType())); + groupMessageMapper.insert(buildGroupMessage(1L, 100L, WINDOW_BEGIN.plusDays(1)).setType(ImContentTypeEnum.IMAGE.getType())); // 调用 List> dist = mapper.selectMessageTypeDistribution(WINDOW_BEGIN, WINDOW_END); @@ -205,8 +205,8 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest { // 断言:type=TEXT(0) → 3;type=IMAGE(1) → 1 Map byType = dist.stream().collect(java.util.stream.Collectors.toMap( m -> ((Number) m.get("type")).intValue(), m -> ((Number) m.get("count")).longValue())); - assertEquals(3L, byType.get(ImMessageTypeEnum.TEXT.getType())); - assertEquals(1L, byType.get(ImMessageTypeEnum.IMAGE.getType())); + assertEquals(3L, byType.get(ImContentTypeEnum.TEXT.getType())); + assertEquals(1L, byType.get(ImContentTypeEnum.IMAGE.getType())); } @Test @@ -243,7 +243,7 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest { return ImPrivateMessageDO.builder() .clientMessageId("uuid-" + System.nanoTime()) .senderId(senderId).receiverId(receiverId) - .type(ImMessageTypeEnum.TEXT.getType()) + .type(ImContentTypeEnum.TEXT.getType()) .content("{}") .status(ImMessageStatusEnum.NORMAL.getStatus()) .sendTime(sendTime).build(); @@ -253,7 +253,7 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest { return new ImGroupMessageDO() .setClientMessageId("uuid-" + System.nanoTime()) .setSenderId(senderId).setGroupId(groupId) - .setType(ImMessageTypeEnum.TEXT.getType()) + .setType(ImContentTypeEnum.TEXT.getType()) .setContent("{}") .setStatus(ImMessageStatusEnum.NORMAL.getStatus()) .setSendTime(sendTime); diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImplTest.java index 0bbf441..805b63f 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.junit.jupiter.api.Test; diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java index 1d8aafc..23c4847 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService; import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -158,7 +157,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest { verify(imFriendMapper, never()).insert(any(ImFriendDO.class)); verify(imFriendMapper, never()).updateById(any(ImFriendDO.class)); verify(imFriendMapper, never()).updateReAddFields(anyLong(), anyInt(), any(LocalDateTime.class), - anyBoolean(), anyBoolean(), anyBoolean(), any(), any()); + any(LocalDateTime.class), anyBoolean(), anyBoolean(), anyBoolean(), any(), any()); } @Test @@ -173,7 +172,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest { // 断言:恢复 ENABLE,并清空 deleteTime verify(imFriendMapper).updateReAddFields(eq(10L), eq(CommonStatusEnum.ENABLE.getStatus()), - any(LocalDateTime.class), eq(false), eq(false), eq(false), isNull(), isNull()); + any(LocalDateTime.class), any(LocalDateTime.class), eq(false), eq(false), eq(false), isNull(), isNull()); verify(imFriendMapper, never()).insert(any(ImFriendDO.class)); } diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImplTest.java index 7d2dc75..92138c8 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMemberMapper; import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImplTest.java index c4f41a7..51fb765 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum; import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; import cn.iocoder.yudao.module.im.enums.group.ImGroupRequestHandleResultEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService; import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.junit.jupiter.api.Test; @@ -84,7 +83,7 @@ public class ImGroupRequestServiceImplTest extends BaseMockitoUnitTest { // 推 1510 自由进群 ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType()); } @Test @@ -207,7 +206,7 @@ public class ImGroupRequestServiceImplTest extends BaseMockitoUnitTest { eq(ImGroupAddSourceEnum.SEARCH.getSource()), isNull()); ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_MEMBER_ENTER.getType(), dtoCaptor.getValue().getType()); // 1505 推送给申请人 + owner,去重后两条 verify(websocketService, times(2)).sendPrivateMessageAsync(anyLong(), any(ImPrivateMessageDTO.class)); } diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java index 56bb61d..cf37f37 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper; import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum; import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.friend.ImFriendService; import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService; import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.junit.jupiter.api.Test; @@ -100,7 +100,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 验证:推送 GROUP_CREATE 通知(payload memberUserIds 含创建者自己) ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType()); } @Test @@ -132,7 +132,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 验证:推送 GROUP_CREATE 通知,payload memberUserIds 含全员(创建者 + 邀请) ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_CREATE.getType(), dtoCaptor.getValue().getType()); } @Test @@ -205,7 +205,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 推送 GROUP_NAME_UPDATE 通知给全员 ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_NAME_UPDATE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_NAME_UPDATE.getType(), dtoCaptor.getValue().getType()); } } @@ -234,7 +234,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 推送 GROUP_DISSOLVE 通知(send-before-remove,sendGroupMessage 内部查 active 自动覆盖全员,含群主多端同步) ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType()); } } @@ -276,7 +276,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 断言:使用管理员编号发通知并完成清理 ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(99L), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_DISSOLVE.getType(), dtoCaptor.getValue().getType()); verify(groupMemberService).removeGroupMembersByGroupId(10L); } } @@ -345,7 +345,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { verify(webSocketService, never()).sendGroupMessageAsync(anyCollection(), any(ImGroupMessageDTO.class)); ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType()); } } @@ -429,7 +429,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { eq(ImGroupAddSourceEnum.INVITE.getSource()), eq(1L)); ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType()); } } @@ -564,7 +564,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 推送 GROUP_MEMBER_QUIT 通知给全员(含 quitter,前端自判清群) ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_QUIT.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_MEMBER_QUIT.getType(), dtoCaptor.getValue().getType()); } } @@ -642,7 +642,7 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { // 推送 GROUP_MEMBER_KICK 通知给全员(含被踢者,前端自判清群) ArgumentCaptor dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); verify(groupMessageService).sendGroupMessage(eq(1L), dtoCaptor.capture()); - assertEquals(ImMessageTypeEnum.GROUP_MEMBER_KICK.getType(), dtoCaptor.getValue().getType()); + assertEquals(ImContentTypeEnum.GROUP_MEMBER_KICK.getType(), dtoCaptor.getValue().getType()); } } diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java index 2af9378..0f0e2cb 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService; import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService; @@ -22,8 +22,8 @@ import cn.iocoder.yudao.module.im.service.group.ImGroupService; import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.RecallMessage; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; @@ -70,7 +70,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { ImGroupMessageSendReqVO reqVO = new ImGroupMessageSendReqVO(); reqVO.setClientMessageId("test-uuid-group-001"); reqVO.setGroupId(10L); - reqVO.setType(ImMessageTypeEnum.TEXT.getType()); + reqVO.setType(ImContentTypeEnum.TEXT.getType()); reqVO.setContent("{\"content\":\"群聊你好\"}"); return reqVO; } @@ -85,6 +85,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { // 准备 ImGroupMessageSendReqVO reqVO = buildSendReqVO(); + reqVO.setReceipt(true); when(groupMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-group-001")) .thenReturn(null); ImGroupDO group = new ImGroupDO(); @@ -112,7 +113,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { assertEquals(1L, result.getSenderId()); assertEquals(10L, result.getGroupId()); assertEquals(ImMessageStatusEnum.NORMAL.getStatus(), result.getStatus()); - assertEquals(ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus(), result.getReceiptStatus()); + assertEquals(ImMessageReceiptStatusEnum.PENDING.getStatus(), result.getReceiptStatus()); // 验证推送给 3 个群成员(含发送者自己,用于多端同步) verify(imWebSocketService).sendGroupMessageAsync(argThat((Collection ids) -> @@ -889,7 +890,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { public void testSendGroupMessage_dto_persistsAndSerializesPojoContent() { // 准备:persistent=true 类型 + POJO content ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO() - .setGroupId(10L).setType(ImMessageTypeEnum.RECALL.getType()) + .setGroupId(10L).setType(ImContentTypeEnum.RECALL.getType()) .setContent(new RecallMessage().setMessageId(50L)); when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L)); @@ -901,7 +902,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { ImGroupMessageDO message = captor.getValue(); assertEquals(1L, message.getSenderId()); assertEquals(10L, message.getGroupId()); - assertEquals(ImMessageTypeEnum.RECALL.getType(), message.getType()); + assertEquals(ImContentTypeEnum.RECALL.getType(), message.getType()); assertEquals("{\"messageId\":50}", message.getContent()); assertEquals(ImMessageStatusEnum.NORMAL.getStatus(), message.getStatus()); assertEquals(ImMessageReceiptStatusEnum.NO_RECEIPT.getStatus(), message.getReceiptStatus()); @@ -913,7 +914,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { public void testSendGroupMessage_dto_receiptPending() { // 准备:dto.receipt=true → receiptStatus=PENDING ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO() - .setGroupId(10L).setType(ImMessageTypeEnum.RECALL.getType()) + .setGroupId(10L).setType(ImContentTypeEnum.RECALL.getType()) .setContent("{\"messageId\":50}").setReceipt(true); when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L)); @@ -928,7 +929,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { public void testSendGroupMessage_dto_nonPersistentTypeNotInserted() { // 准备:persistent=false 类型(RECEIPT 回执)→ 不入库,仅推送 ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO() - .setGroupId(10L).setType(ImMessageTypeEnum.RECEIPT.getType()); + .setGroupId(10L).setType(ImContentTypeEnum.RECEIPT.getType()); when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L, 2L)); groupMessageService.sendGroupMessage(1L, dto); @@ -942,7 +943,7 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest { // 准备:调用方传入显式 targets(解散场景成员已被批量 DISABLE,必须按移除前快照推送) Set targets = Set.of(1L, 2L, 3L); ImGroupMessageSendDTO dto = new ImGroupMessageSendDTO() - .setGroupId(10L).setType(ImMessageTypeEnum.GROUP_DISSOLVE.getType()).setContent("{}"); + .setGroupId(10L).setType(ImContentTypeEnum.GROUP_DISSOLVE.getType()).setContent("{}"); groupMessageService.sendGroupMessage(1L, targets, dto); diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java index 1d8c3b6..ca3bbe6 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper; import cn.iocoder.yudao.module.im.enums.message.ImMessageReceiptStatusEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; -import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.conversation.ImConversationReadService; import cn.iocoder.yudao.module.im.service.friend.ImFriendService; @@ -380,7 +380,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest { public void testSendPrivateMessage_dto_persistsAndSerializesPojoContent() { // 准备:persistent=true 类型 + POJO content ImPrivateMessageSendDTO dto = new ImPrivateMessageSendDTO() - .setReceiverId(2L).setType(ImMessageTypeEnum.RECALL.getType()) + .setReceiverId(2L).setType(ImContentTypeEnum.RECALL.getType()) .setContent(new RecallMessage().setMessageId(50L)); privateMessageService.sendPrivateMessage(1L, dto); @@ -391,7 +391,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest { ImPrivateMessageDO message = captor.getValue(); assertEquals(1L, message.getSenderId()); assertEquals(2L, message.getReceiverId()); - assertEquals(ImMessageTypeEnum.RECALL.getType(), message.getType()); + assertEquals(ImContentTypeEnum.RECALL.getType(), message.getType()); assertEquals("{\"messageId\":50}", message.getContent()); assertEquals(ImMessageStatusEnum.NORMAL.getStatus(), message.getStatus()); assertNotNull(message.getClientMessageId()); @@ -405,7 +405,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest { public void testSendPrivateMessage_dto_nonPersistentTypeNotInserted() { // 准备:persistent=false 类型(FRIEND_DELETE 通知)→ 不入库;仅推 sender 多端,receiver 不感知 ImPrivateMessageSendDTO dto = new ImPrivateMessageSendDTO() - .setReceiverId(2L).setType(ImMessageTypeEnum.FRIEND_DELETE.getType()); + .setReceiverId(2L).setType(ImContentTypeEnum.FRIEND_DELETE.getType()); privateMessageService.sendPrivateMessage(1L, dto); diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImplTest.java index 9173b87..52b644f 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImplTest.java +++ b/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; import cn.iocoder.yudao.module.im.framework.config.ImProperties; import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.junit.jupiter.api.Test; diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImplTest.java index df2125a..a76da8a 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/websocket/ImWebSocketServiceImplTest.java +++ b/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; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; -import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; +import cn.iocoder.yudao.module.im.enums.ImContentTypeEnum; +import cn.iocoder.yudao.module.im.enums.ImConversationTypeEnum; +import cn.iocoder.yudao.module.im.service.websocket.notification.ImNotificationWebSocketDTO; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImGroupMessageNotification; +import cn.iocoder.yudao.module.im.service.websocket.notification.message.ImPrivateMessageNotification; import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -21,6 +24,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.*; /** @@ -44,10 +48,10 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest { } } - // ========== sendPrivateMessageAsync ========== + // ========== sendNotificationAsync ========== @Test - public void testSendPrivateMessageAsync_noTransactionSendsImmediately() { + public void testSendNotificationAsync_private_noTransactionSendsImmediately() { try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class))) .thenReturn(imWebSocketService); @@ -60,12 +64,14 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest { // 断言 verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImPrivateMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.PRIVATE, + ImContentTypeEnum.TEXT, dto))); } } @Test - public void testSendPrivateMessageAsync_inTransactionDeferredUntilCommit() { + public void testSendNotificationAsync_private_inTransactionDeferredUntilCommit() { try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class))) .thenReturn(imWebSocketService); @@ -89,43 +95,51 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest { // 断言:提交后推送 verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImPrivateMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.PRIVATE, + ImContentTypeEnum.TEXT, dto))); } finally { TransactionSynchronizationManager.clear(); } } } - // ========== sendGroupMessageAsync ========== + // ========== sendNotificationAsync ========== @Test - public void testSendGroupMessageAsync_fanOutToAllUsers() { + public void testSendNotificationAsync_group_fanOutToAllUsers() { try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class))) .thenReturn(imWebSocketService); - ImGroupMessageDTO dto = new ImGroupMessageDTO(); + ImGroupMessageNotification dto = new ImGroupMessageNotification(); dto.setGroupId(10L); dto.setSenderId(1L); imWebSocketService.sendGroupMessageAsync(ListUtil.of(1L, 2L, 3L), dto); verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImGroupMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP, + ImContentTypeEnum.TEXT, dto))); verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImGroupMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP, + ImContentTypeEnum.TEXT, dto))); verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(3L), eq(ImGroupMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(3L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP, + ImContentTypeEnum.TEXT, dto))); } } @Test - public void testSendGroupMessageAsync_senderExceptionDoesNotBreakOthers() { + public void testSendNotificationAsync_group_senderExceptionDoesNotBreakOthers() { try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class))) .thenReturn(imWebSocketService); - ImGroupMessageDTO dto = new ImGroupMessageDTO(); + ImGroupMessageNotification dto = new ImGroupMessageNotification(); dto.setGroupId(10L); // 给 1 号用户推送时抛异常,不能影响 2/3 号 doThrow(new RuntimeException("user offline")) @@ -143,8 +157,8 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest { public void testDoSendGroupMessage_emptyUserIds_noSend() { ImGroupMessageDTO dto = new ImGroupMessageDTO().setGroupId(10L); - imWebSocketService.doSendGroupMessage(Collections.emptyList(), dto); - imWebSocketService.doSendGroupMessage(null, dto); + imWebSocketService.doSendNotification(Collections.emptyList(), notification); + imWebSocketService.doSendNotification(null, notification); verifyNoInteractions(webSocketSenderApi); } @@ -153,17 +167,21 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest { public void testDoSendGroupMessage_distinctUserIds() { ImGroupMessageDTO dto = new ImGroupMessageDTO().setGroupId(10L); - imWebSocketService.doSendGroupMessage(Arrays.asList(1L, 2L, 1L, null), dto); + imWebSocketService.doSendNotification(Arrays.asList(1L, 2L, 1L, null), notification); verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImGroupMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(1L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP, + ImContentTypeEnum.TEXT, dto))); verify(webSocketSenderApi).sendObject( - eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImGroupMessageDTO.TYPE), eq(dto)); + eq(UserTypeEnum.ADMIN.getValue()), eq(2L), eq(ImNotificationWebSocketDTO.TYPE), + argThat(actual -> isNotification(actual, ImConversationTypeEnum.GROUP, + ImContentTypeEnum.TEXT, dto))); verifyNoMoreInteractions(webSocketSenderApi); } @Test - public void testSendPrivateMessageAsync_exceptionSwallowed() { + public void testSendNotificationAsync_private_exceptionSwallowed() { try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class))) .thenReturn(imWebSocketService); @@ -181,12 +199,12 @@ public class ImWebSocketServiceImplTest extends BaseMockitoUnitTest { } @Test - public void testSendGroupMessageAsync_singleUserDefaultOverload() { + public void testSendNotificationAsync_group_singleUserDefaultOverload() { try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImWebSocketServiceImpl.class))) .thenReturn(imWebSocketService); - ImGroupMessageDTO dto = new ImGroupMessageDTO(); + ImGroupMessageNotification dto = new ImGroupMessageNotification(); dto.setGroupId(10L); imWebSocketService.sendGroupMessageAsync(42L, dto); diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/util/ImMessageUtilsTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/util/ImMessageUtilsTest.java index 03f6a14..f7d859e 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/util/ImMessageUtilsTest.java +++ b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/util/ImMessageUtilsTest.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.im.util; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.module.im.service.websocket.dto.message.QuoteMessage; +import cn.iocoder.yudao.module.im.dal.dataobject.message.content.QuoteMessage; import org.junit.jupiter.api.Test; import java.util.Map; -- libgit2 0.21.4