Explorar el Código

修改:代码优化

安浩浩 hace 1 año
padre
commit
fa23ce144d
Se han modificado 54 ficheros con 537 adiciones y 825 borrados
  1. 13 13
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ImConversationTypeEnum.java
  2. 2 3
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageContentTypeEnum.java
  3. 3 5
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageSourceEnum.java
  4. 7 13
      yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java
  5. 10 12
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationController.java
  6. 0 34
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ConversationLastTimeReqVO.java
  7. 0 35
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ConversationPinnedReqVO.java
  8. 26 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationUpdateLastReadTimeReqVO.java
  9. 24 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationUpdatePinnedReqVO.java
  10. 8 22
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
  11. 4 4
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java
  12. 0 43
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveMessageReqVO.java
  13. 5 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/package-info.java
  14. 57 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImMessageController.java
  15. 0 59
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/MessageController.java
  16. 33 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageListReqVO.java
  17. 21 16
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageRespVO.java
  18. 12 16
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSendReqVO.java
  19. 1 3
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSendRespVO.java
  20. 0 30
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessagePageReqVO.java
  21. 0 52
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessageReqVO.java
  22. 3 4
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ImConversationDO.java
  23. 1 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java
  24. 1 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupMemberDO.java
  25. 7 7
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/ImInboxDO.java
  26. 15 16
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImMessageDO.java
  27. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java
  28. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java
  29. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
  30. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
  31. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
  32. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
  33. 2 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
  34. 4 5
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java
  35. 30 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/GroupMapper.java
  36. 0 30
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java
  37. 35 0
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/GroupMemberMapper.java
  38. 0 35
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java
  39. 8 21
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/InboxMapper.java
  40. 7 11
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/MessageMapper.java
  41. 1 2
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceRedisDAO.java
  42. 8 6
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationService.java
  43. 37 37
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationServiceImpl.java
  44. 4 4
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/GroupService.java
  45. 14 14
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/GroupServiceImpl.java
  46. 4 4
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/GroupMemberService.java
  47. 15 15
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/GroupMemberServiceImpl.java
  48. 3 3
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxService.java
  49. 43 32
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java
  50. 13 12
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageService.java
  51. 44 71
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
  52. 0 49
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
  53. 0 39
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
  54. 0 30
      yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java

+ 13 - 13
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java → yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ImConversationTypeEnum.java

@@ -6,7 +6,6 @@ import lombok.Getter;
 
 import java.util.Arrays;
 
-// TODO @anhaohao:IM 前缀还是要的哈
 /**
  * IM 会话类型枚举
  * 参考 <a href="https://doc.rentsoft.cn/zh-Hans/sdks/enum/conversationType">“会话类型”</a> 文档
@@ -15,13 +14,13 @@ import java.util.Arrays;
  */
 @Getter
 @AllArgsConstructor
-public enum ConversationTypeEnum implements IntArrayValuable {
+public enum ImConversationTypeEnum implements IntArrayValuable {
 
     SINGLE(1, "单聊"),
     GROUP(3, "群聊"),
     NOTIFICATION(4, "通知会话");
 
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ConversationTypeEnum::getType).toArray();
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImConversationTypeEnum::getType).toArray();
 
     /**
      * 类型
@@ -33,25 +32,26 @@ public enum ConversationTypeEnum implements IntArrayValuable {
      */
     private final String name;
 
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
     /**
-     * 生成会话编号 TODO @anhaohao:方法注释,和下面参数之间,要有空格
-     * @param fromUserId 发送者编号
-     * @param receiverId 接收者编号
+     * 生成会话编号
+     *
+     * @param fromUserId       发送者编号
+     * @param receiverId       接收者编号
      * @param conversationType 会话类型
      * @return 会话编号
      */
     public static String generateConversationNo(Long fromUserId, Long receiverId, Integer conversationType) {
-        if (conversationType.equals(ConversationTypeEnum.SINGLE.getType())) {
+        if (conversationType.equals(ImConversationTypeEnum.SINGLE.getType())) {
             return "s_" + fromUserId + "_" + receiverId;
-        } else if (conversationType.equals(ConversationTypeEnum.GROUP.getType())) {
+        } else if (conversationType.equals(ImConversationTypeEnum.GROUP.getType())) {
             return "g_" + receiverId;
         }
         return null;
     }
 
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
 }

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

@@ -6,7 +6,6 @@ import lombok.Getter;
 
 import java.util.Arrays;
 
-// TODO @anhaohao:IM 前缀还是要的哈
 /**
  * IM 消息的类型枚举
  * <p>
@@ -16,7 +15,7 @@ import java.util.Arrays;
  */
 @Getter
 @AllArgsConstructor
