فهرست منبع

IM:code review 消息发送的实现

YunaiV 1 سال پیش
والد
کامیت
2b891cb432
32فایلهای تغییر یافته به همراه99 افزوده شده و 90 حذف شده
  1. 2 1
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java
  2. 4 4
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageContentTypeEnum.java
  3. 3 2
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageSourceEnum.java
  4. 9 0
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageStatusEnum.java
  5. 1 1
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ConversationController.java
  6. 4 1
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ConversationLastTimeReqVO.java
  7. 4 3
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ConversationPinnedReqVO.java
  8. 2 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
  9. 1 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java
  10. 2 1
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveMessageReqVO.java
  11. 2 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/MessageController.java
  12. 5 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessagePageReqVO.java
  13. 3 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessageReqVO.java
  14. 4 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageReqVO.java
  15. 2 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageRespVO.java
  16. 8 3
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ConversationDO.java
  17. 1 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupDO.java
  18. 1 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupMemberDO.java
  19. 4 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/InboxDO.java
  20. 16 5
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/MessageDO.java
  21. 2 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java
  22. 2 1
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/InboxMapper.java
  23. 2 4
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationServiceImpl.java
  24. 1 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxService.java
  25. 4 1
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java
  26. 9 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
  27. 1 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
  28. 0 13
      yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ConversationMapper.xml
  29. 0 12
      yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/group/ImGroupMapper.xml
  30. 0 12
      yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/groupmember/ImGroupMemberMapper.xml
  31. 0 12
      yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/inbox/InboxMapper.xml
  32. 0 12
      yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/message/MessageMapper.xml

+ 2 - 1
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java

@@ -6,6 +6,7 @@ import lombok.Getter;
 
 import java.util.Arrays;
 
+// TODO @anhaohao:IM 前缀还是要的哈
 /**
  * IM 会话类型枚举
  * 参考 <a href="https://doc.rentsoft.cn/zh-Hans/sdks/enum/conversationType">“会话类型”</a> 文档
@@ -38,7 +39,7 @@ public enum ConversationTypeEnum implements IntArrayValuable {
     }
 
     /**
-     * 生成会话编号
+     * 生成会话编号 TODO @anhaohao:方法注释,和下面参数之间,要有空格
      * @param fromUserId 发送者编号
      * @param receiverId 接收者编号
      * @param conversationType 会话类型

+ 4 - 4
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageContentTypeEnum.java

@@ -6,7 +6,7 @@ import lombok.Getter;
 
 import java.util.Arrays;
 
-
+// TODO @anhaohao:IM 前缀还是要的哈
 /**
  * IM 消息的类型枚举
  * <p>
@@ -34,11 +34,11 @@ public enum MessageContentTypeEnum implements IntArrayValuable {
     QUOTE(114, "引用消息"),
     FACE(115, "表情消息"),
     ADVANCED_REVOKE(118, "高级撤回消息"),
-    //好友通知 1200-1299
+    // ========== 好友通知 1200-1299 ===========
     FRIEND_ADDED(1201, "双方成为好友通知"),
-    //系统通知 1400
+    // ========== 系统通知 1400 ==========
     OA_NOTIFICATION(1400, "系统通知"),
-    //群相关 1500-1599
+    // ========== 群相关 1500-1599 ==========
     GROUP_CREATED(1501, "群创建通知"),
     GROUP_INFO_CHANGED(1502, "群信息改变通知"),
     MEMBER_QUIT(1504, "群成员退出通知"),

+ 3 - 2
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageSourceEnum.java

@@ -6,8 +6,9 @@ import lombok.RequiredArgsConstructor;
 
 import java.util.Arrays;
 
+// TODO @anhaohao:IM 前缀还是要的哈
 /**
- * IM 消息的消息来源 100-用户发送;200-系统发送(一般是通知);不能为空
+ * IM 消息的消息来源
  */
 @RequiredArgsConstructor
 @Getter
@@ -18,11 +19,11 @@ public enum MessageSourceEnum implements IntArrayValuable {
 
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageSourceEnum::getStatus).toArray();
 
+    // TODO @anhaohao:应该是 source
     /**
      * 状态
      */
     private final Integer status;
