Commit ba5b7dbd0aeb4db8ddf6b6d4d64cbd2844fb0a0f

Authored by YunaiV
1 parent f6a29e53

📝 refactor(messages): 重构消息类,简化字段命名和结构,增强可读性

Showing 14 changed files with 295 additions and 143 deletions
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4   -import lombok.AllArgsConstructor;
5 3 import lombok.Data;
6   -import lombok.NoArgsConstructor;
7 4  
8   -// TODO @anhaohao:要有 IM;
9   -// TODO @芋艿:后续要挪到 api 包下,主要是给外部接口使用
10 5 /**
11   - * 语音消息的 {@link ImMessageDO 字段 content} 的内容
12   - *
13   - * @author 芋道源码
  6 + * 语音消息内容
14 7 */
15 8 @Data
16   -@AllArgsConstructor
17   -@NoArgsConstructor
18 9 public class AudioMessage {
19 10  
20 11 /**
21   - * 语音文件唯一 ID
  12 + * 语音文件 URL
22 13 */
23   - private String uuid;
24   -
25   - /**
26   - * 语音文件的本地路径
27   - */
28   - private String soundPath;
29   -
  14 + private String url;
30 15 /**
31   - * 语音文件下载地址
  16 + * 语音时长(秒)
32 17 */
33   - private String sourceUrl;
34   -
35   - /**
36   - * 语音文件大小
37   - */
38   - private int dataSize;
39   -
40   - /**
41   - * 语音时长
42   - */
43   - private int duration;
44   -
  18 + private Integer duration;
45 19 /**
46   - * 语音文件类型
  20 + * 文件大小(字节)
47 21 */
48   - private String soundType;
  22 + private Long size;
49 23  
50   -}
51 24 \ No newline at end of file
  25 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4   -import lombok.AllArgsConstructor;
5 3 import lombok.Data;
6   -import lombok.NoArgsConstructor;
7 4  
8 5 /**
9   - * 名片消息的 {@link ImMessageDO 字段 content} 的内容
10   - *
11   - * @author anhaohao
12   - * @since 2024/3/23 下午5:53
  6 + * 名片消息内容
13 7 */
14 8 @Data
15   -@AllArgsConstructor
16   -@NoArgsConstructor
17 9 public class CardMessage {
18 10  
19 11 /**
20   - * 用户 ID
  12 + * 用户编号
21 13 */
22   - private String userID;
23   -
  14 + private Long userId;
24 15 /**
25   - * 用户名
  16 + * 用户昵称
26 17 */
27 18 private String nickname;
28   -
29 19 /**
30 20 * 用户头像
31 21 */
32   - private int faceURL;
  22 + private String avatar;
33 23  
34   - /**
35   - * 扩展字段
36   - */
37   - private String ex;
38 24 }
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4   -import lombok.AllArgsConstructor;
5 3 import lombok.Data;
6   -import lombok.NoArgsConstructor;
7 4  
8 5 /**
9   - * 文件消息的 {@link ImMessageDO 字段 content} 的内容
10   - *
11   - * @author 芋道源码
  6 + * 文件消息内容
12 7 */
13 8 @Data
14   -@AllArgsConstructor
15   -@NoArgsConstructor
16 9 public class FileMessage {
17 10  
18 11 /**
  12 + * 文件 URL
  13 + */
  14 + private String url;
  15 + /**
19 16 * 文件名
20 17 */
21 18 private String name;
22 19 /**
23   - * 文件 URL
  20 + * 文件大小(字节)
24 21 */
25   - private String url;
  22 + private Long size;
  23 + /**
  24 + * 文件类型(扩展名)
  25 + */
  26 + private String type;
26 27  
27   -}
28 28 \ No newline at end of file
  29 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4   -import lombok.AllArgsConstructor;