-public enum MessageContentTypeEnum implements IntArrayValuable {
+public enum ImMessageContentTypeEnum implements IntArrayValuable {
 
     TEXT(101, "文本消息"),
     PICTURE(102, "图片消息"),
@@ -57,7 +56,7 @@ public enum MessageContentTypeEnum implements IntArrayValuable {
     BURN_CHANGE(1701, "阅后即焚开启或关闭通知"),
     REVOKE(2101, "撤回消息通知");;
 
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageContentTypeEnum::getType).toArray();
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageContentTypeEnum::getType).toArray();
 
     /**
      * 类型

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

@@ -6,24 +6,22 @@ import lombok.RequiredArgsConstructor;
 
 import java.util.Arrays;
 
-// TODO @anhaohao:IM 前缀还是要的哈
 /**
  * IM 消息的消息来源
  */
 @RequiredArgsConstructor
 @Getter
-public enum MessageSourceEnum implements IntArrayValuable {
+public enum ImMessageSourceEnum implements IntArrayValuable {
 
     USER_SEND(100, "用户发送"),
     SYSTEM_SEND(200, "系统发送");
 
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageSourceEnum::getStatus).toArray();
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageSourceEnum::getSource).toArray();
 
-    // TODO @anhaohao:应该是 source
     /**
      * 状态
      */
-    private final Integer status;
+    private final Integer source;
     /**
      * 名字
      */

+ 7 - 13
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageStatusEnum.java → yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java

@@ -6,27 +6,21 @@ import lombok.RequiredArgsConstructor;
 
 import java.util.Arrays;
 
-// TODO @anhaohao:IM 前缀还是要的哈
-// TODO TODO 状态是这些哈,客户端的视角:
-//
-//- 草稿(预留) 0
-//- 发送中 1
-//- 发送成功 2
-//- 发送失败 3
-//- 已删除 4
-//- 已撤回 5
 /**
  * IM 消息的状态枚举
  */
 @RequiredArgsConstructor
 @Getter
-public enum MessageStatusEnum implements IntArrayValuable {
+public enum ImMessageStatusEnum implements IntArrayValuable {
 
+    DRAFT(0, "草稿"),
     SENDING(1, "发送中"),
-    SUCCEED(2, "发送成功"),
-    FAILED(3, "发送失败");
+    SUCCESS(2, "发送成功"),
+    FAILURE(3, "发送失败"),
+    DELETED(4, "已删除"),
+    RECALL(5, "已撤回");
 
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageStatusEnum::getStatus).toArray();
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageStatusEnum::getStatus).toArray();
 
     /**
      * 状态

+ 10 - 12
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ConversationController.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationController.java

@@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.im.controller.admin.conversation;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ConversationLastTimeReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO;
 import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationRespVO;
-import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ConversationPinnedReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
+import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
 import cn.iocoder.yudao.module.im.service.conversation.ConversationService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -17,13 +17,13 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
-// TODO @anhaohao:im 前缀少啦
 @Tag(name = "管理后台 - IM 会话")
 @RestController
 @RequestMapping("/im/conversation")
 @Validated
-public class ConversationController {
+public class ImConversationController {
 
     @Resource
     private ConversationService conversationService;
@@ -31,23 +31,21 @@ public class ConversationController {
     @GetMapping("/list")
     @Operation(summary = "获得用户的会话列表")
     public CommonResult<List<ImConversationRespVO>> getConversationList() {
-        List<ConversationDO> conversationList = conversationService.getConversationList();
+        List<ImConversationDO> conversationList = conversationService.getConversationList();
         return success(BeanUtils.toBean(conversationList, ImConversationRespVO.class));
     }
 
-    // TODO @hao:这个接口,需要单独的 VO 哈;
     @PostMapping("/update-pinned")
     @Operation(summary = "置顶会话")
-    public CommonResult<Boolean> updatePinned(@Valid @RequestBody ConversationPinnedReqVO updateReqVO) {
-        conversationService.updatePinned(updateReqVO);
+    public CommonResult<Boolean> updatePinned(@Valid @RequestBody ImConversationUpdatePinnedReqVO updateReqVO) {
+        conversationService.updatePinned(getLoginUserId(),updateReqVO);
         return success(true);
     }
 
-    // TODO @hao:这个接口,需要单独的 VO 哈;
     @PostMapping("/update-last-read-time")
     @Operation(summary = "更新最后已读时间")
-    public CommonResult<Boolean> updateLastReadTime(@Valid @RequestBody ConversationLastTimeReqVO updateReqVO) {
-        conversationService.updateLastReadTime(updateReqVO);
+    public CommonResult<Boolean> updateLastReadTime(@Valid @RequestBody ImConversationUpdateLastReadTimeReqVO updateReqVO) {
+        conversationService.updateLastReadTime(getLoginUserId(),updateReqVO);
         return success(true);
     }
 

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

@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.conversation.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-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;
-
-    @Schema(description = "最后已读时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-01 00:00:00")
-    @NotNull(message = "最后已读时间不能为空")
-    private LocalDateTime lastReadTime;
-
-    // TODO @anhaohao:userId 不用传递,因为 token 已经能解析出当前用户
-    @Schema(description = "所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Long userId;
-
-    @Schema(description = "聊天对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
-    private Long targetId;
-
-    @Schema(description = "会话类型",requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer type; // 枚举 ConversationTypeEnum TODO ,这里可以使用 @InEnum 校验,这样这个注释就不用写了
-
-}

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

@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.conversation.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-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;
-
-    @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "是否置顶不能为空")
-    private Boolean pinned;
-
-    // TODO @anhaohao:userId 不用传递,因为 token 已经能解析出当前用户
-    @Schema(description = "所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Long userId;
-
-    @Schema(description = "聊天对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
-    private Long targetId;
-
-    @Schema(description = "会话类型",requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer type; // 枚举 ConversationTypeEnum TODO ,这里可以使用 @InEnum 校验,这样这个注释就不用写了
-
-}

+ 26 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationUpdateLastReadTimeReqVO.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.im.controller.admin.conversation.vo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 会话最后已读时间 Request VO")
+@Data
+public class ImConversationUpdateLastReadTimeReqVO {
+
+    @Schema(description = "最后已读时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-01 00:00:00")
+    @NotNull(message = "最后已读时间不能为空")
+    private LocalDateTime lastReadTime;
+
+    @Schema(description = "聊天对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Long targetId;
+
+    @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @InEnum(value = ImConversationTypeEnum.class, message = "会话类型必须是 {value}")
+    private Integer type;
+
+}

+ 24 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationUpdatePinnedReqVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.im.controller.admin.conversation.vo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 会话置顶 Request VO")
+@Data
+public class ImConversationUpdatePinnedReqVO {
+
+    @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "是否置顶不能为空")
+    private Boolean pinned;
+
+    @Schema(description = "聊天对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Long targetId;
+
+    @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @InEnum(value = ImConversationTypeEnum.class, message = "会话类型必须是 {value}")
+    private Integer type;
+
+}

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

@@ -25,8 +25,8 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
 
 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;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
+import cn.iocoder.yudao.module.im.service.group.GroupService;
 
 // TODO @芋艿:得看看 create、update、delete、get、page 这几个接口,要保留哪些
 @Tag(name = "管理后台 - 群")
@@ -36,20 +36,20 @@ import cn.iocoder.yudao.module.im.service.group.ImGroupService;
 public class ImGroupController {
 
     @Resource
-    private ImGroupService imGroupService;
+    private GroupService groupService;
 
     @PostMapping("/create")
     @Operation(summary = "创建群")
     @PreAuthorize("@ss.hasPermission('im:group:create')")
     public CommonResult<Long> createGroup(@Valid @RequestBody ImGroupSaveReqVO createReqVO) {
-        return success(imGroupService.createGroup(createReqVO));
+        return success(groupService.createGroup(createReqVO));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新群")
     @PreAuthorize("@ss.hasPermission('im:group:update')")
     public CommonResult<Boolean> updateGroup(@Valid @RequestBody ImGroupSaveReqVO updateReqVO) {
-        imGroupService.updateGroup(updateReqVO);
+        groupService.updateGroup(updateReqVO);
         return success(true);
     }
 
@@ -58,7 +58,7 @@ public class ImGroupController {
     @Parameter(name = "id", description = "编号", required = true)
     @PreAuthorize("@ss.hasPermission('im:group:delete')")
     public CommonResult<Boolean> deleteGroup(@RequestParam("id") Long id) {
-        imGroupService.deleteGroup(id);
+        groupService.deleteGroup(id);
         return success(true);
     }
 
@@ -67,7 +67,7 @@ public class ImGroupController {
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('im:group:query')")
     public CommonResult<ImGroupRespVO> getGroup(@RequestParam("id") Long id) {
-        GroupDO group = imGroupService.getGroup(id);
+        ImGroupDO group = groupService.getGroup(id);
         return success(BeanUtils.toBean(group, ImGroupRespVO.class));
     }
 
@@ -75,22 +75,8 @@ public class ImGroupController {
     @Operation(summary = "获得群分页")
     @PreAuthorize("@ss.hasPermission('im:group:query')")
     public CommonResult<PageResult<ImGroupRespVO>> getGroupPage(@Valid ImGroupPageReqVO pageReqVO) {
-        PageResult<GroupDO> pageResult = imGroupService.getGroupPage(pageReqVO);
+        PageResult<ImGroupDO> pageResult = groupService.getGroupPage(pageReqVO);
         return success(BeanUtils.toBean(pageResult, ImGroupRespVO.class));
     }
 
-    // TODO @anhaohao:导出可以先不做哈;
-    @GetMapping("/export-excel")
-    @Operation(summary = "导出群 Excel")
-    @PreAuthorize("@ss.hasPermission('im:group:export')")
-    @OperateLog(type = EXPORT)
-    public void exportGroupExcel(@Valid ImGroupPageReqVO pageReqVO,
-              HttpServletResponse response) throws IOException {
-        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<GroupDO> list = imGroupService.getGroupPage(pageReqVO).getList();
-        // 导出 Excel
-        ExcelUtils.write(response, "群.xls", "数据", ImGroupRespVO.class,
-                        BeanUtils.toBean(list, ImGroupRespVO.class));
-    }
-
 }

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

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
 import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberRespVO;
 import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
 import cn.iocoder.yudao.module.im.service.groupmember.GroupMemberService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -66,7 +66,7 @@ public class ImGroupMemberController {
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('im:group-member:query')")
     public CommonResult<ImGroupMemberRespVO> getGroupMember(@RequestParam("id") Long id) {
-        GroupMemberDO groupMember = groupMemberService.getGroupMember(id);
+        ImGroupMemberDO groupMember = groupMemberService.getGroupMember(id);
         return success(BeanUtils.toBean(groupMember, ImGroupMemberRespVO.class));
     }
 
@@ -74,7 +74,7 @@ public class ImGroupMemberController {
     @Operation(summary = "获得群成员分页")
     @PreAuthorize("@ss.hasPermission('im:group-member:query')")
     public CommonResult<PageResult<ImGroupMemberRespVO>> getGroupMemberPage(@Valid ImGroupMemberPageReqVO pageReqVO) {
-        PageResult<GroupMemberDO> pageResult = groupMemberService.getGroupMemberPage(pageReqVO);
+        PageResult<ImGroupMemberDO> pageResult = groupMemberService.getGroupMemberPage(pageReqVO);
         return success(BeanUtils.toBean(pageResult, ImGroupMemberRespVO.class));
     }
 
@@ -85,7 +85,7 @@ public class ImGroupMemberController {
     public void exportGroupMemberExcel(@Valid ImGroupMemberPageReqVO pageReqVO,
                                        HttpServletResponse response) throws IOException {
         pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<GroupMemberDO> list = groupMemberService.getGroupMemberPage(pageReqVO).getList();
+        List<ImGroupMemberDO> list = groupMemberService.getGroupMemberPage(pageReqVO).getList();
         // 导出 Excel
         ExcelUtils.write(response, "群成员.xls", "数据", ImGroupMemberRespVO.class,
                 BeanUtils.toBean(list, ImGroupMemberRespVO.class));

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

@@ -1,43 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.inbox.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-// TODO @anhaohao:im 前缀哈
-@Schema(description = "管理后台 - 收件箱保存消息 Request VO")
-@Data
-public class InboxSaveMessageReqVO {
-
-    @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer conversationType; // 对应 ImConversationTypeEnum 枚举
-
-    @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long fromId;  // 根据 conversationType 区分
-
-    @Schema(description = "发送人昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
-    private String senderNickname;
-
-    @Schema(description = "发送人头像", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String senderAvatar;
-
-    @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
-    private Long receiverId;
-
-    @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
-    private Long messageId;
-
-    @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer contentType; // 参见 ImMessageTypeEnum 枚举
-
-    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String content;
-
-    @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime sendTime;
-
-//    @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
-//    private Long sequence;
-
-}

+ 5 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/package-info.java

@@ -0,0 +1,5 @@
+/**
+ * @author anhaohao
+ * @since 2024/3/31 下午10:41
+ */
+package cn.iocoder.yudao.module.im.controller.admin.inbox.vo;

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

@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.im.controller.admin.message;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageRespVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendRespVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
+import cn.iocoder.yudao.module.im.service.message.MessageService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Tag(name = "管理后台 - IM 消息")
+@RestController
+@RequestMapping("/im/message")
+@Validated
+public class ImMessageController {
+
+    @Resource
+    private MessageService messageService;
+
+    @PostMapping("/send")
+    @Operation(summary = "发送消息")
+    public CommonResult<ImMessageSendRespVO> sendMessage(@Valid @RequestBody ImMessageSendReqVO imMessageSendReqVO) {
+        ImMessageDO message = messageService.sendMessage(getLoginUserId(), imMessageSendReqVO);
+        return success(BeanUtils.toBean(message, ImMessageSendRespVO.class));
+    }
+
+    @GetMapping("/pull")
+    @Operation(summary = "消息列表-拉取大于 sequence 的消息列表")
+    @Parameter(name = "sequence", description = "序号", required = true, example = "1")
+    @Parameter(name = "size", description = "条数", required = true, example = "10")
+    public CommonResult<List<ImMessageRespVO>> pullMessageList(@RequestParam("sequence") Long sequence,
+                                                               @RequestParam("size") Integer size) {
+        List<ImMessageDO> messages = messageService.pullMessageList(getLoginUserId(), sequence, size);
+        return success(BeanUtils.toBean(messages, ImMessageRespVO.class));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "消息列表-根据接收人和发送时间进行分页查询")
+    public CommonResult<List<ImMessageRespVO>> getMessageList(@Valid ImMessageListReqVO listReqVO) {
+        List<ImMessageDO> messagePage = messageService.getMessageList(getLoginUserId(), listReqVO);
+        return success(BeanUtils.toBean(messagePage, ImMessageRespVO.class));
+    }
+
+}

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

@@ -1,59 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.message;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.MessagePageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.MessageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.SendMessageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.SendMessageRespVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
-import cn.iocoder.yudao.module.im.service.message.MessageService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.annotation.Resource;
-import jakarta.validation.Valid;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-
-@Tag(name = "管理后台 - IM 消息")
-@RestController
-@RequestMapping("/im/message")
-@Validated
-public class MessageController {
-
-    @Resource
-    private MessageService messageService;
-
-    @PostMapping("/send")
-    @Operation(summary = "发送消息")
-    public CommonResult<SendMessageRespVO> sendMessage(@Valid @RequestBody SendMessageReqVO message) {
-        return success(messageService.sendMessage(getLoginUserId(), message));
-    }
-
-    // TODO @anhaohao:我在想,这个接口,改成叫 pullMessageList,会不会更好理解?拉取消息列表
-    @GetMapping("/list-by-sequence")
-    @Operation(summary = "拉取大于 sequence 的消息列表")
-    @Parameter(name = "sequence", description = "序号", required = true, example = "1")
-    @Parameter(name = "size", description = "条数", required = true, example = "10")
-    public CommonResult<List<MessageReqVO>> getMessageListBySequence(@RequestParam("sequence") Long sequence,
-                                                                     @RequestParam("size") Integer size) {
-        List<MessageDO> messages = messageService.getMessageListBySequence(getLoginUserId(), sequence, size);
-        return success(BeanUtils.toBean(messages, MessageReqVO.class));
-    }
-
-    // TODO @anhaohao:直接叫 getMessageList,不叫历史哈;因为它只是给用户叫历史,对系统来说,就是消息列表
-    @GetMapping("/history")
-    @Operation(summary = "查询聊天记录-根据会话标志和发送时间进行分页查询")
-    public CommonResult<List<MessageReqVO>> getHistoryMessage(@Valid MessagePageReqVO pageReqVO) {
-        //根据会话标志和发送时间进行分页查询
-        List<MessageDO> messagePage = messageService.getHistoryMessage(pageReqVO);
-        return success(BeanUtils.toBean(messagePage, MessageReqVO.class));
-    }
-
-}

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

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.im.controller.admin.message.vo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+
+@Schema(description = "管理后台 - 消息列表 Request VO")
+@Data
+@ToString(callSuper = true)
+public class ImMessageListReqVO {
+
+    @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
+    @NotNull(message = "接收人编号不能为空")
+    private Long receiverId;
+
+    @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @InEnum(value = ImConversationTypeEnum.class,message = "会话类型必须是 {value}")
+    @NotNull(message = "会话类型不能为空")
+    private Integer conversationType;
+
+    @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-27 12:00:00")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private LocalDateTime sendTime;
+
+}

+ 21 - 16
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSendMessageReqVO.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageRespVO.java

@@ -1,42 +1,47 @@
-package cn.iocoder.yudao.module.im.controller.admin.inbox.vo;
+package cn.iocoder.yudao.module.im.controller.admin.message.vo;
 
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageContentTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
 
-@Schema(description = "管理后台 - 收件箱保存消息 Request VO")
+@Schema(description = "管理后台 - 消息 Response VO")
 @Data
-public class InboxSendMessageReqVO {
+public class ImMessageRespVO {
+
+    @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
+    private Long id;
 
     @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer conversationType; // 对应 ImConversationTypeEnum 枚举
+    @InEnum(value = ImConversationTypeEnum.class)
+    private Integer conversationType;
 
-    @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long fromId;  // 根据 conversationType 区分
+    @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Long senderId;
 
     @Schema(description = "发送人昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
     private String senderNickname;
 
-    @Schema(description = "发送人头像", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "发送人头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://www.iocoder.cn/xxx.jpg")
     private String senderAvatar;
-    
-    @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
-    private Long receiverId;
 
-    @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
-    private Long messageId;
+    @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Long receiverId;
 
     @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer contentType; // 参见 ImMessageTypeEnum 枚举
+    @InEnum(value = ImMessageContentTypeEnum.class)
+    private Integer contentType;
 
-    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好")
     private String content;
 
-    @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-27 12:00:00")
     private LocalDateTime sendTime;
 
-    @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long sequence;
 
 }

+ 12 - 16
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageReqVO.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSendReqVO.java

@@ -1,40 +1,36 @@
 package cn.iocoder.yudao.module.im.controller.admin.message.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageContentTypeEnum;
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageContentTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
-// TODO @anhaohao:MessageSendReqVO,消息发送
-
-// TODO @anhaohao:不应该有 excel 相关的注解
-
 @Schema(description = "管理后台 - 发送消息 Request VO")
 @Data
-@ExcelIgnoreUnannotated
-public class SendMessageReqVO {
+public class ImMessageSendReqVO {
 
     @Schema(description = "客户端消息编号 uuid,用于排重", requiredMode = Schema.RequiredMode.REQUIRED, example = "3331")
-    @ExcelProperty("客户端消息编号 uuid,用于排重")
+    @NotNull(message = "客户端消息编号不能为空")
     private String clientMessageId;
 
     @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
-    @ExcelProperty("接收人编号")
+    @NotNull(message = "接收人编号不能为空")
     private Long receiverId;
 
     @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
-    @ExcelProperty("会话类型")
+    @InEnum(value = ImConversationTypeEnum.class)
+    @NotNull(message = "会话类型不能为空")
     private Integer conversationType;
 
     @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @ExcelProperty("消息类型")
-    @InEnum(MessageContentTypeEnum.class)
+    @InEnum(ImMessageContentTypeEnum.class)
+    @NotNull(message = "消息类型不能为空")
     private Integer contentType;
 
-    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("消息内容")
+    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好")
+    @NotNull(message = "消息内容不能为空")
     private String content;
 
 }

+ 1 - 3
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageRespVO.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSendRespVO.java

@@ -10,13 +10,11 @@ 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
 @NoArgsConstructor
-public class SendMessageRespVO {
+public class ImMessageSendRespVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
     private Long id;

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

@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.message.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-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;
-
-}

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

@@ -1,52 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.message.vo;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageContentTypeEnum;
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-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 {
-
-    @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
-    private Long id;
-
-    @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 区分
-
-    @Schema(description = "发送人昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
-    private String senderNickname;
-
-    @Schema(description = "发送人头像", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String senderAvatar;
-
-    @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
-    private Long receiverId;
-
-    @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer contentType; // 参见 ImMessageTypeEnum 枚举
-
-    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String content;
-
-    @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime sendTime;
-
-    @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
-    private Long sequence;
-
-}

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

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.conversation;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -9,7 +9,6 @@ import lombok.*;
 
 import java.time.LocalDateTime;
 
-// TODO @anhaohao:还是有 IM 前缀哈
 /**
  * IM 会话 DO
  *
@@ -23,7 +22,7 @@ import java.time.LocalDateTime;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class ConversationDO extends BaseDO {
+public class ImConversationDO extends BaseDO {
 
     /**
      * 编号
@@ -39,7 +38,7 @@ public class ConversationDO extends BaseDO {
     /**
      * 会话类型
      * <p>
-     * 枚举 {@link ConversationTypeEnum}
+     * 枚举 {@link ImConversationTypeEnum}
      */
     private Integer type;
     /**

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

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
-// TODO @anhaohao:还是要有 IM
 /**
  * IM 群信息 DO
  *
@@ -20,7 +19,7 @@ import lombok.*;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class GroupDO extends BaseDO {
+public class ImGroupDO extends BaseDO {
 
     /**
      * 编号

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

@@ -4,7 +4,6 @@ import lombok.*;
 import com.baomidou.mybatisplus.annotation.*;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 
-// TODO @anhaohao:还是要有 IM
 /**
  * IM 群成员 DO
  *
@@ -18,7 +17,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class GroupMemberDO extends BaseDO {
+public class ImGroupMemberDO extends BaseDO {
 
     /**
      * 编号

+ 7 - 7
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/InboxDO.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/ImInboxDO.java

@@ -1,14 +1,14 @@
 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 cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 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
  *
@@ -22,7 +22,7 @@ import lombok.*;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class InboxDO extends BaseDO {
+public class ImInboxDO extends BaseDO {
 
     /**
      * 编号
@@ -31,14 +31,14 @@ public class InboxDO extends BaseDO {
     private Long id;
     /**
      * 用户编号
-     *
-     * TODO @hao:写下 userId 和 messageId 的关联字段
+     * <p>
+     * 关联 {@link ImMessageDO#getSenderId()}  或者 {@link ImMessageDO#getReceiverId()}
      */
     private Long userId;
     /**
      * 消息编号
-     *
-     * 关联 {@link MessageDO#getId()}
+     * <p>
+     * 关联 {@link ImMessageDO#getId()}
      */
     private Long messageId;
     /**

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

@@ -1,10 +1,10 @@
 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.conversation.ConversationTypeEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageContentTypeEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageSourceEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageStatusEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageContentTypeEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageSourceEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -12,7 +12,6 @@ import lombok.*;
 
 import java.time.LocalDateTime;
 
-// TODO @anhaohao:还是要有 IM
 /**
  * IM 消息 DO
  *
@@ -26,7 +25,7 @@ import java.time.LocalDateTime;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class MessageDO extends BaseDO {
+public class ImMessageDO extends BaseDO {
 
     /**
      * 编号
@@ -60,24 +59,24 @@ public class MessageDO extends BaseDO {
      */
     private String senderAvatar;
     /**
-     * 会话类型 枚举 {@link ConversationTypeEnum}
+     * 会话类型 枚举 {@link ImConversationTypeEnum}
      */
     private Integer conversationType;
     /**
      * 会话标志
-     *
-     * 生成规则:{@link ConversationTypeEnum#generateConversationNo(Long, Long, Integer)} 方法
+     * <p>
+     * 生成规则:{@link ImConversationTypeEnum#generateConversationNo(Long, Long, Integer)} 方法
      */
     private String conversationNo;
     /**
      * 消息类型
-     *
-     * 枚举 {@link MessageContentTypeEnum}
+     * <p>
+     * 枚举 {@link ImMessageContentTypeEnum}
      */
     private Integer contentType;
     /**
      * 消息内容
-     *
+     * <p>
      * JSON 格式 对应 dal/dataobject/message/content 包
      */
     private String content;
@@ -87,14 +86,14 @@ public class MessageDO extends BaseDO {
     private LocalDateTime sendTime;
     /**
      * 消息来源
-     *
-     * 枚举 {@link MessageSourceEnum}
+     * <p>
+     * 枚举 {@link ImMessageSourceEnum}
      */
     private Integer sendFrom;
     /**
      * 消息状态
-     *
-     * 枚举 {@link MessageStatusEnum}
+     * <p>
+     * 枚举 {@link ImMessageStatusEnum}
      */
     private Integer messageStatus;
 

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

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
 // TODO @anhaohao:要有 IM;
 // TODO @芋艿:后续要挪到 api 包下,主要是给外部接口使用
 /**
- * 语音消息的 {@link MessageDO 字段 content} 的内容
+ * 语音消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author 芋道源码
  */

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

@@ -1,12 +1,12 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 /**
- * 名片消息的 {@link MessageDO 字段 content} 的内容
+ * 名片消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author anhaohao
  * @since 2024/3/23 下午5:53

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

@@ -1,12 +1,12 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 /**
- * 文件消息的 {@link MessageDO 字段 content} 的内容
+ * 文件消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author 芋道源码
  */

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

@@ -1,12 +1,12 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 /**
- * 图片消息的 {@link MessageDO 字段 content} 的内容
+ * 图片消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author 芋道源码
  */

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

@@ -1,12 +1,12 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 /**
- * 地址位置消息的 {@link MessageDO 字段 content} 的内容
+ * 地址位置消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author 芋道源码
  */

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

@@ -1,12 +1,12 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 /**
- * 文本消息的 {@link MessageDO 字段 content} 的内容
+ * 文本消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author 芋道源码
  */

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

@@ -1,10 +1,10 @@
 package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
 
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import lombok.Data;
 
 /**
- * 视频消息的 {@link MessageDO 字段 content} 的内容
+ * 视频消息的 {@link ImMessageDO 字段 content} 的内容
  *
  * @author 芋道源码
  */

+ 4 - 5
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.module.im.dal.mysql.conversation;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
@@ -11,9 +10,9 @@ import org.apache.ibatis.annotations.Mapper;
  * @author 芋道源码
  */
 @Mapper
-public interface ConversationMapper extends BaseMapperX<ConversationDO> {
+public interface ConversationMapper extends BaseMapperX<ImConversationDO> {
 
-    default ConversationDO selectByNo(String no){
-        return selectOne(ConversationDO::getNo, no);
+    default ImConversationDO selectByNo(String no){
+        return selectOne(ImConversationDO::getNo, no);
     }
 }

+ 30 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/GroupMapper.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.im.dal.mysql.group;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
+
+/**
+ * 群 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface GroupMapper extends BaseMapperX<ImGroupDO> {
+
+    default PageResult<ImGroupDO> selectPage(ImGroupPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<ImGroupDO>()
+                .likeIfPresent(ImGroupDO::getGroupName, reqVO.getGroupName())
+                .eqIfPresent(ImGroupDO::getOwnerId, reqVO.getOwnerId())
+                .eqIfPresent(ImGroupDO::getHeadImage, reqVO.getHeadImage())
+                .eqIfPresent(ImGroupDO::getHeadImageThumb, reqVO.getHeadImageThumb())
+                .eqIfPresent(ImGroupDO::getNotice, reqVO.getNotice())
+                .eqIfPresent(ImGroupDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(ImGroupDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(ImGroupDO::getId));
+    }
+
+}

+ 0 - 30
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java

@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.im.dal.mysql.group;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupDO;
-import org.apache.ibatis.annotations.Mapper;
-import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
-
-/**
- * 群 Mapper
- *
- * @author 芋道源码
- */
-@Mapper
-public interface ImGroupMapper extends BaseMapperX<GroupDO> {
-
-    default PageResult<GroupDO> selectPage(ImGroupPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<GroupDO>()
-                .likeIfPresent(GroupDO::getGroupName, reqVO.getGroupName())
-                .eqIfPresent(GroupDO::getOwnerId, reqVO.getOwnerId())
-                .eqIfPresent(GroupDO::getHeadImage, reqVO.getHeadImage())
-                .eqIfPresent(GroupDO::getHeadImageThumb, reqVO.getHeadImageThumb())
-                .eqIfPresent(GroupDO::getNotice, reqVO.getNotice())
-                .eqIfPresent(GroupDO::getRemark, reqVO.getRemark())
-                .betweenIfPresent(GroupDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(GroupDO::getId));
-    }
-
-}

+ 35 - 0
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/GroupMemberMapper.java

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.im.dal.mysql.groupmember;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 群成员 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface GroupMemberMapper extends BaseMapperX<ImGroupMemberDO> {
+
+    default PageResult<ImGroupMemberDO> selectPage(ImGroupMemberPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<ImGroupMemberDO>()
+                .eqIfPresent(ImGroupMemberDO::getGroupId, reqVO.getGroupId())
+                .eqIfPresent(ImGroupMemberDO::getUserId, reqVO.getUserId())
+                .likeIfPresent(ImGroupMemberDO::getNickname, reqVO.getNickname())
+                .eqIfPresent(ImGroupMemberDO::getAvatar, reqVO.getAvatar())
+                .likeIfPresent(ImGroupMemberDO::getAliasName, reqVO.getAliasName())
+                .eqIfPresent(ImGroupMemberDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(ImGroupMemberDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(ImGroupMemberDO::getId));
+    }
+
+    default List<ImGroupMemberDO> selectListByGroupId(Long groupId) {
+        return selectList(new LambdaQueryWrapperX<ImGroupMemberDO>().eq(ImGroupMemberDO::getGroupId, groupId));
+    }
+}

+ 0 - 35
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java

@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.im.dal.mysql.groupmember;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-
-/**
- * 群成员 Mapper
- *
- * @author 芋道源码
- */
-@Mapper
-public interface ImGroupMemberMapper extends BaseMapperX<GroupMemberDO> {
-
-    default PageResult<GroupMemberDO> selectPage(ImGroupMemberPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<GroupMemberDO>()
-                .eqIfPresent(GroupMemberDO::getGroupId, reqVO.getGroupId())
-                .eqIfPresent(GroupMemberDO::getUserId, reqVO.getUserId())
-                .likeIfPresent(GroupMemberDO::getNickname, reqVO.getNickname())
-                .eqIfPresent(GroupMemberDO::getAvatar, reqVO.getAvatar())
-                .likeIfPresent(GroupMemberDO::getAliasName, reqVO.getAliasName())
-                .eqIfPresent(GroupMemberDO::getRemark, reqVO.getRemark())
-                .betweenIfPresent(GroupMemberDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(GroupMemberDO::getId));
-    }
-
-    default List<GroupMemberDO> selectListByGroupId(Long groupId) {
-        return selectList(new LambdaQueryWrapperX<GroupMemberDO>().eq(GroupMemberDO::getGroupId, groupId));
-    }
-}

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

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.inbox;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.InboxDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -13,27 +13,14 @@ import java.util.List;
  * @author 芋道源码
  */
 @Mapper
-public interface InboxMapper extends BaseMapperX<InboxDO> {
+public interface InboxMapper extends BaseMapperX<ImInboxDO> {
 
-    // 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)) // TODO @anhaohao:这里 limit 就可以了,不用从 limit 0 开始;
-                .stream()
-                .map(InboxDO::getMessageId)
-                .toList();
+    default List<ImInboxDO> selectListByUserIdAndSequence(Long userId, Long sequence, Integer size) {
+        return selectList(new LambdaQueryWrapperX<ImInboxDO>()
+                .gt(ImInboxDO::getUserId, userId)
+                .gt(ImInboxDO::getSequence, sequence)
+                .orderByAsc(ImInboxDO::getSequence)
+                .last("LIMIT " + size));
     }
 
-//    default PageResult<InboxDO> selectPage(ImInboxPageReqVO reqVO) {
-//        return selectPage(reqVO, new LambdaQueryWrapperX<InboxDO>()
-//                .eqIfPresent(InboxDO::getUserId, reqVO.getUserId())
-//                .eqIfPresent(InboxDO::getMessageId, reqVO.getMessageId())
-//                .eqIfPresent(InboxDO::getSequence, reqVO.getSequence())
-//                .betweenIfPresent(InboxDO::getCreateTime, reqVO.getCreateTime())
-//                .orderByDesc(InboxDO::getId));
-//    }
-
 }

+ 7 - 11
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/MessageMapper.java

@@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.message;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.MessagePageReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.InboxDO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
-import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -16,13 +13,12 @@ import java.util.List;
  * @author 芋道源码
  */
 @Mapper
-public interface MessageMapper extends BaseMapperX<MessageDO> {
+public interface MessageMapper extends BaseMapperX<ImMessageDO> {
 
-    default List<MessageDO> getHistoryMessage(MessagePageReqVO pageReqVO) {
-        return selectList(new LambdaQueryWrapperX<MessageDO>()
-                .eqIfPresent(MessageDO::getConversationNo, pageReqVO.getConversationNo())
-                .betweenIfPresent(MessageDO::getSendTime, pageReqVO.getSendTime())
-                .orderByAsc(MessageDO::getSendTime));
+    default List<ImMessageDO> selectMessageList(ImMessageDO message) {
+        return selectList(new LambdaQueryWrapperX<ImMessageDO>()
+                .eqIfPresent(ImMessageDO::getConversationNo, message.getConversationNo())
+                .eqIfPresent(ImMessageDO::getSendTime, message.getSendTime())
+                .orderByAsc(ImMessageDO::getSendTime));
     }
-
 }

+ 1 - 2
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceRedisDao.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceRedisDAO.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.im.dal.redis.inbox;
 
 import jakarta.annotation.Resource;
-import org.redisson.api.RedissonClient;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Repository;
 
@@ -15,7 +14,7 @@ import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.INBOX_SEQUE
  * @author anhaohao
  */
 @Repository
-public class SequenceRedisDao {
+public class SequenceRedisDAO {
 
     @Resource
     private RedisTemplate<String, Long> redisTemplate;

+ 8 - 6
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationService.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.im.service.conversation;
 
-import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ConversationLastTimeReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ConversationPinnedReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
+import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
 
 import java.util.List;
 
@@ -18,20 +18,22 @@ public interface ConversationService {
      *
      * @return 会话列表
      */
-    List<ConversationDO> getConversationList();
+    List<ImConversationDO> getConversationList();
 
     /**
      * 置顶会话
      *
+     * @param loginUserId 登录用户编号
      * @param updateReqVO 更新信息
      */
-    void updatePinned(ConversationPinnedReqVO updateReqVO);
+    void updatePinned(Long loginUserId, ImConversationUpdatePinnedReqVO updateReqVO);
 
     /**
      * 更新最后已读时间
      *
+     * @param loginUserId 登录用户编号
      * @param updateReqVO 更新信息
      */
-    void updateLastReadTime(ConversationLastTimeReqVO updateReqVO);
+    void updateLastReadTime(Long loginUserId, ImConversationUpdateLastReadTimeReqVO updateReqVO);
 
 }

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

@@ -1,10 +1,10 @@
 package cn.iocoder.yudao.module.im.service.conversation;
 
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ConversationLastTimeReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ConversationPinnedReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
+import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
 import cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
 import cn.iocoder.yudao.module.im.service.inbox.InboxService;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
@@ -27,50 +27,50 @@ public class ConversationServiceImpl implements ConversationService {
     private InboxService inboxService;
 
     @Override
-    public List<ConversationDO> getConversationList() {
+    public List<ImConversationDO> getConversationList() {
         return conversationMapper.selectList();
     }
 
     @Override
-    public void updatePinned(ConversationPinnedReqVO updateReqVO) {
-        // TODO @hao:updateTop 和 updateLastReadTime 使用独立的逻辑实现,不使用统一的 ImConversationSaveReqVO;
-        // TODO 大体步骤建议:
-        // 1. 先 getOrderCreateConversation,查询会话,不存在则插入;
-        // 2. 更新对应的字段
-        // 3. 做对应更新的 notify 推送
-        ConversationDO conversation = conversationMapper.selectByNo(updateReqVO.getNo());
+    public void updatePinned(Long loginUserId, ImConversationUpdatePinnedReqVO updateReqVO) {
+        // 1. 获得会话编号
+        String no = ImConversationTypeEnum.generateConversationNo(loginUserId, updateReqVO.getTargetId(), updateReqVO.getType());
+        // 2. 查询会话
+        ImConversationDO conversation = conversationMapper.selectByNo(no);
         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());
-            conversationDO.setTargetId(updateReqVO.getTargetId());
-            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);
+            // 2.1. 不存在,则插入
+            conversation = insertConversation(no, loginUserId, updateReqVO.getTargetId(), updateReqVO.getType());
         }
+        // 3. 更新会话
+        conversation.setPinned(updateReqVO.getPinned());
+        conversationMapper.updateById(conversation);
+        // 4. 做对应更新的 notify 推送
+    }
+
+    private ImConversationDO insertConversation(String no, Long userId, Long targetId, Integer type) {
+        ImConversationDO imConversationDO = new ImConversationDO();
+        imConversationDO.setNo(no);
+        imConversationDO.setUserId(userId);
+        imConversationDO.setTargetId(targetId);
+        imConversationDO.setType(type);
+        conversationMapper.insert(imConversationDO);
+        return imConversationDO;
     }
 
     @Override
-    public void updateLastReadTime(ConversationLastTimeReqVO updateReqVO) {
-        ConversationDO conversation = conversationMapper.selectByNo(updateReqVO.getNo());
+    public void updateLastReadTime(Long loginUserId, ImConversationUpdateLastReadTimeReqVO updateReqVO) {
+        // 1. 获得会话编号
+        String no = ImConversationTypeEnum.generateConversationNo(loginUserId, updateReqVO.getTargetId(), updateReqVO.getType());
+        // 2. 查询会话
+        ImConversationDO conversation = conversationMapper.selectByNo(no);
         if (conversation == null) {
-            ConversationDO conversationDO = new ConversationDO();
-            conversationDO.setNo(updateReqVO.getNo());
-            conversationDO.setLastReadTime(updateReqVO.getLastReadTime());
-            conversationDO.setUserId(updateReqVO.getUserId());
-            conversationDO.setTargetId(updateReqVO.getTargetId());
-            conversationDO.setType(updateReqVO.getType());
-            conversationMapper.insert(conversationDO);
-        } else {
-            // 更新
-            ConversationDO updateObj = BeanUtils.toBean(updateReqVO, ConversationDO.class);
-            conversationMapper.updateById(updateObj);
+            // 2.1. 不存在,则插入
+            conversation = insertConversation(no, loginUserId, updateReqVO.getTargetId(), updateReqVO.getType());
         }
+        // 3. 更新会话
+        conversation.setLastReadTime(updateReqVO.getLastReadTime());
+        conversationMapper.updateById(conversation);
+        // 4. 做对应更新的 notify 推送
     }
 
 }

+ 4 - 4
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/GroupService.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.im.service.group;
 
 import jakarta.validation.*;
 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.dal.dataobject.group.ImGroupDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 
 /**
@@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
  *
  * @author 芋道源码
  */
-public interface ImGroupService {
+public interface GroupService {
 
     /**
      * 创建群
@@ -40,7 +40,7 @@ public interface ImGroupService {
      * @param id 编号
      * @return 群
      */
-    GroupDO getGroup(Long id);
+    ImGroupDO getGroup(Long id);
 
     /**
      * 获得群分页
@@ -48,6 +48,6 @@ public interface ImGroupService {
      * @param pageReqVO 分页查询
      * @return 群分页
      */
-    PageResult<GroupDO> getGroupPage(ImGroupPageReqVO pageReqVO);
+    PageResult<ImGroupDO> getGroupPage(ImGroupPageReqVO pageReqVO);
 
 }

+ 14 - 14
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java → yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/GroupServiceImpl.java

@@ -5,11 +5,11 @@ import jakarta.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
 
 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.dal.dataobject.group.ImGroupDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 
-import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper;
+import cn.iocoder.yudao.module.im.dal.mysql.group.GroupMapper;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
@@ -21,16 +21,16 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
  */
 @Service
 @Validated
-public class ImGroupServiceImpl implements ImGroupService {
+public class GroupServiceImpl implements GroupService {
 
     @Resource
-    private ImGroupMapper imGroupMapper;
+    private GroupMapper groupMapper;
 
     @Override
     public Long createGroup(ImGroupSaveReqVO createReqVO) {
         // 插入
-        GroupDO group = BeanUtils.toBean(createReqVO, GroupDO.class);
-        imGroupMapper.insert(group);
+        ImGroupDO group = BeanUtils.toBean(createReqVO, ImGroupDO.class);
+        groupMapper.insert(group);
         // 返回
         return group.getId();
     }
@@ -40,8 +40,8 @@ public class ImGroupServiceImpl implements ImGroupService {
         // 校验存在
         validateGroupExists(updateReqVO.getId());
         // 更新
-        GroupDO updateObj = BeanUtils.toBean(updateReqVO, GroupDO.class);
-        imGroupMapper.updateById(updateObj);
+        ImGroupDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupDO.class);
+        groupMapper.updateById(updateObj);
     }
 
     @Override
@@ -49,23 +49,23 @@ public class ImGroupServiceImpl implements ImGroupService {
         // 校验存在
         validateGroupExists(id);
         // 删除
-        imGroupMapper.deleteById(id);
+        groupMapper.deleteById(id);
     }
 
     private void validateGroupExists(Long id) {
-        if (imGroupMapper.selectById(id) == null) {
+        if (groupMapper.selectById(id) == null) {
             throw exception(GROUP_NOT_EXISTS);
         }
     }
 
     @Override
-    public GroupDO getGroup(Long id) {
-        return imGroupMapper.selectById(id);
+    public ImGroupDO getGroup(Long id) {
+        return groupMapper.selectById(id);
     }
 
     @Override
-    public PageResult<GroupDO> getGroupPage(ImGroupPageReqVO pageReqVO) {
-        return imGroupMapper.selectPage(pageReqVO);
+    public PageResult<ImGroupDO> getGroupPage(ImGroupPageReqVO pageReqVO) {
+        return groupMapper.selectPage(pageReqVO);
     }
 
 }

+ 4 - 4
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/GroupMemberService.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.im.service.groupmember;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
 import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
 import jakarta.validation.Valid;
 
 import java.util.List;
@@ -43,7 +43,7 @@ public interface GroupMemberService {
      * @param id 编号
      * @return 群成员
      */
-    GroupMemberDO getGroupMember(Long id);
+    ImGroupMemberDO getGroupMember(Long id);
 
     /**
      * 获得群成员分页
@@ -51,7 +51,7 @@ public interface GroupMemberService {
      * @param pageReqVO 分页查询
      * @return 群成员分页
      */
-    PageResult<GroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO);
+    PageResult<ImGroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO);
 
     /**
      * 根据群组id查询群成员
@@ -59,5 +59,5 @@ public interface GroupMemberService {
      * @param groupId 群组id
      * @return 群成员列表
      */
-    List<GroupMemberDO> selectByGroupId(Long groupId);
+    List<ImGroupMemberDO> selectByGroupId(Long groupId);
 }

+ 15 - 15
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/GroupMemberServiceImpl.java

@@ -5,11 +5,11 @@ import jakarta.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
 
 import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*;
-import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 
-import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper;
+import cn.iocoder.yudao.module.im.dal.mysql.groupmember.GroupMemberMapper;
 
 import java.util.List;
 
@@ -26,13 +26,13 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
 public class GroupMemberServiceImpl implements GroupMemberService {
 
     @Resource
-    private ImGroupMemberMapper imGroupMemberMapper;
+    private GroupMemberMapper groupMemberMapper;
 
     @Override
     public Long createGroupMember(ImGroupMemberSaveReqVO createReqVO) {
         // 插入
-        GroupMemberDO groupMember = BeanUtils.toBean(createReqVO, GroupMemberDO.class);
-        imGroupMemberMapper.insert(groupMember);
+        ImGroupMemberDO groupMember = BeanUtils.toBean(createReqVO, ImGroupMemberDO.class);
+        groupMemberMapper.insert(groupMember);
         // 返回
         return groupMember.getId();
     }
@@ -42,8 +42,8 @@ public class GroupMemberServiceImpl implements GroupMemberService {
         // 校验存在
         validateGroupMemberExists(updateReqVO.getId());
         // 更新
-        GroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, GroupMemberDO.class);
-        imGroupMemberMapper.updateById(updateObj);
+        ImGroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupMemberDO.class);
+        groupMemberMapper.updateById(updateObj);
     }
 
     @Override
@@ -51,28 +51,28 @@ public class GroupMemberServiceImpl implements GroupMemberService {
         // 校验存在
         validateGroupMemberExists(id);
         // 删除
-        imGroupMemberMapper.deleteById(id);
+        groupMemberMapper.deleteById(id);
     }
 
     private void validateGroupMemberExists(Long id) {
-        if (imGroupMemberMapper.selectById(id) == null) {
+        if (groupMemberMapper.selectById(id) == null) {
             throw exception(GROUP_MEMBER_NOT_EXISTS);
         }
     }
 
     @Override
-    public GroupMemberDO getGroupMember(Long id) {
-        return imGroupMemberMapper.selectById(id);
+    public ImGroupMemberDO getGroupMember(Long id) {
+        return groupMemberMapper.selectById(id);
     }
 
     @Override
-    public PageResult<GroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO) {
-        return imGroupMemberMapper.selectPage(pageReqVO);
+    public PageResult<ImGroupMemberDO> getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO) {
+        return groupMemberMapper.selectPage(pageReqVO);
     }
 
     @Override
-    public List<GroupMemberDO> selectByGroupId(Long groupId) {
-        return imGroupMemberMapper.selectListByGroupId(groupId);
+    public List<ImGroupMemberDO> selectByGroupId(Long groupId) {
+        return groupMemberMapper.selectListByGroupId(groupId);
     }
 
 }

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

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.im.service.inbox;
 
-import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveMessageReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 
 import java.util.List;
 
@@ -14,9 +14,9 @@ public interface InboxService {
     /**
      * 保存收件箱和发送消息
      *
-     * @param inboxSaveMessageReqVO 收件箱保存消息 Request VO
+     * @param imMessageDO 收件箱保存消息 Request VO
      */
-    void saveInboxAndSendMessage(InboxSaveMessageReqVO inboxSaveMessageReqVO);
+    void saveInboxAndSendMessage(ImMessageDO imMessageDO);
 
     /**
      * 获得大于 sequence 的消息ids

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

@@ -2,18 +2,19 @@ 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.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;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.InboxDO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageRespVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper;
 import cn.iocoder.yudao.module.im.dal.redis.inbox.InboxLockRedisDAO;
-import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceRedisDao;
-import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
+import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceRedisDAO;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
 import cn.iocoder.yudao.module.im.service.groupmember.GroupMemberService;
 import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
 import jakarta.annotation.Resource;
 import org.dromara.hutool.core.date.DateUnit;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
@@ -33,50 +34,60 @@ public class InboxServiceImpl implements InboxService {
 
     @Resource
     private InboxMapper inboxMapper;
+
     @Resource
-    private SequenceRedisDao sequenceRedisDao; // 序列生成器Redis DAO
+    private SequenceRedisDAO sequenceRedisDAO;
     @Resource
-    private InboxLockRedisDAO inboxLockRedisDAO; // 收件箱的锁 Redis DAO
+    private InboxLockRedisDAO inboxLockRedisDAO;
+
     @Resource
     private WebSocketSenderApi webSocketSenderApi;
     @Resource
     private GroupMemberService groupMemberService;
 
-    // TODO @anhaohao:下面的逻辑,最好是,1. 保存收件箱 + 发送消息给用户; 2. xxx;这样看的人,会更有感觉哈;
     @Override
-    public void saveInboxAndSendMessage(InboxSaveMessageReqVO inboxSaveMessage) {
-        // 保存收件箱 + 发送消息给用户
-        saveInboxAndSendMessageForUser(inboxSaveMessage.getFromId(), inboxSaveMessage);
-
-        if (inboxSaveMessage.getConversationType().equals(ConversationTypeEnum.SINGLE.getType())) {
-            saveInboxAndSendMessageForUser(inboxSaveMessage.getReceiverId(), inboxSaveMessage);
-        } else if (inboxSaveMessage.getConversationType().equals(ConversationTypeEnum.GROUP.getType())) {
-            List<GroupMemberDO> groupMembers = groupMemberService.selectByGroupId(inboxSaveMessage.getReceiverId());
-            groupMembers.forEach(groupMemberDO -> saveInboxAndSendMessageForUser(groupMemberDO.getUserId(), inboxSaveMessage));
+    public void saveInboxAndSendMessage(ImMessageDO message) {
+        // 1. 保存收件箱 + 发送消息给发送人
+        saveInboxAndSendMessageForUser(message.getSenderId(), message);
+        // 2. 保存收件箱 + 发送消息给接收人
+        if (message.getConversationType().equals(ImConversationTypeEnum.SINGLE.getType())) {
+            // 2.1 如果是单聊,直接发送给接收人
+            saveInboxAndSendMessageForUser(message.getReceiverId(), message);
+        } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
+            // 2.2 如果是群聊,发送给群聊的所有人
+            List<ImGroupMemberDO> groupMembers = groupMemberService.selectByGroupId(message.getReceiverId());
+            groupMembers.forEach(groupMemberDO -> saveInboxAndSendMessageForUser(groupMemberDO.getUserId(), message));
         }
     }
 
     @Override
     public List<Long> selectMessageIdsByUserIdAndSequence(Long userId, Long sequence, Integer size) {
-        return inboxMapper.selectMessageIdsByUserIdAndSequence(userId, sequence, size);
+        List<ImInboxDO> imInboxDOS = inboxMapper.selectListByUserIdAndSequence(userId, sequence, size);
+        return imInboxDOS.stream().map(ImInboxDO::getMessageId).toList();
     }
 
-    private void saveInboxAndSendMessageForUser(Long userId, InboxSaveMessageReqVO inboxSaveMessage) {
+
+    //TODO 多线程处理
+    public void saveInboxAndSendMessageForUser(Long userId, ImMessageDO message) {
         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);
+            // 1. 生成序列号
+            Long userSequence = sequenceRedisDAO.generateSequence(userId);
+            // 2. 保存收件箱
+            ImInboxDO inbox = new ImInboxDO()
+                    .setUserId(userId)
+                    .setMessageId(message.getId())
+                    .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);
+            // 3. 发送消息
+            sendAsyncMessage(userId, message, userSequence);
         });
     }
 
+    @Async
+    public void sendAsyncMessage(Long userId, ImMessageDO message, Long userSequence) {
+        ImMessageRespVO messageRespVO = BeanUtils.toBean(message, ImMessageRespVO.class);
+        messageRespVO.setSequence(userSequence);
+        webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId, IM_MESSAGE_RECEIVE, messageRespVO);
+    }
+
 }

+ 13 - 12
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageService.java

@@ -1,9 +1,8 @@
 package cn.iocoder.yudao.module.im.service.message;
 
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.MessagePageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.SendMessageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.SendMessageRespVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 
 import java.util.List;
 
@@ -17,26 +16,28 @@ public interface MessageService {
     /**
      * 获得历史消息
      *
-     * @param pageReqVO 分页查询
+     * @param loginUserId 登录用户编号
+     * @param listReqVO   分页查询
      * @return 消息分页
      */
-    List<MessageDO> getHistoryMessage(MessagePageReqVO pageReqVO);
+    List<ImMessageDO> getMessageList(Long loginUserId, ImMessageListReqVO listReqVO);
 
     /**
      * 拉取消息-大于 seq 的消息
      *
-     * @param userId   用户id
-     * @param sequence 序列号
-     * @param size 数量
+     * @param loginUserId 登录用户编号
+     * @param sequence    序列号
+     * @param size        数量
      * @return 消息列表
      */
-    List<MessageDO> getMessageListBySequence(Long userId, Long sequence, Integer size);
+    List<ImMessageDO> pullMessageList(Long loginUserId, Long sequence, Integer size);
 
     /**
      * 发送消息
+     *
      * @param loginUserId 登录用户编号
-     * @param message 消息
+     * @param message     消息
      * @return 消息编号
      */
-    SendMessageRespVO sendMessage(Long loginUserId, SendMessageReqVO message);
+    ImMessageDO sendMessage(Long loginUserId, ImMessageSendReqVO message);
 }

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

@@ -1,15 +1,14 @@
 package cn.iocoder.yudao.module.im.service.message;
 
-import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveMessageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.MessagePageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.SendMessageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.SendMessageRespVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import cn.hutool.core.bean.BeanUtil;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
 import cn.iocoder.yudao.module.im.dal.mysql.message.MessageMapper;
-import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageSourceEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageStatusEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageSourceEnum;
+import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
 import cn.iocoder.yudao.module.im.service.groupmember.GroupMemberService;
 import cn.iocoder.yudao.module.im.service.inbox.InboxService;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
@@ -38,92 +37,66 @@ public class MessageServiceImpl implements MessageService {
     @Resource
     private MessageMapper messageMapper;
     @Resource
-    private InboxService inboxService;
-    @Resource
     private AdminUserApi adminUserApi;
     @Resource
+    private InboxService inboxService;
+    @Resource
     private GroupMemberService groupMemberService;
 
     @Override
-    public List<MessageDO> getHistoryMessage(MessagePageReqVO pageReqVO) {
-        return messageMapper.getHistoryMessage(pageReqVO);
+    public List<ImMessageDO> getMessageList(Long loginUserId, ImMessageListReqVO listReqVO) {
+        // 1. 获得会话编号
+        String no = ImConversationTypeEnum.generateConversationNo(loginUserId, listReqVO.getReceiverId(), listReqVO.getConversationType());
+        // 2. 查询历史消息
+        ImMessageDO message = new ImMessageDO()
+                .setSendTime(listReqVO.getSendTime())
+                .setConversationNo(no);
+        return messageMapper.selectMessageList(message);
     }
 
     @Override
-    public List<MessageDO> getMessageListBySequence(Long userId, Long sequence, Integer size) {
+    public List<ImMessageDO> pullMessageList(Long userId, Long sequence, Integer size) {
         List<Long> messageIds = inboxService.selectMessageIdsByUserIdAndSequence(userId, sequence, size);
         return messageMapper.selectBatchIds(messageIds);
     }
 
     @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;
+    public ImMessageDO sendMessage(Long fromUserId, ImMessageSendReqVO imMessageSendReqVO) {
+        // 1. 保存消息
+        ImMessageDO message = saveMessage(fromUserId, imMessageSendReqVO);
+        // 2. 保存到收件箱,并发送消息
+        inboxService.saveInboxAndSendMessage(message);
+        return message;
     }
 
-    // TODO @anhaohao:这个方法,是不是定义成 private 哈;然后返回是 MessageDO 对象,设置最上面的 sendMessage 也是这个。最终 controller 转成 SendMessageRespVO
-    public SendMessageRespVO saveMessage(Long fromUserId, SendMessageReqVO message, InboxSaveMessageReqVO inboxSaveMessageReqVO) {
-        // 需要校验 receiverId 存在
+    private ImMessageDO saveMessage(Long fromUserId, ImMessageSendReqVO message) {
+        // 1. 校验接收人是否存在
         validateReceiverIdExists(message);
-        // 查询发送人昵称和发送人头像
+        // 2. 查询发送人信息
         AdminUserRespDTO fromUser = adminUserApi.getUser(fromUserId);
-        // 使用链式调用创建 MessageDO 对象
-        // TODO @anhaohao:一部分字段,可以 beanutils tobean 搞定;
-        // TODO @anhaohao:链式 set 的时候,要把相同的放在一行;例如说,setSenderNickname、setSenderAvatar;本质上,就是为了“同类”在一行,阅读起来简单;
-        MessageDO messageDO = new MessageDO()
-                .setClientMessageId(message.getClientMessageId())
+        // 3. 保存消息
+        ImMessageDO imMessageDO = BeanUtil.copyProperties(message, ImMessageDO.class)
+                .setSenderNickname(fromUser.getNickname()).setSenderAvatar(fromUser.getAvatar())
                 .setSenderId(fromUserId)
-                .setReceiverId(message.getReceiverId())
-                .setSenderNickname(fromUser.getNickname())
-                .setSenderAvatar(fromUser.getAvatar())
-                .setConversationType(message.getConversationType())
-                .setContentType(message.getContentType())
-                .setConversationNo(ConversationTypeEnum.generateConversationNo(fromUserId, message.getReceiverId(), message.getConversationType()))
-                .setContent(message.getContent())
-                .setSendFrom(MessageSourceEnum.USER_SEND.getStatus())
-                .setSendTime(TimeUtil.now())
-                .setMessageStatus(MessageStatusEnum.SENDING.getStatus());
-        messageMapper.insert(messageDO);
-
-        // 设置 InboxSaveMessageReqVO 对象
-        inboxSaveMessageReqVO.setConversationType(message.getConversationType())
-                .setFromId(fromUserId)
-                .setReceiverId(message.getReceiverId())
-                .setMessageId(messageDO.getId())
-                .setContentType(message.getContentType())
-                .setContent(message.getContent())
-                .setSendTime(messageDO.getSendTime())
-                .setSenderNickname(fromUser.getNickname())
-                .setSenderAvatar(fromUser.getAvatar());
-
-        // 返回 SendMessageRespVO 对象
-        return new SendMessageRespVO(messageDO.getId(), messageDO.getSendTime());
+                .setConversationNo(ImConversationTypeEnum.generateConversationNo(fromUserId, message.getReceiverId(), message.getConversationType()))
+                .setSendFrom(ImMessageSourceEnum.USER_SEND.getSource())
+                .setMessageStatus(ImMessageStatusEnum.SENDING.getStatus())
+                .setSendTime(TimeUtil.now());
+        messageMapper.insert(imMessageDO);
+        return imMessageDO;
     }
 
-    // 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:// 之后要空一个空格,中英文协作习惯,中文和英文之间,不能连着;最后也不用 ;哈
-            //校验用户是否存在;
+    private void validateReceiverIdExists(ImMessageSendReqVO message) {
+        if (message.getConversationType().equals(ImConversationTypeEnum.SINGLE.getType())) {
+            // 校验用户是否存在
             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());
-            if (groupMemberDOS.isEmpty()) {
+        } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
+            // 校验群聊是否存在
+            List<ImGroupMemberDO> imGroupMemberDOS = groupMemberService.selectByGroupId(message.getReceiverId());
+            if (imGroupMemberDOS.isEmpty()) {
                 throw exception(MESSAGE_RECEIVER_NOT_EXISTS);
             }
         }

+ 0 - 49
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java

@@ -1,49 +0,0 @@
-package cn.iocoder.yudao.module.im.websocket;
-
-import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
-import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
-import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
-import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.springframework.web.socket.WebSocketSession;
-
-// TODO @hao:消息发送,使用 http 上行。因为在 cloud 框架下,我们比较难去 Listener。因为 im-server 不会自己启动 websocket 路径
-
-/**
- * WebSocket im
- *
- * @author 芋道源码
- */
-@Component
-@Slf4j
-public class ImWebSocketMessageListener implements WebSocketMessageListener<ImSendMessage> {
-
-    public static final String IM_MESSAGE_RECEIVE = "im-message-receive";
-    @Resource
-    private WebSocketSenderApi webSocketSenderApi; // WebSocket消息发送器
-
-    /**
-     * 处理WebSocket消息
-     *
-     * @param session WebSocket会话
-     * @param message 发送的IM消息
-     */
-    @Override
-    public void onMessage(WebSocketSession session, ImSendMessage message) {
-        Long fromUserId = WebSocketFrameworkUtils.getLoginUserId(session); // 获取登录用户ID
-        log.info(message.toString());
-    }
-
-    /**
-     * 获取类型
-     *
-     * @return 类型
-     */
-    @Override
-    public String getType() {
-        return "im-message-send";
-    }
-
-}

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

@@ -1,39 +0,0 @@
-package cn.iocoder.yudao.module.im.websocket.message;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - 消息发送 receive")
-@Data
-public class ImReceiveMessage {
-
-    @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @InEnum(ConversationTypeEnum.class)
-    private Integer conversationType;
-
-    // TODO @anhaohao:我们应该是 senderId;因为它和 receiverId 是相对应的哈。
-    @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long fromId;  // 根据 conversationType 区分
-
-    // TODO @hao:昵称和头像,也直接发给接收人好了;
-
-    @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
-    private Long messageId;
-
-    @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer contentType; // 参见 ImMessageTypeEnum 枚举
-
-    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String content;
-
-    @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime sendTime;
-
-    @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
-    private Long sequence;
-
-}

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

@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.im.websocket.message;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
-import cn.iocoder.yudao.module.im.enums.message.MessageContentTypeEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-@Schema(description = "管理后台 - IM 消息发送 send")
-@Data
-public class ImSendMessage {
-
-    @Schema(description = "客户端消息编号 uuid,用于排重", requiredMode = Schema.RequiredMode.REQUIRED, example = "3331")
-    private String clientMessageId;
-
-    @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @InEnum(ConversationTypeEnum.class)
-    private Integer conversationType;
-
-    @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long receiverId;  // 根据 conversationType 区分
-
-    @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @InEnum(MessageContentTypeEnum.class)
-    private Integer contentType;
-
-    @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
-    private String content;
-
-}