-
     /**
      * 名字
      */

+ 9 - 0
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageStatusEnum.java

@@ -6,6 +6,15 @@ import lombok.RequiredArgsConstructor;
 
 import java.util.Arrays;
 
+// TODO @anhaohao:IM 前缀还是要的哈
+// TODO TODO 状态是这些哈,客户端的视角:
+//
+//- 草稿(预留) 0
+//- 发送中 1
+//- 发送成功 2
+//- 发送失败 3
+//- 已删除 4
+//- 已撤回 5
 /**
  * IM 消息的状态枚举
  */

+ 1 - 1
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ConversationController.java

@@ -18,6 +18,7 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
+// TODO @anhaohao:im 前缀少啦
 @Tag(name = "管理后台 - IM 会话")
 @RestController
 @RequestMapping("/im/conversation")
@@ -42,7 +43,6 @@ public class ConversationController {
         return success(true);
     }
 
-
     // TODO @hao:这个接口,需要单独的 VO 哈;
     @PostMapping("/update-last-read-time")
     @Operation(summary = "更新最后已读时间")

+ 4 - 1
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ConversationLastTimeReqVO.java

@@ -7,10 +7,12 @@ import lombok.Data;
 
 import java.time.LocalDateTime;
 
+// TODO @anhaohao:改成 ConversationUpdateLastReadTimeReqVO,项目目前都是动名词哈。更新置顶
 @Schema(description = "管理后台 - 会话最后已读时间 Request VO")
 @Data
 public class ConversationLastTimeReqVO {
 
+    // TODO @anhaohao:no 不用传递哈。因为 userId + targetId 可以推出来
     @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "s_1_2")
     @NotEmpty(message = "会话标志不能为空")
     private String no;