5 3 import lombok.Data;
6   -import lombok.NoArgsConstructor;
7 4  
8 5 /**
9   - * 图片消息的 {@link ImMessageDO 字段 content} 的内容
10   - *
11   - * @author 芋道源码
  6 + * 图片消息内容
12 7 */
13 8 @Data
14   -@AllArgsConstructor
15   -@NoArgsConstructor
16 9 public class ImageMessage {
17 10  
18 11 /**
19   - * 图片地址
  12 + * 图片 URL
20 13 */
21 14 private String url;
  15 + /**
  16 + * 缩略图 URL
  17 + */
  18 + private String thumbnailUrl;
  19 + /**
  20 + * 图片宽度
  21 + */
  22 + private Integer width;
  23 + /**
  24 + * 图片高度
  25 + */
  26 + private Integer height;
  27 + /**
  28 + * 图片大小(字节)
  29 + */
  30 + private Long size;
22 31  
23 32 }
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4   -import lombok.AllArgsConstructor;
5 3 import lombok.Data;
6   -import lombok.NoArgsConstructor;
7 4  
8 5 /**
9   - * 地址位置消息的 {@link ImMessageDO 字段 content} 的内容
10   - *
11   - * @author 芋道源码
  6 + * 位置消息内容
12 7 */
13 8 @Data
14   -@AllArgsConstructor
15   -@NoArgsConstructor
16 9 public class LocationMessage {
17 10  
18 11 /**
19   - * 地理位置
20   - * <p>
21   - * 例如说:中国 浙江省 杭州市 网商路 599号
  12 + * 位置描述
22 13 */
23   - private String address;
  14 + private String description;
24 15 /**
25 16 * 经度
26 17 */
... ... @@ -30,4 +21,4 @@ public class LocationMessage {
30 21 */
31 22 private Double latitude;
32 23  
33   -}
34 24 \ No newline at end of file
  25 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4   -import lombok.AllArgsConstructor;
5 3 import lombok.Data;
6   -import lombok.NoArgsConstructor;
7 4  
8 5 /**
9   - * 文本消息的 {@link ImMessageDO 字段 content} 的内容
10   - *
11   - * @author 芋道源码
  6 + * 文本消息内容
12 7 */
13 8 @Data
14   -@AllArgsConstructor
15   -@NoArgsConstructor
16 9 public class TextMessage {
17 10  
18 11 /**
19   - * 文本消息的具体内容
  12 + * 文本内容
20 13 */
21 14 private String content;
22 15  
23   -}
24 16 \ No newline at end of file
  17 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
1 1 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
4 3 import lombok.Data;
5 4  
6 5 /**
7   - * 视频消息的 {@link ImMessageDO 字段 content} 的内容
8   - *
9   - * @author 芋道源码
  6 + * 视频消息内容
10 7 */
11 8 @Data
12 9 public class VideoMessage {
13 10  
14 11 /**
15   - * 视频地址
  12 + * 视频文件 URL
16 13 */
17 14 private String url;
  15 + /**
  16 + * 视频封面 URL
  17 + */
  18 + private String coverUrl;
  19 + /**
  20 + * 视频时长(秒)
  21 + */
  22 + private Integer duration;
  23 + /**
  24 + * 视频宽度
  25 + */
  26 + private Integer width;
  27 + /**
  28 + * 视频高度
  29 + */
  30 + private Integer height;
  31 + /**
  32 + * 文件大小(字节)
  33 + */
  34 + private Long size;
18 35  
19   -}
20 36 \ No newline at end of file
  37 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.group;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
  5 +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO;
  6 +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * 群成员 Service 接口
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public interface ImGroupMemberService {
  17 +
  18 + /**
  19 + * 创建群成员
  20 + *
  21 + * @param createReqVO 创建信息
  22 + * @return 编号
  23 + */
  24 + Long createGroupMember(@Valid ImGroupMemberSaveReqVO createReqVO);
  25 +
  26 + /**
  27 + * 更新群成员
  28 + *
  29 + * @param updateReqVO 更新信息
  30 + */
  31 + void updateGroupMember(@Valid ImGroupMemberSaveReqVO updateReqVO);
  32 +
  33 + /**
  34 + * 删除群成员
  35 + *
  36 + * @param id 编号
  37 + */
  38 + void deleteGroupMember(Long id);
  39 +
  40 + /**
  41 + * 获得群成员
  42 + *
  43 + * @param id 编号
  44 + * @return 群成员
  45 + */
  46 + ImGroupMemberDO getGroupMember(Long id);
  47 +
  48 + /**
  49 + * 获得群成员分页
  50 + *
  51 + * @param pageReqVO 分页查询
  52 + * @return 群成员分页
  53 + */
  54 + PageResult<ImGroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO);
  55 +
  56 + /**
  57 + * 根据群组id查询群成员
  58 + *
  59 + * @param groupId 群组id
  60 + * @return 群成员列表
  61 + */
  62 + List<ImGroupMemberDO> selectByGroupId(Long groupId);
  63 +
  64 + /**
  65 + * 根据群编号和用户编号查询群成员
  66 + *
  67 + * @param groupId 群编号
  68 + * @param userId 用户编号
  69 + * @return 群成员
  70 + */
  71 + ImGroupMemberDO getGroupMember(Long groupId, Long userId);
  72 +
  73 + /**
  74 + * 查询用户所在的所有群的成员记录
  75 + *
  76 + * @param userId 用户编号
  77 + * @return 群成员记录列表
  78 + */
  79 + List<ImGroupMemberDO> getGroupMembersByUserId(Long userId);
  80 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.service.group;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +import jakarta.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +
  7 +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*;
  8 +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  11 +
  12 +import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper;
  13 +
  14 +import java.util.List;
  15 +
  16 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  17 +import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
  18 +
  19 +/**
  20 + * 群成员 Service 实现类
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@Service
  25 +@Validated
  26 +public class ImGroupMemberServiceImpl implements ImGroupMemberService {
  27 +
  28 + @Resource
  29 + private ImGroupMemberMapper imGroupMemberMapper;
  30 +
  31 + @Override
  32 + public Long createGroupMember(ImGroupMemberSaveReqVO createReqVO) {
  33 + // 插入
  34 + ImGroupMemberDO groupMember = BeanUtils.toBean(createReqVO, ImGroupMemberDO.class);
  35 + imGroupMemberMapper.insert(groupMember);
  36 + // 返回
  37 + return groupMember.getId();
  38 + }
  39 +
  40 + @Override
  41 + public void updateGroupMember(ImGroupMemberSaveReqVO updateReqVO) {
  42 + // 校验存在
  43 + validateGroupMemberExists(updateReqVO.getId());
  44 + // 更新
  45 + ImGroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupMemberDO.class);
  46 + imGroupMemberMapper.updateById(updateObj);
  47 + }
  48 +
  49 + @Override
  50 + public void deleteGroupMember(Long id) {
  51 + // 校验存在
  52 + validateGroupMemberExists(id);
  53 + // 删除
  54 + imGroupMemberMapper.deleteById(id);
  55 + }
  56 +
  57 + private void validateGroupMemberExists(Long id) {
  58 + if (imGroupMemberMapper.selectById(id) == null) {
  59 + throw exception(GROUP_MEMBER_NOT_EXISTS);
  60 + }
  61 + }
  62 +
  63 + @Override
  64 + public ImGroupMemberDO getGroupMember(Long id) {
  65 + return imGroupMemberMapper.selectById(id);
  66 + }
  67 +
  68 + @Override
  69 + public PageResult<ImGroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO) {
  70 + return imGroupMemberMapper.selectPage(pageReqVO);
  71 + }
  72 +
  73 + @Override
  74 + public List<ImGroupMemberDO> selectByGroupId(Long groupId) {
  75 + return imGroupMemberMapper.selectListByGroupId(groupId);
  76 + }
  77 +
  78 + @Override
  79 + public ImGroupMemberDO getGroupMember(Long groupId, Long userId) {
  80 + return imGroupMemberMapper.selectByGroupIdAndUserId(groupId, userId);
  81 + }
  82 +
  83 + @Override
  84 + public List<ImGroupMemberDO> getGroupMembersByUserId(Long userId) {
  85 + return imGroupMemberMapper.selectListByUserId(userId);
  86 + }
  87 +
  88 +}
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
... ... @@ -15,9 +15,9 @@ import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
15 15 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
16 16 import cn.iocoder.yudao.module.im.enums.message.ImWebSocketTypeConstants;
17 17 import cn.iocoder.yudao.module.im.service.group.ImGroupService;
18   -import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
  18 +import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
19 19 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
20   -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
  20 +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
21 21 import jakarta.annotation.Resource;
22 22 import lombok.extern.slf4j.Slf4j;
23 23 import org.springframework.stereotype.Service;
... ... @@ -54,7 +54,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
54 54 @Resource
55 55 private GroupReadPositionRedisDAO groupReadPositionRedisDAO;
56 56 @Resource
57   - private WebSocketSenderApi webSocketSenderApi;
  57 + private WebSocketMessageSender webSocketMessageSender;
58 58  
59 59 @Override
60 60 public ImGroupMessageDO sendMessage(Long senderId, ImGroupMessageSendReqVO reqVO) {
... ... @@ -170,7 +170,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
170 170 Map<String, Object> readEvent = new HashMap<>();
171 171 readEvent.put("groupId", groupId.toString());
172 172 readEvent.put("messageScene", "group");
173   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
  173 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
174 174 ImWebSocketTypeConstants.READ, readEvent);
175 175  
176 176 // 5. 刷新群回执
... ... @@ -209,7 +209,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
209 209 if (ImGroupMemberStatusEnum.QUIT.getStatus().equals(m.getStatus())) {
210 210 continue;
211 211 }
212   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
  212 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
213 213 ImWebSocketTypeConstants.RECALL, recallEvent);
214 214 }
215 215 }
... ... @@ -302,7 +302,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
302 302 if (ImGroupMemberStatusEnum.QUIT.getStatus().equals(m.getStatus())) {
303 303 continue;
304 304 }
305   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
  305 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
306 306 ImWebSocketTypeConstants.RECEIPT, receiptEvent);
307 307 }
308 308 }
... ... @@ -382,7 +382,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
382 382 && !member.getUserId().equals(message.getSenderId())) {
383 383 continue;
384 384 }
385   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), member.getUserId(),
  385 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), member.getUserId(),
386 386 ImWebSocketTypeConstants.GROUP_MESSAGE, event);
387 387 }
388 388 }
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
... ... @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
9 9 import cn.iocoder.yudao.module.im.enums.message.ImWebSocketTypeConstants;
10 10 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
11 11 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
12   -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
  12 +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
13 13 import jakarta.annotation.Resource;
14 14 import lombok.extern.slf4j.Slf4j;
15 15 import org.springframework.stereotype.Service;
... ... @@ -48,7 +48,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
48 48  
49 49 // TODO @AI:这个类貌似路径不对?!
50 50 @Resource
51   - private WebSocketSenderApi webSocketSenderApi;
  51 + private WebSocketMessageSender webSocketMessageSender;
52 52  
53 53 @Override
54 54 public ImPrivateMessageDO sendMessage(Long senderId, ImPrivateMessageSendReqVO reqVO) {
... ... @@ -107,7 +107,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
107 107 // TODO @AI:需要整理下,相关的 websocket DTO;可维护性变强!
108 108 readEvent.put("friendId", friendId.toString());
109 109 readEvent.put("messageScene", "private");
110   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
  110 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
111 111 ImWebSocketTypeConstants.READ, readEvent);
112 112  
113 113 // 3. 发送 RECEIPT 事件给对方(已读回执)
... ... @@ -115,7 +115,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
115 115 // TODO @AI:需要整理下,相关的 websocket DTO;可维护性变强!
116 116 receiptEvent.put("userId", userId.toString());
117 117 receiptEvent.put("messageScene", "private");
118   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), friendId,
  118 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), friendId,
119 119 ImWebSocketTypeConstants.RECEIPT, receiptEvent);
120 120 }
121 121  
... ... @@ -147,11 +147,11 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
147 147 recallEvent.put("messageId", messageId.toString());
148 148 recallEvent.put("messageScene", "private");
149 149 recallEvent.put("senderId", userId.toString());
150   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
  150 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
151 151 ImWebSocketTypeConstants.RECALL, recallEvent);
152 152 // 3.2 也通知发送方自己的其他终端
153 153 // TODO @AI:需要整理下,相关的 websocket DTO;可维护性变强!
154   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
  154 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
155 155 ImWebSocketTypeConstants.RECALL, recallEvent);
156 156 }
157 157  
... ... @@ -171,10 +171,10 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
171 171 event.put("sendTime", message.getSendTime().toString());
172 172 event.put("messageScene", "private");
173 173 // 推送给接收方
174   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
  174 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
175 175 ImWebSocketTypeConstants.PRIVATE_MESSAGE, event);
176 176 // 推送给发送方自己的其他终端(多端同步)
177   - webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), message.getSenderId(),
  177 + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getSenderId(),
178 178 ImWebSocketTypeConstants.PRIVATE_MESSAGE, event);
179 179 }
180 180  
... ...
yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java
1 1 package cn.iocoder.yudao.module.im.service.message;
2 2  
3 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
4   -import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImGroupMessageSendReqVO;
  4 +import cn.iocoder.yudao.module.im.controller.admin.message.vo.group.ImGroupMessageSendReqVO;
5 5 import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
... ... @@ -11,9 +11,9 @@ import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberStatusEnum;
11 11 import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum;
12 12 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
13 13 import cn.iocoder.yudao.module.im.service.group.ImGroupService;
14   -import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
  14 +import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
15 15 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
16   -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
  16 +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
17 17 import org.junit.jupiter.api.Test;
18 18 import org.junit.jupiter.api.extension.ExtendWith;
19 19 import org.mockito.InjectMocks;
... ... @@ -51,7 +51,7 @@ public class ImGroupMessageServiceImplTest {
51 51 @Mock
52 52 private GroupReadPositionRedisDAO groupReadPositionRedisDAO;
53 53 @Mock
54   - private WebSocketSenderApi webSocketSenderApi;
  54 + private WebSocketMessageSender webSocketMessageSender;
55 55  
56 56 private ImGroupMessageSendReqVO buildSendReqVO() {
57 57 ImGroupMessageSendReqVO reqVO = new ImGroupMessageSendReqVO();
... ... @@ -89,7 +89,11 @@ public class ImGroupMessageServiceImplTest {
89 89 .status(ImGroupMemberStatusEnum.NORMAL.getStatus()).build()
90 90 );
91 91 when(imGroupMemberService.selectByGroupId(10L)).thenReturn(allMembers);
92   - when(imGroupMessageMapper.insert(any())).thenReturn(1);
  92 + when(imGroupMessageMapper.insert(any(ImGroupMessageDO.class))).thenAnswer(invocation -> {
  93 + ImGroupMessageDO msg = invocation.getArgument(0);
  94 + msg.setId(99L);
  95 + return 1;
  96 + });
93 97  
94 98 // 调用
95 99 ImGroupMessageDO result = groupMessageService.sendMessage(1L, reqVO);
... ... @@ -102,7 +106,7 @@ public class ImGroupMessageServiceImplTest {
102 106 assertEquals(ImGroupMessageReceiptStatusEnum.NO_RECEIPT.getStatus(), result.getReceiptStatus());
103 107  
104 108 // 验证推送给 3 个群成员
105   - verify(webSocketSenderApi, times(3)).sendObject(anyInt(), anyLong(), anyString(), any());
  109 + verify(webSocketMessageSender, times(3)).sendObject(anyInt(), anyLong(), anyString(), any());
106 110 }
107 111  
108 112 @Test
... ... @@ -121,7 +125,7 @@ public class ImGroupMessageServiceImplTest {
121 125  
122 126 // 断言
123 127 assertEquals(100L, result.getId());
124   - verify(imGroupMessageMapper, never()).insert(any());
  128 + verify(imGroupMessageMapper, never()).insert(any(ImGroupMessageDO.class));
125 129 }
126 130  
127 131 @Test
... ... @@ -262,7 +266,7 @@ public class ImGroupMessageServiceImplTest {
262 266 .id(50L).senderId(1L).groupId(10L)
263 267 .status(ImMessageStatusEnum.NORMAL).build();
264 268 when(imGroupMessageMapper.selectById(50L)).thenReturn(message);
265   - when(imGroupMessageMapper.updateById(any())).thenReturn(1);
  269 + when(imGroupMessageMapper.updateById(any(ImGroupMessageDO.class))).thenReturn(1);
266 270  
267 271 List<ImGroupMemberDO> members = List.of(
268 272 ImGroupMemberDO.builder().groupId(10L).userId(1L)
... ... @@ -278,7 +282,7 @@ public class ImGroupMessageServiceImplTest {
278 282 groupMessageService.recallMessage(1L, 50L);
279 283  
280 284 // 断言:只给 2 个活跃成员发送 RECALL 事件(userId=3 已退群)
281   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
  285 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
282 286 }
283 287  
284 288 // ========== 群已读测试 ==========
... ...
yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java
... ... @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
7 7 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
8 8 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
9 9 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
10   -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
  10 +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
11 11 import org.junit.jupiter.api.Test;
12 12 import org.junit.jupiter.api.extension.ExtendWith;
13 13 import org.mockito.InjectMocks;
... ... @@ -40,7 +40,7 @@ public class ImPrivateMessageServiceImplTest {
40 40 @Mock
41 41 private ImSensitiveWordService imSensitiveWordService;
42 42 @Mock
43   - private WebSocketSenderApi webSocketSenderApi;
  43 + private WebSocketMessageSender webSocketMessageSender;
44 44  
45 45 private ImPrivateMessageSendReqVO buildSendReqVO() {
46 46 ImPrivateMessageSendReqVO reqVO = new ImPrivateMessageSendReqVO();
... ... @@ -59,7 +59,11 @@ public class ImPrivateMessageServiceImplTest {
59 59 ImPrivateMessageSendReqVO reqVO = buildSendReqVO();
60 60 when(imPrivateMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-001"))
61 61 .thenReturn(null);
62   - when(imPrivateMessageMapper.insert(any())).thenReturn(1);
  62 + when(imPrivateMessageMapper.insert(any(ImPrivateMessageDO.class))).thenAnswer(invocation -> {
  63 + ImPrivateMessageDO msg = invocation.getArgument(0);
  64 + msg.setId(99L);
  65 + return 1;
  66 + });
63 67  
64 68 // 调用
65 69 ImPrivateMessageDO result = privateMessageService.sendMessage(1L, reqVO);
... ... @@ -75,8 +79,8 @@ public class ImPrivateMessageServiceImplTest {
75 79 // 验证调用
76 80 verify(imFriendService).validateIsFriend(1L, 2L);
77 81 verify(imSensitiveWordService).validateText(reqVO.getContent());
78   - verify(imPrivateMessageMapper).insert(any());
79   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
  82 + verify(imPrivateMessageMapper).insert(any(ImPrivateMessageDO.class));
  83 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
80 84 }
81 85  
82 86 @Test
... ... @@ -96,7 +100,7 @@ public class ImPrivateMessageServiceImplTest {
96 100 // 断言:返回已存在的消息
97 101 assertEquals(100L, result.getId());
98 102 // 验证不会重复插入
99   - verify(imPrivateMessageMapper, never()).insert(any());
  103 + verify(imPrivateMessageMapper, never()).insert(any(ImPrivateMessageDO.class));
100 104 }
101 105  
102 106 @Test
... ... @@ -151,7 +155,7 @@ public class ImPrivateMessageServiceImplTest {
151 155 privateMessageService.readMessages(1L, 2L);
152 156  
153 157 // 断言:发送了 READ 和 RECEIPT 事件
154   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
  158 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
155 159 }
156 160  
157 161 // ========== 撤回测试 ==========
... ... @@ -163,15 +167,15 @@ public class ImPrivateMessageServiceImplTest {
163 167 .id(10L).senderId(1L).receiverId(2L)
164 168 .status(ImMessageStatusEnum.UNREAD.getStatus()).build();
165 169 when(imPrivateMessageMapper.selectById(10L)).thenReturn(message);
166   - when(imPrivateMessageMapper.updateById(any())).thenReturn(1);
  170 + when(imPrivateMessageMapper.updateById(any(ImPrivateMessageDO.class))).thenReturn(1);
167 171  
168 172 // 调用
169 173 privateMessageService.recallMessage(1L, 10L);
170 174  
171 175 // 断言
172   - verify(imPrivateMessageMapper).updateById(any());
  176 + verify(imPrivateMessageMapper).updateById(any(ImPrivateMessageDO.class));
173 177 // 验证推送了 RECALL 事件(给接收方和发送方)
174   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
  178 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
175 179 }
176 180  
177 181 @Test
... ...
yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImWebSocketEventTest.java
... ... @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
6 6 import cn.iocoder.yudao.module.im.enums.message.ImWebSocketTypeConstants;
7 7 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
8 8 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
9   -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
  9 +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
10 10 import org.junit.jupiter.api.Test;
11 11 import org.junit.jupiter.api.extension.ExtendWith;
12 12 import org.mockito.ArgumentCaptor;
... ... @@ -40,7 +40,7 @@ public class ImWebSocketEventTest {
40 40 @Mock
41 41 private ImSensitiveWordService imSensitiveWordService;
42 42 @Mock
43   - private WebSocketSenderApi webSocketSenderApi;
  43 + private WebSocketMessageSender webSocketMessageSender;
44 44  
45 45 @Test
46 46 public void testSendMessage_websocketEvent() {
... ... @@ -52,7 +52,12 @@ public class ImWebSocketEventTest {
52 52 reqVO.setContent("{\"content\":\"事件测试\"}");
53 53  
54 54 when(imPrivateMessageMapper.selectBySenderIdAndClientMessageId(1L, "evt-uuid")).thenReturn(null);
55   - when(imPrivateMessageMapper.insert(any())).thenReturn(1);
  55 + // mock insert:通过 doAnswer 模拟 MyBatis-Plus 设置 ID
  56 + when(imPrivateMessageMapper.insert(any(ImPrivateMessageDO.class))).thenAnswer(invocation -> {
  57 + ImPrivateMessageDO msg = invocation.getArgument(0);
  58 + msg.setId(99L);
  59 + return 1;
  60 + });
56 61  
57 62 // 调用
58 63 privateMessageService.sendMessage(1L, reqVO);
... ... @@ -60,7 +65,7 @@ public class ImWebSocketEventTest {
60 65 // 捕获 WebSocket 调用
61 66 ArgumentCaptor<String> typeCaptor = ArgumentCaptor.forClass(String.class);
62 67 ArgumentCaptor<Object> contentCaptor = ArgumentCaptor.forClass(Object.class);
63   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(),
  68 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(),
64 69 typeCaptor.capture(), contentCaptor.capture());
65 70  
66 71 // 验证消息事件类型
... ... @@ -87,7 +92,7 @@ public class ImWebSocketEventTest {
87 92 // 捕获
88 93 ArgumentCaptor<String> typeCaptor = ArgumentCaptor.forClass(String.class);
89 94 ArgumentCaptor<Long> userCaptor = ArgumentCaptor.forClass(Long.class);
90   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), userCaptor.capture(),
  95 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), userCaptor.capture(),
91 96 typeCaptor.capture(), any());
92 97  
93 98 // 第一次:发给自己的 READ 事件
... ... @@ -104,7 +109,7 @@ public class ImWebSocketEventTest {
104 109 ImPrivateMessageDO message = ImPrivateMessageDO.builder()
105 110 .id(10L).senderId(1L).receiverId(2L).status(0).build();
106 111 when(imPrivateMessageMapper.selectById(10L)).thenReturn(message);
107   - when(imPrivateMessageMapper.updateById(any())).thenReturn(1);
  112 + when(imPrivateMessageMapper.updateById(any(ImPrivateMessageDO.class))).thenReturn(1);
108 113  
109 114 // 调用
110 115 privateMessageService.recallMessage(1L, 10L);
... ... @@ -112,7 +117,7 @@ public class ImWebSocketEventTest {
112 117 // 捕获
113 118 ArgumentCaptor<String> typeCaptor = ArgumentCaptor.forClass(String.class);
114 119 ArgumentCaptor<Object> contentCaptor = ArgumentCaptor.forClass(Object.class);
115   - verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(),
  120 + verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(),
116 121 typeCaptor.capture(), contentCaptor.capture());
117 122  
118 123 // 验证 RECALL 事件类型
... ...