Commit 0e79d8ec53ae4f234adc1ebe28ac5f86c52abb54

Authored by YunaiV
1 parent 9c1764e3

im:code review 消息发送的逻辑

Showing 21 changed files with 74 additions and 35 deletions
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ImConversationTypeEnum.java
... ... @@ -12,6 +12,7 @@ import lombok.Getter;
12 12 @AllArgsConstructor
13 13 public enum ImConversationTypeEnum {
14 14  
  15 + // TODO @hao:单聊,我们使用 SINGLE,主要 private 这个单词在 java 里太特殊了;
15 16 PRIVATE(1, "单聊"),
16 17 GROUP(2, "群聊"),
17 18 NOTICE(4, "通知会话");
... ...
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java
... ... @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
6 6  
7 7 import java.util.Arrays;
8 8  
  9 +// TODO @hao:注释哈;
9 10 @RequiredArgsConstructor
10 11 @Getter
11 12 public enum ImMessageStatusEnum implements IntArrayValuable {
... ... @@ -16,7 +17,9 @@ public enum ImMessageStatusEnum implements IntArrayValuable {
16 17 DELETED(4, "已删除"),
17 18 RECALL(5, "已撤回");
18 19  
  20 + // TODO @hao:静态变量,和普通变量,最好空一行;
19 21 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageStatusEnum::getStatus).toArray();
  22 + // TODO @hao:注释哈;
20 23 private final Integer status;
21 24 private final String name;
22 25  
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/ImInboxPageReqVO.java
... ... @@ -11,6 +11,7 @@ import java.time.LocalDateTime;
11 11  
12 12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
13 13  
  14 +// TODO @hao:这个是不是删除掉,应该不会有这个 VO 哈
14 15 @Schema(description = "管理后台 - 收件箱分页 Request VO")
15 16 @Data
16 17 @EqualsAndHashCode(callSuper = true)
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/ImInboxRespVO.java
... ... @@ -7,6 +7,7 @@ import lombok.Data;
7 7  
8 8 import java.time.LocalDateTime;
9 9  
  10 +// TODO @hao:这个是不是删除掉,应该不会有这个 VO 哈;应该给前端的,是要屏蔽掉这个表,最终返回的都是 Message 哈;说白了,这个 inbox 是后端的内部实现
10 11 @Schema(description = "管理后台 - 收件箱 Response VO")
11 12 @Data
12 13 @ExcelIgnoreUnannotated
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/ImInboxSaveReqVO.java
... ... @@ -6,6 +6,7 @@ import lombok.AllArgsConstructor;
6 6 import lombok.Data;
7 7 import lombok.NoArgsConstructor;
8 8  
  9 +// TODO @hao:这个是不是删除掉,应该不会有这个 VO 哈
9 10 @Schema(description = "管理后台 - 收件箱新增/修改 Request VO")
10 11 @Data
11 12 @AllArgsConstructor
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImMessageController.java
... ... @@ -24,7 +24,7 @@ import java.util.List;
24 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 25 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
26 26  
27   -@Tag(name = "管理后台 - 消息")
  27 +@Tag(name = "管理后台 - IM 消息")
28 28 @RestController
29 29 @RequestMapping("/im/message")
30 30 @Validated
... ... @@ -33,19 +33,20 @@ public class ImMessageController {
33 33 @Resource
34 34 private ImMessageService imMessageService;
35 35  
36   - @GetMapping("/get-message-by-sequence")
37   - @Operation(summary = "拉取消息-增量拉取大于 seq 的消息")
  36 + @GetMapping("/get-message-by-sequence") // TODO @hao:list-by-sequence
  37 + @Operation(summary = "拉取消息-增量拉取大于 seq 的消息") // TODO @hao:可以改成 拉取大于 sequence 的消息列表
38 38 @Parameter(name = "sequence", description = "序号", required = true, example = "1")
39 39 @Parameter(name = "size", description = "条数", required = true, example = "10")
40   - @PreAuthorize("@ss.hasPermission('im:message:query')")
41   - public CommonResult<List<ImMessageRespVO>> loadMessage(
42   - @RequestParam("sequence") Long sequence,
43   - @RequestParam("size") Integer size) {
  40 + @PreAuthorize("@ss.hasPermission('im:message:query')") // TODO @hao:权限可以删除哈;
  41 + public CommonResult<List<ImMessageRespVO>> loadMessage(@RequestParam("sequence") Long sequence,
  42 + @RequestParam("size") Integer size) {
  43 + // TODO @hao:方法名,可以改成 getMessageListBySequence
  44 + // TODO @hao:如果是返回列表,变量要用 messages, 或者 messageList,体现出是复数
44 45 List<ImMessageDO> message = imMessageService.loadMessage(getLoginUserId(), sequence, size);
45 46 return success(BeanUtils.toBean(message, ImMessageRespVO.class));
46 47 }
47 48  
48   -
  49 + // TODO @hao:这个接口的使用场景是哪个哈?
49 50 @GetMapping("/get-all-message")
50 51 @Operation(summary = "拉取全部消息")
51 52 @Parameter(name = "size", description = "条数", required = true, example = "10")
... ... @@ -55,14 +56,13 @@ public class ImMessageController {
55 56 return success(BeanUtils.toBean(message, ImMessageRespVO.class));
56 57 }
57 58  
58   -
  59 + // TODO @hao:是不是分页参数不太对哈?应该只有 conversationNo,sendTime 字段;然后,做链式分页的查询,不太适合传统的 pageSize + number 查询;
59 60 @GetMapping("/page")
60 61 @Operation(summary = "查询聊天记录-分页")
61   - @PreAuthorize("@ss.hasPermission('im:message:query')")
  62 + @PreAuthorize("@ss.hasPermission('im:message:query')") // TODO @hao:权限可以删除哈;
62 63 public CommonResult<PageResult<ImMessageRespVO>> getMessagePage(@Valid ImMessagePageReqVO pageReqVO) {
63 64 PageResult<ImMessageDO> messagePage = imMessageService.getMessagePage(pageReqVO);
64 65 return success(BeanUtils.toBean(messagePage, ImMessageRespVO.class));
65 66 }
66 67  
67   -
68 68 }
69 69 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationMapper.java
... ... @@ -10,7 +10,7 @@ import org.apache.ibatis.annotations.Mapper;
10 10 import java.util.Optional;
11 11  
12 12 /**
13   - * 会话 Mapper
  13 + * IM 会话 Mapper
14 14 *
15 15 * @author 芋道源码
16 16 */
... ... @@ -29,6 +29,7 @@ public interface ImConversationMapper extends BaseMapperX&lt;ImConversationDO&gt; {
29 29 .orderByDesc(ImConversationDO::getId));
30 30 }
31 31  
  32 + // TODO @hao:1)no) {,要有空格哈;2)可以直接 selectOne(ImConversationDO::getNo, no) 父类做了封装
32 33 default ImConversationDO selectByNo(String no){
33 34 return selectOne(new LambdaQueryWrapperX<ImConversationDO>().eq(ImConversationDO::getNo, no));
34 35 }
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java
... ... @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
10 10 /**
11   - * 收件箱 Mapper
  11 + * IM 收件箱 Mapper
12 12 *
13 13 * @author 芋道源码
14 14 */
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImMessageMapper.java
... ... @@ -36,6 +36,7 @@ public interface ImMessageMapper extends BaseMapperX&lt;ImMessageDO&gt; {
36 36 .orderByDesc(ImMessageDO::getId));
37 37 }
38 38  
  39 + // TODO @hao:不链表哈;先从 ImInboxDO 查询出 messageId,然后再到 ImMessageDO 里 IN
39 40 default List<ImMessageDO> getGreaterThanSequenceMessage(Long userId, Long sequence, Integer size) {
40 41 //查询 inbox 表中,大于 sequence 的消息,关联 message 表,按照 inbox 表 sequence 升序
41 42 return selectJoinList(ImMessageDO.class, new MPJLambdaWrapper<ImMessageDO>()
... ... @@ -47,6 +48,7 @@ public interface ImMessageMapper extends BaseMapperX&lt;ImMessageDO&gt; {
47 48 .last("limit 0," + size));
48 49 }
49 50  
  51 + // TODO @hao:在 dao 里,使用 selectListByUserId,查询用 select,条件用 by,这个算是 spring data 的 method dsl
50 52 default List<ImMessageDO> getAllMessage(Long userId, Integer size) {
51 53 //查询 inbox 表中,100条消息,关联 message 表,按照 inbox 表 sequence 降序
52 54 return selectJoinList(ImMessageDO.class, new MPJLambdaWrapper<ImMessageDO>()
... ... @@ -56,4 +58,5 @@ public interface ImMessageMapper extends BaseMapperX&lt;ImMessageDO&gt; {
56 58 .orderByDesc(ImInboxDO::getSequence)
57 59 .last("limit 0," + size));
58 60 }
  61 +
59 62 }
60 63 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceGeneratorRedisDao.java
... ... @@ -6,6 +6,7 @@ import org.springframework.stereotype.Repository;
6 6  
7 7 import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.INBOX_SEQUENCE;
8 8  
  9 +// TODO @芋艿:这个名字,需要在考虑下;
9 10 /**
10 11 * 序号生成器 Redis DAO
11 12 *
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationService.java
... ... @@ -9,7 +9,7 @@ import jakarta.validation.Valid;
9 9 import java.util.List;
10 10  
11 11 /**
12   - * 会话 Service 接口
  12 + * IM 会话 Service 接口
13 13 *
14 14 * @author 芋道源码
15 15 */
... ... @@ -74,4 +74,5 @@ public interface ImConversationService {
74 74 * @param updateReqVO 更新信息
75 75 */
76 76 void updateLastReadTime(ImConversationSaveReqVO updateReqVO);
  77 +
77 78 }
78 79 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java
... ... @@ -18,7 +18,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
18 18 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_NOT_EXISTS;
19 19  
20 20 /**
21   - * 会话 Service 实现类
  21 + * IM 会话 Service 实现类
22 22 *
23 23 * @author 芋道源码
24 24 */
... ... @@ -26,18 +26,19 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_N
26 26 @Validated
27 27 public class ImConversationServiceImpl implements ImConversationService {
28 28  
  29 + // TODO @hao: 自己模块的注入,不用带 im 前缀哈;
29 30 @Resource
30 31 private ImConversationMapper imConversationMapper;
31 32  
  33 + // TODO @hao: 这个方法,是不是不需要哈
32 34 @Override
33 35 public Long createConversation(ImConversationSaveReqVO createReqVO) {
34   - // 插入
35 36 ImConversationDO conversation = BeanUtils.toBean(createReqVO, ImConversationDO.class);
36 37 imConversationMapper.insert(conversation);
37   - // 返回
38 38 return conversation.getId();
39 39 }
40 40  
  41 + // TODO @hao: 这个方法,是不是不需要哈
41 42 @Override
42 43 public void updateConversation(ImConversationSaveReqVO updateReqVO) {
43 44 // 校验存在
... ... @@ -47,6 +48,7 @@ public class ImConversationServiceImpl implements ImConversationService {
47 48 imConversationMapper.updateById(updateObj);
48 49 }
49 50  
  51 + // TODO @hao: 考虑到可能和端上不同步,可以不校验是不是存储。另外,不基于 id 删除。要基于 no + userId 删除哈。说白了,对端上要屏蔽 id 字段
50 52 @Override
51 53 public void deleteConversation(Long id) {
52 54 // 校验存在
... ... @@ -86,6 +88,11 @@ public class ImConversationServiceImpl implements ImConversationService {
86 88 createOrUpdateConversation(updateReqVO);
87 89 }
88 90  
  91 + // TODO @hao:updateTop 和 updateLastReadTime 使用独立的逻辑实现,不使用统一的 ImConversationSaveReqVO;
  92 + // TODO 大体步骤建议:
  93 + // 1. 先 getOrderCreateConversation,查询会话,不存在则插入;
  94 + // 2. 更新对应的字段
  95 + // 3. 做对应更新的 notify 推送
89 96 private void createOrUpdateConversation(ImConversationSaveReqVO updateReqVO) {
90 97 // 操作会话(已读、置顶)时,才会延迟创建,要先判断是否存在,根据 no 查询是否存在,不存在则新增
91 98 ImConversationDO conversation = imConversationMapper.selectByNo(updateReqVO.getNo());
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxService.java
... ... @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
7 7 import jakarta.validation.Valid;
8 8  
  9 +// TODO @hao:不用的方法,删除下哈;
9 10 /**
10   - * 收件箱 Service 接口
  11 + * IM 收件箱 Service 接口
11 12 *
12 13 * @author 芋道源码
13 14 */
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java
... ... @@ -27,10 +27,8 @@ public class ImInboxServiceImpl implements ImInboxService {
27 27  
28 28 @Override
29 29 public Long createInbox(ImInboxSaveReqVO createReqVO) {
30   - // 插入
31 30 ImInboxDO inbox = BeanUtils.toBean(createReqVO, ImInboxDO.class);
32 31 imInboxMapper.insert(inbox);
33   - // 返回
34 32 return inbox.getId();
35 33 }
36 34  
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java
... ... @@ -91,6 +91,7 @@ public interface ImMessageService {
91 91 */
92 92 List<ImMessageDO> loadMessage(Long userId, Long sequence, Integer size);
93 93  
  94 + // TODO @hao;这种接口,项目里叫 getMessageListByUserId,尽量保持 getList 获取列表哈;
94 95 /**
95 96 * 拉取全部消息
96 97 *
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java
... ... @@ -84,26 +84,31 @@ public class ImMessageServiceImpl implements ImMessageService {
84 84 }
85 85  
86 86 private ImMessageDO saveImMessageDO(ImSendMessage message, Long fromUserId) {
  87 + // TODO @hao:可以搞成 messageDO
  88 + // TODO @hao:链式调用
87 89 ImMessageDO imMessageDO = new ImMessageDO();
88 90 imMessageDO.setClientMessageId(message.getClientMessageId());
89 91 imMessageDO.setSenderId(fromUserId);
90 92 imMessageDO.setReceiverId(message.getReceiverId());
91   - //查询发送人昵称和发送人头像
  93 + // 查询发送人昵称和发送人头像
92 94 AdminUserRespDTO user = adminUserApi.getUser(fromUserId);
93 95 imMessageDO.setSenderNickname(user.getNickname());
94 96 imMessageDO.setSenderAvatar(user.getAvatar());
95 97 imMessageDO.setConversationType(message.getConversationType());
96 98 imMessageDO.setContentType(message.getContentType());
97   - //单聊:s_{userId}_{targetId} 群聊:群聊:g_{groupId}
  99 + // 单聊:s_{userId}_{targetId} 群聊:群聊:g_{groupId}
  100 + // TODO @hao:这里的 conversationNo 的生成,可以写到工具类里,或者干脆放到 ImConversationTypeEnum 里;
98 101 if (message.getConversationType().equals(ImConversationTypeEnum.PRIVATE.getType())) {
99 102 imMessageDO.setConversationNo("s_" + fromUserId + "_" + message.getReceiverId());
100 103 } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
101 104 imMessageDO.setConversationNo("g_" + message.getReceiverId());
102 105 }
103 106 imMessageDO.setContent(message.getContent());
104   - //消息来源 100-用户发送;200-系统发送(一般是通知);不能为空
  107 + // TODO @hao:枚举哈;
  108 + // 消息来源 100-用户发送;200-系统发送(一般是通知);不能为空
105 109 imMessageDO.setSendFrom(100);
106 110 imMessageDO.setSendTime(TimeUtil.now());
  111 + // TODO @hao:服务端的消息,就是默认生成哈;
107 112 imMessageDO.setMessageStatus(ImMessageStatusEnum.SENDING.getStatus());
108 113 imMessageMapper.insert(imMessageDO);
109 114 return imMessageDO;
... ... @@ -111,7 +116,7 @@ public class ImMessageServiceImpl implements ImMessageService {
111 116  
112 117 @Override
113 118 public void updateMessageStatus(Long messageId, Integer messageStatus) {
114   - //校验 id 是否存在
  119 + // 校验 id 是否存在
115 120 validateMessageExists(messageId);
116 121 //更新消息状态
117 122 ImMessageDO imMessageDO = new ImMessageDO();
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
... ... @@ -23,6 +23,7 @@ import org.springframework.web.socket.WebSocketSession;
23 23  
24 24 import java.util.List;
25 25  
  26 +// TODO @hao:消息发送,使用 http 上行。因为在 cloud 框架下,我们比较难去 Listener。因为 im-server 不会自己启动 websocket 路径
26 27 /**
27 28 * WebSocket im
28 29 *
... ... @@ -60,9 +61,10 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
60 61 if (message.getConversationType().equals(ImConversationTypeEnum.PRIVATE.getType())) {
61 62 handlePrivateMessage(fromUserId, message);
62 63 } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
63   - //处理群聊消息
  64 + // 处理群聊消息
64 65 handleGroupMessage(fromUserId, message);
65 66 } else {
  67 + // TODO @hao:是不是应该会话类型哈?然后打印这种错误日志,最好把 message 整个打进去,这样更好定位完整的消息;
66 68 log.error("[onMessage][消息类型({}) 未支持]", message.getConversationType());
67 69 }
68 70 }
... ... @@ -74,13 +76,17 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
74 76 * @param message 发送的IM消息
75 77 */
76 78 private void handleGroupMessage(Long fromUserId, ImSendMessage message) {
  79 + // TODO @hao:群存在;
  80 + // TODO @hao:发送人在群里;
77 81 ImMessageDO imMessageDO = imMessageService.saveGroupMessage(message, fromUserId); // 保存群聊消息
78 82 Long groupId = message.getReceiverId();
79 83  
80 84 // 发送消息给群聊成员
  85 + // TODO @hao:变量名可以叫 groupMembers;一般不用 DO 后缀,除非为了区分;
81 86 List<GroupMemberDO> groupMemberDOList = imGroupMemberService.selectByGroupId(groupId);
82 87 groupMemberDOList.forEach(groupMemberDO -> {
83   - //过滤掉自己
  88 + // 过滤掉自己
  89 + // TODO @hao:98 到 99 的代码,是不是可以融合到这里来;
84 90 if (groupMemberDO.getUserId().equals(fromUserId)) {
85 91 return;
86 92 }
... ... @@ -106,11 +112,14 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
106 112 * @param message 发送的IM消息
107 113 */
108 114 private void handlePrivateMessage(Long fromUserId, ImSendMessage message) {
  115 + // TODO @hao:需要校验 receiverId 存在;
109 116 ImMessageDO imMessageDO = imMessageService.savePrivateMessage(message, fromUserId); // 保存私人消息
110 117 Long receiverId = message.getReceiverId();
111 118  
  119 + // TODO @hao:sequenceGeneratorRedisDao.generateSequence 和 createAndSaveInbox 步骤,要加锁;不然会有并发问题;如果有疑问,可以微信招我沟通哈;另外,创建 seq、保存收件箱、发送,可以统一封装到 imInboxService 里哈;这样,后续要发某个消息,就是丢个 message 对象进去;
112 120 Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列
113 121 Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱
  122 +
114 123 Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(message.getReceiverId()); // 生成接收者序列
115 124 Long receiverInboxId = createAndSaveInbox(message.getReceiverId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱
116 125  
... ... @@ -119,6 +128,7 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
119 128 sendMessage(receiverId, receiverInboxId, imMessageDO, message, receiverSequence);
120 129  
121 130 // 更新消息状态为成功
  131 + // TODO @hao:后端消息的发送,默认就是 success 哈,不要区分 status;status 更多是前端使用的;
122 132 imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus());
123 133 // 保存私人会话,只有在 client 操作会话(已读、置顶)时,才会延迟创建
124 134 //imConversationService.savePrivateConversation(fromUserId, receiverId);
... ... @@ -137,6 +147,7 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
137 147 return imInboxService.createInbox(inboxSaveReqVO); // 创建收件箱
138 148 }
139 149  
  150 + // TODO @hao:这个使用 WebSocketSenderApi 发送哈;
140 151 /**
141 152 * 发送消息
142 153 *
... ... @@ -147,6 +158,7 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
147 158 * @param sequence 序列
148 159 */
149 160 private void sendMessage(Long fromUserId, Long inboxId, ImMessageDO imMessageDO, ImSendMessage message, Long sequence) {
  161 + // TODO @hao:不要每个字段 set 占一行;想同类型的字段用一行,然后链式 set,会更简洁干净。
150 162 ImReceiveMessage receiveMessage = new ImReceiveMessage(); // 创建接收消息
151 163 receiveMessage.setFromId(fromUserId); // 设置发送者ID
152 164 receiveMessage.setConversationType(message.getConversationType()); // 设置会话类型
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
1 1 package cn.iocoder.yudao.module.im.websocket.message;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.body.ImMessageBody;
4 3 import io.swagger.v3.oas.annotations.media.Schema;
5   -import jakarta.validation.constraints.NotNull;
6 4 import lombok.Data;
7 5  
8 6 import java.time.LocalDateTime;
... ... @@ -17,22 +15,25 @@ public class ImReceiveMessage {
17 15 @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
18 16 private Long fromId; // 根据 conversationType 区分
19 17  
  18 + // TODO @hao:昵称和头像,也直接发给接收人好了;
  19 +
  20 + @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
  21 + private Long messageId;
  22 +
20 23 @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
21 24 private Integer contentType; // 参见 ImMessageTypeEnum 枚举
22 25  
23 26 @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
24 27 private String content;
25 28  
26   - @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
27   - private Long messageId;
28   -
29 29 @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
30 30 private LocalDateTime sendTime;
31 31  
  32 + // TODO @hao:inboxId 不需要哈;
32 33 @Schema(description = "收件箱编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18389")
33 34 private Long inboxId;
34 35  
35   - @Schema(description = "序号,按照 user 递增", requiredMode = Schema.RequiredMode.REQUIRED)
  36 + @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
36 37 private Long sequence;
37 38  
38 39 }
39 40 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java
1 1 package cn.iocoder.yudao.module.im.websocket.message;
2 2  
3   -import cn.iocoder.yudao.module.im.dal.dataobject.message.body.ImMessageBody;
4 3 import io.swagger.v3.oas.annotations.media.Schema;
5   -import jakarta.validation.constraints.NotEmpty;
6 4 import lombok.Data;
7 5  
8   -@Schema(description = "管理后台 - 消息发送 send")
  6 +@Schema(description = "管理后台 - IM 消息发送 send")
9 7 @Data
10 8 public class ImSendMessage {
11 9  
... ... @@ -13,6 +11,7 @@ public class ImSendMessage {
13 11 private String clientMessageId;
14 12  
15 13 @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  14 + // TODO @hao:用下 InEnum 校验。这样可以少写 15 的注释哈;类似 contentType 也是;
16 15 private Integer conversationType; // 对应 ImConversationTypeEnum 枚举
17 16  
18 17 @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
... ...
yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ImConversationMapper.xml
... ... @@ -2,6 +2,7 @@
2 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3 3 <mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper">
4 4  
  5 + <!-- TODO @hao:xml 如果用不到,可以先删除哈 -->
5 6 <!--
6 7 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
7 8 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java
... ... @@ -41,6 +41,7 @@ public class AdminUserRespDTO {
41 41 */
42 42 private String mobile;
43 43  
  44 + // TODO @hao:这种字段的添加,最好和 do 保持一致的顺序哈;
44 45 /**
45 46 * 用户头像
46 47 */
... ...