@@ -19,6 +21,7 @@ public class ConversationLastTimeReqVO {
     @NotNull(message = "最后已读时间不能为空")
     private LocalDateTime lastReadTime;
 
+    // TODO @anhaohao:userId 不用传递,因为 token 已经能解析出当前用户
     @Schema(description = "所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long userId;
 
@@ -26,6 +29,6 @@ public class ConversationLastTimeReqVO {
     private Long targetId;
 
     @Schema(description = "会话类型",requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer type; //枚举 ConversationTypeEnum
+    private Integer type; // 枚举 ConversationTypeEnum TODO ,这里可以使用 @InEnum 校验,这样这个注释就不用写了
 
 }

+ 4 - 3
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ConversationPinnedReqVO.java

@@ -8,10 +8,12 @@ import lombok.Data;
 
 import java.time.LocalDateTime;
 
+// TODO @anhaohao:改成 ConversationUpdatePinnedReqVO,项目目前都是动名词哈。更新置顶
 @Schema(description = "管理后台 - 会话置顶 Request VO")
 @Data
 public class ConversationPinnedReqVO {
 
+    // TODO @anhaohao:no 不用传递哈。因为 userId + targetId 可以推出来
     @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "s_1_2")
     @NotEmpty(message = "会话标志不能为空")
     private String no;
@@ -20,6 +22,7 @@ public class ConversationPinnedReqVO {
     @NotNull(message = "是否置顶不能为空")
     private Boolean pinned;
 
+    // TODO @anhaohao:userId 不用传递,因为 token 已经能解析出当前用户
     @Schema(description = "所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long userId;
 
@@ -27,8 +30,6 @@ public class ConversationPinnedReqVO {
     private Long targetId;
 
     @Schema(description = "会话类型",requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer type; //枚举 ConversationTypeEnum
-
-
+    private Integer type; // 枚举 ConversationTypeEnum TODO ,这里可以使用 @InEnum 校验,这样这个注释就不用写了
 
 }

+ 2 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java

@@ -28,6 +28,7 @@ import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
 import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupDO;
 import cn.iocoder.yudao.module.im.service.group.ImGroupService;
 
+// TODO @芋艿:得看看 create、update、delete、get、page 这几个接口,要保留哪些
 @Tag(name = "管理后台 - 群")
 @RestController
 @RequestMapping("/im/group")
@@ -78,6 +79,7 @@ public class ImGroupController {
         return success(BeanUtils.toBean(pageResult, ImGroupRespVO.class));
     }
 
+    // TODO @anhaohao:导出可以先不做哈;
     @GetMapping("/export-excel")
     @Operation(summary = "导出群 Excel")
     @PreAuthorize("@ss.hasPermission('im:group:export')")

+ 1 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java

@@ -27,6 +27,7 @@ import java.util.List;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
+// TODO @芋艿:得看看 create、update、delete、get、page 这几个接口,要保留哪些
 @Tag(name = "管理后台 - 群成员")
 @RestController
 @RequestMapping("/im/group-member")

+ 2 - 1
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveMessageReqVO.java

@@ -5,6 +5,7 @@ import lombok.Data;
 
 import java.time.LocalDateTime;
 
+// TODO @anhaohao:im 前缀哈
 @Schema(description = "管理后台 - 收件箱保存消息 Request VO")
 @Data
 public class InboxSaveMessageReqVO {
@@ -20,7 +21,7 @@ public class InboxSaveMessageReqVO {
 
     @Schema(description = "发送人头像", requiredMode = Schema.RequiredMode.REQUIRED)
     private String senderAvatar;
-    
+
     @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
     private Long receiverId;
 

+ 2 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/MessageController.java

@@ -36,6 +36,7 @@ public class MessageController {
         return success(messageService.sendMessage(getLoginUserId(), message));
     }
 
+    // TODO @anhaohao:我在想,这个接口,改成叫 pullMessageList,会不会更好理解?拉取消息列表
     @GetMapping("/list-by-sequence")
     @Operation(summary = "拉取大于 sequence 的消息列表")
     @Parameter(name = "sequence", description = "序号", required = true, example = "1")
@@ -46,6 +47,7 @@ public class MessageController {
         return success(BeanUtils.toBean(messages, MessageReqVO.class));
     }
 
+    // TODO @anhaohao:直接叫 getMessageList,不叫历史哈;因为它只是给用户叫历史,对系统来说,就是消息列表
     @GetMapping("/history")
     @Operation(summary = "查询聊天记录-根据会话标志和发送时间进行分页查询")
     public CommonResult<List<MessageReqVO>> getHistoryMessage(@Valid MessagePageReqVO pageReqVO) {

+ 5 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessagePageReqVO.java

@@ -10,14 +10,19 @@ import java.time.LocalDateTime;
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
+// TODO @anhaohao:这个类,不要交 Page,而是消息列表,MessageListReqVO
 @Schema(description = "管理后台 - 消息分页 Request VO")
 @Data
 @ToString(callSuper = true)
 public class MessagePageReqVO {
 
+    // TODO @anhaohao:还是传递 targetId 和 conversationType,我们要弱化 no 的概念;
+
     @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "g_1000")
     private String conversationNo;
 
+    // TODO @anhaohao:应该不传递时间范围,而是传递分页的时间,然后根据时间,查询消息
+
     @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-27")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] sendTime;

+ 3 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessageReqVO.java

@@ -12,6 +12,8 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
+// TODO @anhaohao:MessageRespVO 消息响应 Response VO
+// TODO @anahaohao:每个 example 都写下;啊哈,漏了地方,要补下;因为 http mock 的时候,可以根据它去生成
 @Schema(description = "管理后台 - 消息 Request VO")
 @Data
 public class MessageReqVO {
@@ -22,6 +24,7 @@ public class MessageReqVO {
     @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer conversationType; // 对应 ImConversationTypeEnum 枚举
 
+    // TODO @anhaohao:这个应该是 senderId
     @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long fromId;  // 根据 conversationType 区分
 

+ 4 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageReqVO.java

@@ -7,6 +7,10 @@ import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+// TODO @anhaohao:MessageSendReqVO,消息发送
+
+// TODO @anhaohao:不应该有 excel 相关的注解
+
 @Schema(description = "管理后台 - 发送消息 Request VO")
 @Data
 @ExcelIgnoreUnannotated

+ 2 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageRespVO.java

@@ -10,6 +10,8 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
+// TODO @anhaohao:MessageSendRespVO,消息发送结果
+
 @Schema(description = "管理后台 - 发送消息 Response VO")
 @Data
 @AllArgsConstructor

+ 8 - 3
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ConversationDO.java

@@ -9,6 +9,7 @@ import lombok.*;
 
 import java.time.LocalDateTime;
 
+// TODO @anhaohao:还是有 IM 前缀哈
 /**
  * IM 会话 DO
  *
@@ -44,15 +45,19 @@ public class ConversationDO extends BaseDO {
     /**
      * 聊天对象编号
      * <p>
-     * 1. 单聊时,用户编号;群聊时,群编号
+     * 1. 单聊时,用户编号;
+     * 2. 群聊时,群编号
      */
     private Long targetId;
     /**
-     * 会话标志 单聊:s_{userId}_{targetId},需要排序 userId 和 targetId 群聊:g_groupId
+     * 会话标志
+     *
+     * 1. 单聊:s_{userId}_{targetId},需要排序 userId 和 targetId
+     * 2. 群聊:g_groupId
      */
     private String no;
     /**
-     * 是否置顶 0否 1是
+     * 是否置顶
      */
     private Boolean pinned;
     /**

+ 1 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupDO.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
+// TODO @anhaohao:还是要有 IM
 /**
  * IM 群信息 DO
  *

+ 1 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupMemberDO.java

@@ -4,6 +4,7 @@ import lombok.*;
 import com.baomidou.mybatisplus.annotation.*;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 
+// TODO @anhaohao:还是要有 IM
 /**
  * IM 群成员 DO
  *

+ 4 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/InboxDO.java

@@ -1,11 +1,13 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.inbox;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
+// TODO @anhaohao:还是要有 IM
 // TODO 我们要不要改成 ImMessageQueue 队列?从理解上,概念上,可能都更清晰一点哈。每个用户一个消息队列;
 /**
  * IM 收件箱 DO
@@ -35,6 +37,8 @@ public class InboxDO extends BaseDO {
     private Long userId;
     /**
      * 消息编号
+     *
+     * 关联 {@link MessageDO#getId()}
      */
     private Long messageId;
     /**

+ 16 - 5
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/MessageDO.java

@@ -12,6 +12,7 @@ import lombok.*;
 
 import java.time.LocalDateTime;
 
+// TODO @anhaohao:还是要有 IM
 /**
  * IM 消息 DO
  *
@@ -63,15 +64,21 @@ public class MessageDO extends BaseDO {
      */
     private Integer conversationType;
     /**
-     * 会话标志 {@link ConversationTypeEnum} 的generateConversationNo() 方法生成
+     * 会话标志
+     *
+     * 生成规则:{@link ConversationTypeEnum#generateConversationNo(Long, Long, Integer)} 方法
      */
     private String conversationNo;
     /**
-     * 消息类型 枚举 {@link MessageContentTypeEnum}
+     * 消息类型
+     *
+     * 枚举 {@link MessageContentTypeEnum}
      */
     private Integer contentType;
     /**
-     * 消息内容 JSON 格式 对应 dal/dataobject/message/content 包
+     * 消息内容
+     *
+     * JSON 格式 对应 dal/dataobject/message/content 包
      */
     private String content;
     /**
@@ -79,11 +86,15 @@ public class MessageDO extends BaseDO {
      */
     private LocalDateTime sendTime;
     /**
-     * 消息来源 枚举 {@link MessageSourceEnum}
+     * 消息来源
+     *
+     * 枚举 {@link MessageSourceEnum}
      */
     private Integer sendFrom;
     /**
-     * 消息状态 枚举 {@link MessageStatusEnum}
+     * 消息状态
+     *
+     * 枚举 {@link MessageStatusEnum}
      */
     private Integer messageStatus;
 

+ 2 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java

@@ -5,6 +5,8 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+// TODO @anhaohao:要有 IM;
+// TODO @芋艿:后续要挪到 api 包下,主要是给外部接口使用
 /**
  * 语音消息的 {@link MessageDO 字段 content} 的内容
  *

+ 2 - 1
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/InboxMapper.java

@@ -15,12 +15,13 @@ import java.util.List;
 @Mapper
 public interface InboxMapper extends BaseMapperX<InboxDO> {
 
+    // TODO @anhaohao:返回 List<InboxDO> ,转换成 messageId 交给上层;dao 尽量通用
     default List<Long> selectMessageIdsByUserIdAndSequence(Long userId, Long sequence, Integer size) {
         return selectList(new LambdaQueryWrapperX<InboxDO>()
                 .gt(InboxDO::getUserId, userId)
                 .gt(InboxDO::getSequence, sequence)
                 .orderByAsc(InboxDO::getSequence)
-                .last("limit 0," + size))
+                .last("limit 0," + size)) // TODO @anhaohao:这里 limit 就可以了,不用从 limit 0 开始;
                 .stream()
                 .map(InboxDO::getMessageId)
                 .toList();

+ 2 - 4
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationServiceImpl.java

@@ -12,8 +12,6 @@ import org.springframework.validation.annotation.Validated;
 
 import java.util.List;
 
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-
 /**
  * IM 会话 Service 实现类
  *
@@ -43,6 +41,7 @@ public class ConversationServiceImpl implements ConversationService {
         ConversationDO conversation = conversationMapper.selectByNo(updateReqVO.getNo());
         if (conversation == null) {
             ConversationDO conversationDO = new ConversationDO();
+            // TODO @hao:no 不是前端传递哈,后端生成;另外,其实可以把 insert 写成一个公用方法;get会话,拿不到就 insert;接着处理 update 操作;首次多 update 一次,无所谓的;没多少量的
             conversationDO.setNo(updateReqVO.getNo());
             conversationDO.setPinned(updateReqVO.getPinned());
             conversationDO.setUserId(updateReqVO.getUserId());
@@ -50,11 +49,10 @@ public class ConversationServiceImpl implements ConversationService {
             conversationDO.setType(updateReqVO.getType());
             conversationMapper.insert(conversationDO);
         } else {
-            // 更新
+            // 更新 TODO @anhaohao:这里不要 toBean,因为这里逻辑偏 toc,new ConversationDO 对象,然后逐个 set 需要的值;
             ConversationDO updateObj = BeanUtils.toBean(updateReqVO, ConversationDO.class);
             conversationMapper.updateById(updateObj);
         }
-
     }
 
     @Override

+ 1 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxService.java

@@ -27,4 +27,5 @@ public interface InboxService {
      * @return 消息编号列表
      */
     List<Long> selectMessageIdsByUserIdAndSequence(Long userId, Long sequence, Integer size);
+
 }

+ 4 - 1
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java

@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.im.service.inbox;
 
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
 import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveMessageReqVO;
 import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSendMessageReqVO;
 import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
@@ -43,6 +42,7 @@ public class InboxServiceImpl implements InboxService {
     @Resource
     private GroupMemberService groupMemberService;
 
+    // TODO @anhaohao:下面的逻辑,最好是,1. 保存收件箱 + 发送消息给用户; 2. xxx;这样看的人,会更有感觉哈;
     @Override
     public void saveInboxAndSendMessage(InboxSaveMessageReqVO inboxSaveMessage) {
         // 保存收件箱 + 发送消息给用户
@@ -64,12 +64,15 @@ public class InboxServiceImpl implements InboxService {
     private void saveInboxAndSendMessageForUser(Long userId, InboxSaveMessageReqVO inboxSaveMessage) {
         inboxLockRedisDAO.lock(userId, INBOX_LOCK_TIMEOUT, () -> {
             Long userSequence = sequenceRedisDao.generateSequence(userId);
+            // TODO @anhaohao:链式调用;
             InboxDO inbox = new InboxDO();
             inbox.setUserId(userId);
             inbox.setMessageId(inboxSaveMessage.getMessageId());
             inbox.setSequence(userSequence);
             inboxMapper.insert(inbox);
 
+            // TODO @anhaohao:是不是 send 不用在加锁里面哈?!
+            // TODO @anhaohao:再进一步,是不是用 spring @async 可以并发推送噢
             InboxSendMessageReqVO message = BeanUtils.toBean(inboxSaveMessage, InboxSendMessageReqVO.class);
             message.setSequence(userSequence);
             webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId, IM_MESSAGE_RECEIVE, message);

+ 9 - 2
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java

@@ -58,20 +58,25 @@ public class MessageServiceImpl implements MessageService {
     @Override
     public SendMessageRespVO sendMessage(Long fromUserId, SendMessageReqVO message) {
         // 保存消息
+        // TODO @anhaohao:InboxSaveMessageReqVO 不用 new 出来传递到 saveMessage 方法里;
         InboxSaveMessageReqVO inboxSaveMessageReqVO = new InboxSaveMessageReqVO();
         SendMessageRespVO sendMessageRespVO = saveMessage(fromUserId, message, inboxSaveMessageReqVO);
 
         // 保存收件箱 + 发送消息给用户
+        // TODO @anhaohao:考虑到少定义一些 VO,直接传递 MessageDO 就完事了;反正这两者也是强耦合的;
         inboxService.saveInboxAndSendMessage(inboxSaveMessageReqVO);
         return sendMessageRespVO;
     }
 
+    // TODO @anhaohao:这个方法,是不是定义成 private 哈;然后返回是 MessageDO 对象,设置最上面的 sendMessage 也是这个。最终 controller 转成 SendMessageRespVO
     public SendMessageRespVO saveMessage(Long fromUserId, SendMessageReqVO message, InboxSaveMessageReqVO inboxSaveMessageReqVO) {
-        //需要校验 receiverId 存在
+        // 需要校验 receiverId 存在
         validateReceiverIdExists(message);
         // 查询发送人昵称和发送人头像
         AdminUserRespDTO fromUser = adminUserApi.getUser(fromUserId);
         // 使用链式调用创建 MessageDO 对象
+        // TODO @anhaohao:一部分字段,可以 beanutils tobean 搞定;
+        // TODO @anhaohao:链式 set 的时候,要把相同的放在一行;例如说,setSenderNickname、setSenderAvatar;本质上,就是为了“同类”在一行,阅读起来简单;
         MessageDO messageDO = new MessageDO()
                 .setClientMessageId(message.getClientMessageId())
                 .setSenderId(fromUserId)
@@ -102,17 +107,19 @@ public class MessageServiceImpl implements MessageService {
         return new SendMessageRespVO(messageDO.getId(), messageDO.getSendTime());
     }
 
+    // TODO @anhaohao:validateReceiver,更简单一点哈;不仅仅校验存在,未来还可以校验,自己是不是有好友关系、群聊是否在群聊里面等等
     private void validateReceiverIdExists(SendMessageReqVO message) {
+        // TODO @anhaohao:这个不要这里校验,交给 validator 校验掉
         if (message.getReceiverId() == null) {
             throw exception(MESSAGE_RECEIVER_NOT_EXISTS);
         }
         if (message.getConversationType().equals(ConversationTypeEnum.SINGLE.getType())) {
+            // TODO @anhaohao:// 之后要空一个空格,中英文协作习惯,中文和英文之间,不能连着;最后也不用 ;哈
             //校验用户是否存在;
             AdminUserRespDTO receiverUser = adminUserApi.getUser(message.getReceiverId());
             if (receiverUser == null) {
                 throw exception(MESSAGE_RECEIVER_NOT_EXISTS);
             }
-
         } else if (message.getConversationType().equals(ConversationTypeEnum.GROUP.getType())) {
             //校验群聊是否存在;
             List<GroupMemberDO> groupMemberDOS = groupMemberService.selectByGroupId(message.getReceiverId());

+ 1 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java

@@ -15,6 +15,7 @@ public class ImReceiveMessage {
     @InEnum(ConversationTypeEnum.class)
     private Integer conversationType;
 
+    // TODO @anhaohao:我们应该是 senderId;因为它和 receiverId 是相对应的哈。
     @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long fromId;  // 根据 conversationType 区分
 

+ 0 - 13
yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ConversationMapper.xml

@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper">
-
-    <!-- TODO @hao:xml 如果用不到,可以先删除哈 -->
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 12
yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/group/ImGroupMapper.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 12
yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/groupmember/ImGroupMemberMapper.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 12
yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/inbox/InboxMapper.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 12
yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/message/MessageMapper.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.iocoder.yudao.module.im.dal.mysql.message.MessageMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>