diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/api/package-info.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/api/package-info.java
index cfe63d8..4938097 100644
--- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/api/package-info.java
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/api/package-info.java
@@ -1,5 +1,5 @@
/**
* @author anhaohao
- * @date 2024/3/9 下午8:59 TODO @hao:没有 @date 这个,应该是 @since 哈
+ * @since 2024/3/9 下午8:59
*/
package cn.iocoder.yudao.module.im.api;
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java
index c56f5da..3232338 100644
--- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java
@@ -17,6 +17,7 @@ public interface ErrorCodeConstants {
// ========== 消息 (1-040-300-000) ==========
ErrorCode MESSAGE_NOT_EXISTS = new ErrorCode(1_040_300_000, "消息不存在");
+ ErrorCode MESSAGE_RECEIVER_NOT_EXISTS = new ErrorCode(1_040_300_001, "接收人不存在");
// ========== 群 (1-040-400-000) ==========
ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_040_400_000, "群不存在");
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ImConversationTypeEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java
index bef578a..afd6bfe 100644
--- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ImConversationTypeEnum.java
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java
@@ -4,26 +4,43 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
- * IM 会话的类型枚举
+ * IM 会话类型枚举
+ * 参考 “会话类型” 文档
*
- * @author 芋道源码
+ * @author anhaohao
*/
@Getter
@AllArgsConstructor
-public enum ImConversationTypeEnum {
+public enum ConversationTypeEnum {
- // TODO @hao:单聊,我们使用 SINGLE,主要 private 这个单词在 java 里太特殊了;
- PRIVATE(1, "单聊"),
- GROUP(2, "群聊"),
- NOTICE(4, "通知会话");
+ SINGLE(1, "单聊"),
+ GROUP(3, "群聊"),
+ NOTIFICATION(4, "通知会话");
/**
* 类型
*/
private final Integer type;
+
/**
* 名字
*/
private final String name;
+ /**
+ * 生成会话编号
+ * @param fromUserId 发送者编号
+ * @param receiverId 接收者编号
+ * @param conversationType 会话类型
+ * @return 会话编号
+ */
+ public static String generateConversationNo(Long fromUserId, Long receiverId, Integer conversationType) {
+ if (conversationType.equals(ConversationTypeEnum.SINGLE.getType())) {
+ return "s_" + fromUserId + "_" + receiverId;
+ } else if (conversationType.equals(ConversationTypeEnum.GROUP.getType())) {
+ return "g_" + receiverId;
+ }
+ return null;
+ }
+
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java
deleted file mode 100644
index 984f62b..0000000
--- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package cn.iocoder.yudao.module.im.enums.message;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-// TODO @hao:类型保持和 openim 一致
-/**
- * IM 消息的类型枚举
- *
- * 参考 “消息类型” 文档
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-public enum ImMessageTypeEnum implements IntArrayValuable {
-
- TEXT(1, "文本"), // 消息内容为普通文本
- IMAGE(2, "图片"), // 消息内容为图片 URL 地址、尺寸、图片大小等信息
- AUDIO(3, "语音"), // 消息内容为语音文件的 URL 地址、时长、大小、格式等信息
- VIDEO(4, "视频"), // 消息内容为视频文件的 URL 地址、时长、大小、格式等信息
- FILE(5, "文件"), // 消息内容为文件的 URL 地址、大小、格式等信息
- LOCATION(6, "地理位置"), // 消息内容为地理位置标题、经度、纬度信息
- // TODO @芋艿:下面两种,貌似企业微信设计的更好:https://developer.work.weixin.qq.com/document/path/90240
- TIP(7, "提示"), // 又叫做 Tip 消息,没有推送和通知栏提醒,主要用于会话内的通知提醒,例如进入会话时出现的欢迎消息,或是会话过程中命中敏感词后的提示消息等场景
- NOTIFICATION(8, "通知"), // 主要用于群组、聊天室和超大群的事件通知,由服务端下发,客户端无法发送事件通知消息。通知类消息有在线、离线、漫游机制;没有通知栏提醒
- ;
-
- public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageTypeEnum::getType).toArray();
- /**
- * 类型
- */
- private final Integer type;
- /**
- * 名字
- */
- private final String name;
-
- @Override
- public int[] array() {
- return ARRAYS;
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageContentTypeEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageContentTypeEnum.java
new file mode 100644
index 0000000..580ed21
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageContentTypeEnum.java
@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.im.enums.message;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+
+/**
+ * IM 消息的类型枚举
+ *
+ * 参考 “消息类型” 文档
+ *
+ * @author anhaohao
+ */
+@Getter
+@AllArgsConstructor
+public enum MessageContentTypeEnum implements IntArrayValuable {
+
+ TEXT(101, "文本消息"),
+ PICTURE(102, "图片消息"),
+ VOICE(103, "语音消息"),
+ VIDEO(104, "视频消息"),
+ FILE(105, "文件消息"),
+ AT_TEXT(106, "@消息"),
+ MERGE(107, "合并消息"),
+ CARD(108, "名片消息"),
+ LOCATION(109, "位置消息"),
+ CUSTOM(110, "自定义消息"),
+ REVOKE_RECEIPT(111, "撤回消息回执"),
+ C2C_RECEIPT(112, "单聊消息回执"),
+ TYPING(113, "输入状态"),
+ QUOTE(114, "引用消息"),
+ FACE(115, "表情消息"),
+ ADVANCED_REVOKE(118, "高级撤回消息"),
+ //好友通知 1200-1299
+ FRIEND_ADDED(1201, "双方成为好友通知"),
+ //系统通知 1400
+ OA_NOTIFICATION(1400, "系统通知"),
+ //群相关 1500-1599
+ GROUP_CREATED(1501, "群创建通知"),
+ GROUP_INFO_CHANGED(1502, "群信息改变通知"),
+ MEMBER_QUIT(1504, "群成员退出通知"),
+ GROUP_OWNER_CHANGED(1507, "群主更换通知"),
+ MEMBER_KICKED(1508, "群成员被踢通知"),
+ MEMBER_INVITED(1509, "邀请群成员通知"),
+ MEMBER_ENTER(1510, "群成员进群通知"),
+ GROUP_DISMISSED(1511, "解散群通知"),
+ GROUP_MEMBER_MUTED(1512, "群成员禁言通知"),
+ GROUP_MEMBER_CANCEL_MUTED(1513, "取消群成员禁言通知"),
+ GROUP_MUTED(1514, "群禁言通知"),
+ GROUP_CANCEL_MUTED(1515, "取消群禁言通知"),
+ GROUP_ANNOUNCEMENT_UPDATED(1519, "群公告改变通知"),
+ GROUP_NAME_UPDATED(1520, "群名称改变通知"),
+
+ BURN_CHANGE(1701, "阅后即焚开启或关闭通知"),
+ REVOKE(2101, "撤回消息通知");;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageContentTypeEnum::getType).toArray();
+
+ /**
+ * 类型
+ */
+ private final Integer type;
+
+ /**
+ * 名字
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageSourceEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageSourceEnum.java
new file mode 100644
index 0000000..3b04c97
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageSourceEnum.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.im.enums.message;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * IM 消息的消息来源 100-用户发送;200-系统发送(一般是通知);不能为空
+ */
+@RequiredArgsConstructor
+@Getter
+public enum MessageSourceEnum implements IntArrayValuable {
+
+ USER_SEND(100, "用户发送"),
+ SYSTEM_SEND(200, "系统发送");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageSourceEnum::getStatus).toArray();
+
+ /**
+ * 状态
+ */
+ private final Integer status;
+
+ /**
+ * 名字
+ */
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageStatusEnum.java
index d2ce4e4..389d9fd 100644
--- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/MessageStatusEnum.java
@@ -6,21 +6,27 @@ import lombok.RequiredArgsConstructor;
import java.util.Arrays;
-// TODO @hao:注释哈;
+/**
+ * IM 消息的状态枚举
+ */
@RequiredArgsConstructor
@Getter
-public enum ImMessageStatusEnum implements IntArrayValuable {
+public enum MessageStatusEnum implements IntArrayValuable {
SENDING(1, "发送中"),
- SUCCESS(2, "发送成功"),
- FAILURE(3, "发送失败"),
- DELETED(4, "已删除"),
- RECALL(5, "已撤回");
-
- // TODO @hao:静态变量,和普通变量,最好空一行;
- public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageStatusEnum::getStatus).toArray();
- // TODO @hao:注释哈;
+ SUCCEED(2, "发送成功"),
+ FAILED(3, "发送失败");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageStatusEnum::getStatus).toArray();
+
+ /**
+ * 状态
+ */
private final Integer status;
+
+ /**
+ * 名字
+ */
private final String name;
@Override
diff --git a/yudao-module-im/yudao-module-im-biz/pom.xml b/yudao-module-im/yudao-module-im-biz/pom.xml
index a6d1bff..058c10a 100644
--- a/yudao-module-im/yudao-module-im-biz/pom.xml
+++ b/yudao-module-im/yudao-module-im-biz/pom.xml
@@ -5,19 +5,19 @@
yudao-module-im
cn.iocoder.boot
- ${revision}
+ ${revision}
4.0.0
- jar
+ jar
yudao-module-im-biz
- ${project.artifactId}
-
+ ${project.artifactId}
+
im 模块,主要实现 im 模块的业务逻辑。
-
+
cn.iocoder.boot
yudao-module-im-api
@@ -41,34 +41,34 @@
yudao-spring-boot-starter-security
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-websocket
+
+
cn.iocoder.boot
yudao-spring-boot-starter-mybatis
-
cn.iocoder.boot
- yudao-spring-boot-starter-test
+ yudao-spring-boot-starter-redis
-
-
+
cn.iocoder.boot
yudao-spring-boot-starter-excel
+
+
cn.iocoder.boot
- yudao-spring-boot-starter-websocket
+ yudao-spring-boot-starter-test
-
-
- org.redisson
- redisson-spring-boot-starter
-
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ConversationController.java
index c94140b..6276c15 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationController.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ConversationController.java
@@ -4,8 +4,8 @@ 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.ImConversationRespVO;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
-import cn.iocoder.yudao.module.im.service.conversation.ImConversationService;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
+import cn.iocoder.yudao.module.im.service.conversation.ConversationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
@@ -19,22 +19,22 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
// TODO @hao: 管理后台 - IM 会话
-@Tag(name = "管理后台 - 会话")
+@Tag(name = "管理后台 - IM 会话")
@RestController
@RequestMapping("/im/conversation")
@Validated
-public class ImConversationController {
+public class ConversationController {
// TODO @hao: conversationService 即可
@Resource
- private ImConversationService imConversationService;
+ private ConversationService conversationService;
// TODO @hao:/list 会话列表;一般 get 是给单个对象,或者 get-count 这种;然后 conversation 已经是模块名了,所以可以简化
@GetMapping("/get-conversation")
@Operation(summary = "获得用户的会话列表")
@PreAuthorize("hasAuthority('im:conversation:query')") // TODO @hao:不用权限哈
public CommonResult> getConversationList() {
- List conversationList = imConversationService.getConversationList();
+ List conversationList = conversationService.getConversationList();
return success(BeanUtils.toBean(conversationList, ImConversationRespVO.class));
}
@@ -44,7 +44,7 @@ public class ImConversationController {
@Operation(summary = "置顶会话")
@PreAuthorize("hasAuthority('im:conversation:update')") // TODO @hao:不用权限哈;因为肯定会判断是不是自己的
public CommonResult updateTop(@Valid @RequestBody ImConversationSaveReqVO updateReqVO) {
- imConversationService.updateTop(updateReqVO);
+ conversationService.updateTop(updateReqVO);
return success(true);
}
@@ -54,7 +54,7 @@ public class ImConversationController {
@Operation(summary = "更新最后已读时间")
@PreAuthorize("hasAuthority('im:conversation:update')") // TODO @hao:不用权限哈;因为肯定会判断是不是自己的
public CommonResult updateLastReadTime(@Valid @RequestBody ImConversationSaveReqVO updateReqVO) {
- imConversationService.updateLastReadTime(updateReqVO);
+ conversationService.updateLastReadTime(updateReqVO);
return success(true);
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationPageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationPageReqVO.java
index c3a24b3..e1308d8 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationPageReqVO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationPageReqVO.java
@@ -22,7 +22,7 @@ public class ImConversationPageReqVO extends PageParam {
private Long userId;
@Schema(description = "类型:1 单聊;2 群聊;4 通知会话(预留)", example = "1")
- private Integer conversationType;
+ private Integer type;
@Schema(description = "单聊时,用户编号;群聊时,群编号", example = "21454")
private Long targetId;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationSaveReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationSaveReqVO.java
index 58d7123..b226f16 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationSaveReqVO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationSaveReqVO.java
@@ -21,7 +21,7 @@ public class ImConversationSaveReqVO {
@Schema(description = "类型:1 单聊;2 群聊;4 通知会话(预留)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "类型:1 单聊;2 群聊;4 通知会话(预留)不能为空")
- private Integer conversationType;
+ private Integer type;
@Schema(description = "单聊时,用户编号;群聊时,群编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21454")
@NotEmpty(message = "单聊时,用户编号;群聊时,群编号不能为空")
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
index a1afcc9..abd97bf 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
@@ -25,7 +25,7 @@ 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.ImGroupDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupDO;
import cn.iocoder.yudao.module.im.service.group.ImGroupService;
@Tag(name = "管理后台 - 群")
@@ -66,7 +66,7 @@ public class ImGroupController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('im:group:query')")
public CommonResult getGroup(@RequestParam("id") Long id) {
- ImGroupDO group = imGroupService.getGroup(id);
+ GroupDO group = imGroupService.getGroup(id);
return success(BeanUtils.toBean(group, ImGroupRespVO.class));
}
@@ -74,7 +74,7 @@ public class ImGroupController {
@Operation(summary = "获得群分页")
@PreAuthorize("@ss.hasPermission('im:group:query')")
public CommonResult> getGroupPage(@Valid ImGroupPageReqVO pageReqVO) {
- PageResult pageResult = imGroupService.getGroupPage(pageReqVO);
+ PageResult pageResult = imGroupService.getGroupPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, ImGroupRespVO.class));
}
@@ -85,7 +85,7 @@ public class ImGroupController {
public void exportGroupExcel(@Valid ImGroupPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
- List list = imGroupService.getGroupPage(pageReqVO).getList();
+ List list = imGroupService.getGroupPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "群.xls", "数据", ImGroupRespVO.class,
BeanUtils.toBean(list, ImGroupRespVO.class));
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java
index c715b63..1a70ebb 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java
+++ b/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.groupmember.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/ImInboxController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/ImInboxController.java
index 4912f72..4459d49 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/ImInboxController.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/ImInboxController.java
@@ -8,8 +8,8 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxRespVO;
-import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
+import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.inbox.InboxDO;
import cn.iocoder.yudao.module.im.service.inbox.ImInboxService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -39,14 +39,14 @@ public class ImInboxController {
@PostMapping("/create")
@Operation(summary = "创建收件箱")
@PreAuthorize("@ss.hasPermission('im:inbox:create')")
- public CommonResult createInbox(@Valid @RequestBody ImInboxSaveReqVO createReqVO) {
+ public CommonResult createInbox(@Valid @RequestBody InboxSaveReqVO createReqVO) {
return success(imInboxService.createInbox(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新收件箱")
@PreAuthorize("@ss.hasPermission('im:inbox:update')")
- public CommonResult updateInbox(@Valid @RequestBody ImInboxSaveReqVO updateReqVO) {
+ public CommonResult updateInbox(@Valid @RequestBody InboxSaveReqVO updateReqVO) {
imInboxService.updateInbox(updateReqVO);
return success(true);
}
@@ -65,7 +65,7 @@ public class ImInboxController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('im:inbox:query')")
public CommonResult getInbox(@RequestParam("id") Long id) {
- ImInboxDO inbox = imInboxService.getInbox(id);
+ InboxDO inbox = imInboxService.getInbox(id);
return success(BeanUtils.toBean(inbox, ImInboxRespVO.class));
}
@@ -73,7 +73,7 @@ public class ImInboxController {
@Operation(summary = "获得收件箱分页")
@PreAuthorize("@ss.hasPermission('im:inbox:query')")
public CommonResult> getInboxPage(@Valid ImInboxPageReqVO pageReqVO) {
- PageResult pageResult = imInboxService.getInboxPage(pageReqVO);
+ PageResult pageResult = imInboxService.getInboxPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, ImInboxRespVO.class));
}
@@ -84,7 +84,7 @@ public class ImInboxController {
public void exportInboxExcel(@Valid ImInboxPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
- List list = imInboxService.getInboxPage(pageReqVO).getList();
+ List list = imInboxService.getInboxPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "收件箱.xls", "数据", ImInboxRespVO.class,
BeanUtils.toBean(list, ImInboxRespVO.class));
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveMessageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveMessageReqVO.java
new file mode 100644
index 0000000..f48a002
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveMessageReqVO.java
@@ -0,0 +1,42 @@
+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;
+
+@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;
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/ImInboxSaveReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveReqVO.java
index 678be51..b44a2b7 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/ImInboxSaveReqVO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSaveReqVO.java
@@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class ImInboxSaveReqVO {
+public class InboxSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18389")
private Long id;
@@ -28,7 +28,7 @@ public class ImInboxSaveReqVO {
@NotNull(message = "序号,按照 user 递增不能为空")
private Long sequence;
- public ImInboxSaveReqVO(Long userId, Long messageId, Long sequence) {
+ public InboxSaveReqVO(Long userId, Long messageId, Long sequence) {
this.userId = userId;
this.messageId = messageId;
this.sequence = sequence;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSendMessageReqVO.java
index 23a1ad6..ae58c5e 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/inbox/vo/InboxSendMessageReqVO.java
@@ -1,13 +1,13 @@
-package cn.iocoder.yudao.module.im.websocket.message;
+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;
-@Schema(description = "管理后台 - 消息发送 receive")
+@Schema(description = "管理后台 - 收件箱保存消息 Request VO")
@Data
-public class ImReceiveMessage {
+public class InboxSendMessageReqVO {
@Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer conversationType; // 对应 ImConversationTypeEnum 枚举
@@ -15,7 +15,14 @@ public class ImReceiveMessage {
@Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long fromId; // 根据 conversationType 区分
- // TODO @hao:昵称和头像,也直接发给接收人好了;
+ @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;
@@ -29,10 +36,6 @@ public class ImReceiveMessage {
@Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime sendTime;
- // TODO @hao:inboxId 不需要哈;
- @Schema(description = "收件箱编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18389")
- private Long inboxId;
-
@Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long sequence;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImMessageController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImMessageController.java
deleted file mode 100755
index 91026f8..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImMessageController.java
+++ /dev/null
@@ -1,68 +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.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageRespVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import cn.iocoder.yudao.module.im.service.message.ImMessageService;
-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.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-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 ImMessageService imMessageService;
-
- @GetMapping("/get-message-by-sequence") // TODO @hao:list-by-sequence
- @Operation(summary = "拉取消息-增量拉取大于 seq 的消息") // TODO @hao:可以改成 拉取大于 sequence 的消息列表
- @Parameter(name = "sequence", description = "序号", required = true, example = "1")
- @Parameter(name = "size", description = "条数", required = true, example = "10")
- @PreAuthorize("@ss.hasPermission('im:message:query')") // TODO @hao:权限可以删除哈;
- public CommonResult> loadMessage(@RequestParam("sequence") Long sequence,
- @RequestParam("size") Integer size) {
- // TODO @hao:方法名,可以改成 getMessageListBySequence
- // TODO @hao:如果是返回列表,变量要用 messages, 或者 messageList,体现出是复数
- List message = imMessageService.loadMessage(getLoginUserId(), sequence, size);
- return success(BeanUtils.toBean(message, ImMessageRespVO.class));
- }
-
- // TODO @hao:这个接口的使用场景是哪个哈?
- @GetMapping("/get-all-message")
- @Operation(summary = "拉取全部消息")
- @Parameter(name = "size", description = "条数", required = true, example = "10")
- @PreAuthorize("@ss.hasPermission('im:message:query')")
- public CommonResult> loadAllMessage(@RequestParam("size") Integer size) {
- List message = imMessageService.loadAllMessage(getLoginUserId(), size);
- return success(BeanUtils.toBean(message, ImMessageRespVO.class));
- }
-
- // TODO @hao:是不是分页参数不太对哈?应该只有 conversationNo,sendTime 字段;然后,做链式分页的查询,不太适合传统的 pageSize + number 查询;
- @GetMapping("/page")
- @Operation(summary = "查询聊天记录-分页")
- @PreAuthorize("@ss.hasPermission('im:message:query')") // TODO @hao:权限可以删除哈;
- public CommonResult> getMessagePage(@Valid ImMessagePageReqVO pageReqVO) {
- PageResult messagePage = imMessageService.getMessagePage(pageReqVO);
- return success(BeanUtils.toBean(messagePage, ImMessageRespVO.class));
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/MessageController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/MessageController.java
new file mode 100755
index 0000000..fc5d33a
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/MessageController.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.MessagePageReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageReqVO;
+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 sendMessage(@Valid @RequestBody SendMessageReqVO message) {
+ return success(messageService.sendMessage(getLoginUserId(), message));
+ }
+
+ @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> loadMessage(@RequestParam("sequence") Long sequence,
+ @RequestParam("size") Integer size) {
+ List messages = messageService.getMessageListBySequence(getLoginUserId(), sequence, size);
+ return success(BeanUtils.toBean(messages, ImMessageReqVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "查询聊天记录-分页")
+ public CommonResult> getMessagePage(@Valid MessagePageReqVO pageReqVO) {
+ //根据会话标志和发送时间进行分页查询
+ List messagePage = messageService.getMessagePage(pageReqVO);
+ return success(BeanUtils.toBean(messagePage, ImMessageReqVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessagePageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessagePageReqVO.java
deleted file mode 100755
index ed8c2db..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessagePageReqVO.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package cn.iocoder.yudao.module.im.controller.admin.message.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import com.alibaba.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-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_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - 消息分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ImMessagePageReqVO extends PageParam {
-
- @Schema(description = "客户端消息编号 uuid,用于排重", example = "3331")
- private String clientMessageId;
-
- @Schema(description = "发送人编号", example = "23239")
- private Long senderId;
-
- @Schema(description = "接收人编号", example = "32494")
- private Long receiverId;
-
- @Schema(description = "发送人昵称", example = "李四")
- private String senderNickname;
-
- @Schema(description = "发送人头像")
- private String senderAvatar;
-
- @Schema(description = "会话类型", example = "2")
- private Integer conversationType;
-
- @Schema(description = "会话标志")
- private String conversationNo;
-
- @Schema(description = "消息类型", example = "1")
- private Integer contentType;
-
- @Schema(description = "消息内容")
- private String content;
-
- @Schema(description = "发送时间")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private LocalDateTime[] sendTime;
-
- @Schema(description = "消息来源 100-用户发送;200-系统发送(一般是通知);")
- private Integer sendFrom;
-
- @Schema(description = "创建时间")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private LocalDateTime[] createTime;
-
- @Schema(description = "消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回", requiredMode = Schema.RequiredMode.REQUIRED)
- private Integer messageStatus;
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageRespVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageReqVO.java
index 19e3886..0f0d4f2 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageRespVO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageReqVO.java
@@ -1,77 +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.ImMessageStatusEnum;
-import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
+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 jakarta.validation.constraints.NotNull;
import lombok.Data;
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - 消息 Response VO")
+@Schema(description = "管理后台 - 消息 Request VO")
@Data
@ExcelIgnoreUnannotated
-public class ImMessageRespVO {
-
- @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30713")
- @ExcelProperty("编号")
- private Long id;
+public class ImMessageReqVO {
@Schema(description = "客户端消息编号 uuid,用于排重", requiredMode = Schema.RequiredMode.REQUIRED, example = "3331")
@ExcelProperty("客户端消息编号 uuid,用于排重")
private String clientMessageId;
- @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23239")
- @ExcelProperty("发送人编号")
- private Long senderId;
-
@Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
@ExcelProperty("接收人编号")
private Long receiverId;
- @Schema(description = "发送人昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
- @ExcelProperty("发送人昵称")
- private String senderNickname;
-
- @Schema(description = "发送人头像", requiredMode = Schema.RequiredMode.REQUIRED)
- @ExcelProperty("发送人头像")
- private String senderAvatar;
-
@Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@ExcelProperty("会话类型")
private Integer conversationType;
- @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED)
- @ExcelProperty("会话标志")
- private String conversationNo;
-
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("消息类型")
- @InEnum(ImMessageTypeEnum.class)
+ @InEnum(MessageContentTypeEnum.class)
private Integer contentType;
@Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("消息内容")
private String content;
- @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
- @ExcelProperty("发送时间")
- private LocalDateTime sendTime;
-
- @Schema(description = "消息来源 100-用户发送;200-系统发送(一般是通知);", requiredMode = Schema.RequiredMode.REQUIRED)
- @ExcelProperty("消息来源 100-用户发送;200-系统发送(一般是通知);")
- private Integer sendFrom;
-
- @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
- @ExcelProperty("创建时间")
- private LocalDateTime createTime;
-
- @Schema(description = "消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回", requiredMode = Schema.RequiredMode.REQUIRED)
- @ExcelProperty("消息状态")
- @InEnum(ImMessageStatusEnum.class)
- private Integer messageStatus;
-
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessagePageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessagePageReqVO.java
new file mode 100755
index 0000000..01e7b70
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/MessagePageReqVO.java
@@ -0,0 +1,25 @@
+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;
+
+@Schema(description = "管理后台 - 消息分页 Request VO")
+@Data
+@ToString(callSuper = true)
+public class MessagePageReqVO {
+
+ @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "g_1000")
+ private String conversationNo;
+
+ @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-27")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] sendTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageReqVO.java
new file mode 100755
index 0000000..dd97a9c
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageReqVO.java
@@ -0,0 +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 io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 发送消息 Request VO")
+@Data
+@ExcelIgnoreUnannotated
+public class SendMessageReqVO {
+
+ @Schema(description = "客户端消息编号 uuid,用于排重", requiredMode = Schema.RequiredMode.REQUIRED, example = "3331")
+ @ExcelProperty("客户端消息编号 uuid,用于排重")
+ private String clientMessageId;
+
+ @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494")
+ @ExcelProperty("接收人编号")
+ private Long receiverId;
+
+ @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+ @ExcelProperty("会话类型")
+ private Integer conversationType;
+
+ @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("消息类型")
+ @InEnum(MessageContentTypeEnum.class)
+ private Integer contentType;
+
+ @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("消息内容")
+ private String content;
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageRespVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageRespVO.java
new file mode 100755
index 0000000..79ac757
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/SendMessageRespVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.im.controller.admin.message.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+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;
+
+@Schema(description = "管理后台 - 发送消息 Response VO")
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SendMessageRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
+ private Long id;
+
+ @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-27 12:00:00")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime sendTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ImConversationDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ConversationDO.java
index 5a6fabd..0f8f22e 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ImConversationDO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/conversation/ConversationDO.java
@@ -1,6 +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 com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -21,31 +22,28 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class ImConversationDO extends BaseDO {
+public class ConversationDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
+
/**
* 所属用户
*/
private Long userId;
- // TODO @hao:注释可以改成,如下
+
/**
* 会话类型
- *
- * 枚举 {@link cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum}
- */
- /**
- * 类型:1 单聊;2 群聊;4 通知会话(预留)
+ *
+ * 枚举 {@link ConversationTypeEnum}
*/
- // TODO @hao:conversationType 改成 type
- private Integer conversationType;
+ private Integer type;
/**
* 聊天对象编号
- *
+ *
* 1. 单聊时,用户编号;群聊时,群编号
*/
private Long targetId;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupDO.java
index edd2b33..ce6b1a6 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupDO.java
@@ -1,8 +1,10 @@
package cn.iocoder.yudao.module.im.dal.dataobject.group;
-import lombok.*;
-import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
/**
* IM 群信息 DO
@@ -17,7 +19,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class ImGroupDO extends BaseDO {
+public class GroupDO extends BaseDO {
/**
* 编号
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/groupmember/GroupMemberDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupMemberDO.java
index dc97b94..0ccffee 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/groupmember/GroupMemberDO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/GroupMemberDO.java
@@ -1,13 +1,9 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.groupmember;
+package cn.iocoder.yudao.module.im.dal.dataobject.group;
import lombok.*;
-import java.util.*;
-import java.time.LocalDateTime;
-import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-// TODO @hao:这个挪到 group 包下;
/**
* IM 群成员 DO
*
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/ImInboxDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/InboxDO.java
index 6f92474..62accc3 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/ImInboxDO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/inbox/InboxDO.java
@@ -20,7 +20,7 @@ import lombok.*;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class ImInboxDO extends BaseDO {
+public class InboxDO extends BaseDO {
/**
* 编号
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImMessageDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/MessageDO.java
index 2b1646c..7f89a93 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImMessageDO.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/MessageDO.java
@@ -1,6 +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 com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -21,7 +25,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class ImMessageDO extends BaseDO {
+public class MessageDO extends BaseDO {
/**
* 编号
@@ -32,57 +36,54 @@ public class ImMessageDO extends BaseDO {
* 客户端消息编号 uuid,用于排重
*/
private String clientMessageId;
- // TODO @hao:senderId、receiverId 存储的具体值写下,对应的群之类的
/**
- * 发送人编号
+ * 发送人编号 存储的是用户编号
*/
private Long senderId;
/**
* 接收人编号
+ *
+ * 1. 单聊时,用户编号;群聊时,群编号
*/
private Long receiverId;
- // TODO @hao:冗余字段,要说明下的。例如说
/**
- * 发送人昵称
- *
+ * 消息发送者昵称
+ *
* 冗余 AdminUserDO 的 nickname 字段
*/
private String senderNickname;
/**
- * 发送人头像
+ * 消息发送者头像
+ *
+ * 冗余 AdminUserDO 的 avatar 字段
*/
private String senderAvatar;
- // TODO @hao:关联枚举
/**
- * 会话类型
+ * 会话类型 枚举 {@link ConversationTypeEnum}
*/
private Integer conversationType;
- // TODO @hao:关联字段
/**
- * 会话标志
+ * 会话标志 {@link ConversationTypeEnum} 的generateConversationNo() 方法生成
*/
private String conversationNo;
/**
- * 消息类型
+ * 消息类型 枚举 {@link MessageContentTypeEnum}
*/
private Integer contentType;
- // TODO @hao:说明下是 json 格式,在哪个包看具体的格式
/**
- * 消息内容
+ * 消息内容 JSON 格式 对应 dal/dataobject/message/content 包
*/
private String content;
/**
* 发送时间
*/
private LocalDateTime sendTime;
- // TODO @hao:搞个枚举,然后代码里注释说明下
/**
- * 消息来源 100-用户发送;200-系统发送(一般是通知);
+ * 消息来源 枚举 {@link MessageSourceEnum}
*/
private Integer sendFrom;
- // TODO @hao:搞个枚举,然后代码里注释说明下
/**
- * 消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回
+ * 消息状态 枚举 {@link MessageStatusEnum}
*/
private Integer messageStatus;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImAudioMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImAudioMessageBody.java
deleted file mode 100644
index acc8d84..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImAudioMessageBody.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 语音消息的 {@link ImMessageBody}
- *
- * @author 芋道源码
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class ImAudioMessageBody implements ImMessageBody {
-
- /**
- * 语音 URL
- */
- private String url;
- /**
- * 语音格式,例如说 arm、mp3、speex 等
- */
- private String format;
-
- // TODO 芋艿:要不要以下字段?待定;云信有、企业微信没有
-//"dur":4551, //语音持续时长ms
-// "md5":"87b94a090dec5c58f242b7132a530a01", //语音文件的md5值,按照字节流加密
-// "size":16420 //语音文件大小,单位为字节(Byte)
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImMessageBody.java
deleted file mode 100644
index e5eddc0..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImMessageBody.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
-
-
-import cn.iocoder.yudao.module.im.jackson.ImMessageBodyDeserializer;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-
-/**
- * IM 消息的 body 内容
- */
-@JsonDeserialize(using = ImMessageBodyDeserializer.class)
-public interface ImMessageBody {
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java
new file mode 100644
index 0000000..41420ac
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/AudioMessage.java
@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 语音消息的 {@link MessageDO 字段 content} 的内容
+ *
+ * @author 芋道源码
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AudioMessage {
+
+ /**
+ * 语音文件唯一 ID
+ */
+ private String uuid;
+
+ /**
+ * 语音文件的本地路径
+ */
+ private String soundPath;
+
+ /**
+ * 语音文件下载地址
+ */
+ private String sourceUrl;
+
+ /**
+ * 语音文件大小
+ */
+ private int dataSize;
+
+ /**
+ * 语音时长
+ */
+ private int duration;
+
+ /**
+ * 语音文件类型
+ */
+ private String soundType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java
new file mode 100644
index 0000000..3eff9bf
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/CardMessage.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 名片消息的 {@link MessageDO 字段 content} 的内容
+ *
+ * @author anhaohao
+ * @since 2024/3/23 下午5:53
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CardMessage {
+
+ /**
+ * 用户 ID
+ */
+ private String userID;
+
+ /**
+ * 用户名
+ */
+ private String nickname;
+
+ /**
+ * 用户头像
+ */
+ private int faceURL;
+
+ /**
+ * 扩展字段
+ */
+ private String ex;
+}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImFileMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
index 2ed2384..2dd2b6b 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImFileMessageBody.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
@@ -1,18 +1,19 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * 文件消息的 {@link ImMessageBody}
+ * 文件消息的 {@link MessageDO 字段 content} 的内容
*
* @author 芋道源码
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class ImFileMessageBody implements ImMessageBody {
+public class FileMessage {
/**
* 文件名
@@ -23,9 +24,4 @@ public class ImFileMessageBody implements ImMessageBody {
*/
private String url;
- // TODO 芋艿:要不要以下字段?待定;云信有、企业微信没有
-// "md5":"79d62a35fa3d34c367b20c66afc2a500", //文件MD5,按照字节流加密
-// "ext":"ttf", //文件后缀类型
-// "size":91680 //大小,单位为字节(Byte)
-
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImImageMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
index 1a81c28..cfdfcb1 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImImageMessageBody.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
@@ -1,30 +1,23 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * 图片消息的 {@link ImMessageBody}
+ * 图片消息的 {@link MessageDO 字段 content} 的内容
*
* @author 芋道源码
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class ImImageMessageBody implements ImMessageBody {
+public class ImageMessage {
/**
* 图片地址
*/
private String url;
- // TODO 芋艿:要不要以下字段?待定;云信有、企业微信没有
-// "name":"图片发送于2015-05-07 13:59", //图片name
-// "md5":"9894907e4ad9de4678091277509361f7", //图片文件md5,按照字节流加密
-// "ext":"jpg", //图片后缀
-// "w":6814, //宽,单位为像素
-// "h":2332, //高,单位为像素
-// "size":388245 //图片文件大小,单位为字节(Byte)
-
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImLocationMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
index 3e9db26..a95c2d8 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImLocationMessageBody.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
@@ -1,22 +1,23 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * 地址位置消息的 {@link ImMessageBody}
+ * 地址位置消息的 {@link MessageDO 字段 content} 的内容
*
* @author 芋道源码
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class ImLocationMessageBody implements ImMessageBody {
+public class LocationMessage {
/**
* 地理位置
- *
+ *
* 例如说:中国 浙江省 杭州市 网商路 599号
*/
private String address;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImTextMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
index 9e6f973..b7f13a4 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImTextMessageBody.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
@@ -1,21 +1,22 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
- * 文本消息的 {@link ImMessageBody}
+ * 文本消息的 {@link MessageDO 字段 content} 的内容
*
* @author 芋道源码
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class ImTextMessageBody implements ImMessageBody {
+public class TextMessage {
/**
- * 文本消息内容
+ * 文本消息的具体内容
*/
private String content;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImVideoMessageBody.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
index 5d64347..e757e50 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/body/ImVideoMessageBody.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
@@ -1,27 +1,19 @@
-package cn.iocoder.yudao.module.im.dal.dataobject.message.body;
+package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
+import cn.iocoder.yudao.module.im.dal.dataobject.message.MessageDO;
import lombok.Data;
/**
- * 视频消息的 {@link ImMessageBody}
+ * 视频消息的 {@link MessageDO 字段 content} 的内容
*
* @author 芋道源码
*/
@Data
-public class ImVideoMessageBody implements ImMessageBody {
+public class VideoMessage {
/**
* 视频地址
*/
private String url;
- // TODO 芋艿:要不要以下字段?待定;云信有、企业微信没有
-// "dur":8003, //视频持续时长ms
-// "md5":"da2cef3e5663ee9c3547ef5d127f7e3e", //视频文件的md5值,按照字节流加密
-// "w":360, //宽,单位为像素
-// "h":480, //高,单位为像素
-// "size":16420 //视频文件大小,单位为字节(Byte)】
-// "ext":"mp4", //视频格式
-
-
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java
index d4bfb0c..73ade2e 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationMapper.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java
@@ -4,33 +4,31 @@ 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.conversation.vo.ImConversationPageReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
import org.apache.ibatis.annotations.Mapper;
-import java.util.Optional;
-
/**
* IM 会话 Mapper
*
* @author 芋道源码
*/
@Mapper
-public interface ImConversationMapper extends BaseMapperX {
+public interface ConversationMapper extends BaseMapperX {
- default PageResult selectPage(ImConversationPageReqVO reqVO) {
- return selectPage(reqVO, new LambdaQueryWrapperX()
- .eqIfPresent(ImConversationDO::getUserId, reqVO.getUserId())
- .eqIfPresent(ImConversationDO::getConversationType, reqVO.getConversationType())
- .eqIfPresent(ImConversationDO::getTargetId, reqVO.getTargetId())
- .eqIfPresent(ImConversationDO::getNo, reqVO.getNo())
- .eqIfPresent(ImConversationDO::getPinned, reqVO.getPinned())
- .betweenIfPresent(ImConversationDO::getLastReadTime, reqVO.getLastReadTime())
- .betweenIfPresent(ImConversationDO::getCreateTime, reqVO.getCreateTime())
- .orderByDesc(ImConversationDO::getId));
+ default PageResult selectPage(ImConversationPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(ConversationDO::getUserId, reqVO.getUserId())
+ .eqIfPresent(ConversationDO::getType, reqVO.getType())
+ .eqIfPresent(ConversationDO::getTargetId, reqVO.getTargetId())
+ .eqIfPresent(ConversationDO::getNo, reqVO.getNo())
+ .eqIfPresent(ConversationDO::getPinned, reqVO.getPinned())
+ .betweenIfPresent(ConversationDO::getLastReadTime, reqVO.getLastReadTime())
+ .betweenIfPresent(ConversationDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(ConversationDO::getId));
}
// TODO @hao:1)no) {,要有空格哈;2)可以直接 selectOne(ImConversationDO::getNo, no) 父类做了封装
- default ImConversationDO selectByNo(String no){
- return selectOne(new LambdaQueryWrapperX().eq(ImConversationDO::getNo, no));
+ default ConversationDO selectByNo(String no){
+ return selectOne(new LambdaQueryWrapperX().eq(ConversationDO::getNo, no));
}
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java
index ac301ee..6049550 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java
@@ -3,7 +3,7 @@ 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 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.*;
@@ -13,18 +13,18 @@ import cn.iocoder.yudao.module.im.controller.admin.group.vo.*;
* @author 芋道源码
*/
@Mapper
-public interface ImGroupMapper extends BaseMapperX {
+public interface ImGroupMapper extends BaseMapperX {
- default PageResult selectPage(ImGroupPageReqVO reqVO) {
- return selectPage(reqVO, new LambdaQueryWrapperX()
- .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));
+ default PageResult selectPage(ImGroupPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .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));
}
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java
index d42d1f9..505459a 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java
@@ -4,7 +4,7 @@ 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.groupmember.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java
index aae03ba..15c427e 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java
@@ -4,7 +4,7 @@ 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.inbox.vo.ImInboxPageReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.inbox.InboxDO;
import org.apache.ibatis.annotations.Mapper;
/**
@@ -13,15 +13,15 @@ import org.apache.ibatis.annotations.Mapper;
* @author 芋道源码
*/
@Mapper
-public interface ImInboxMapper extends BaseMapperX {
+public interface ImInboxMapper extends BaseMapperX {
- default PageResult selectPage(ImInboxPageReqVO reqVO) {
- return selectPage(reqVO, new LambdaQueryWrapperX()
- .eqIfPresent(ImInboxDO::getUserId, reqVO.getUserId())
- .eqIfPresent(ImInboxDO::getMessageId, reqVO.getMessageId())
- .eqIfPresent(ImInboxDO::getSequence, reqVO.getSequence())
- .betweenIfPresent(ImInboxDO::getCreateTime, reqVO.getCreateTime())
- .orderByDesc(ImInboxDO::getId));
+ default PageResult selectPage(ImInboxPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(InboxDO::getUserId, reqVO.getUserId())
+ .eqIfPresent(InboxDO::getMessageId, reqVO.getMessageId())
+ .eqIfPresent(InboxDO::getSequence, reqVO.getSequence())
+ .betweenIfPresent(InboxDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(InboxDO::getId));
}
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImMessageMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImMessageMapper.java
deleted file mode 100755
index 54d53b9..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImMessageMapper.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package cn.iocoder.yudao.module.im.dal.mysql.message;
-
-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.message.vo.ImMessagePageReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import com.github.yulichang.wrapper.MPJLambdaWrapper;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-
-/**
- * 消息 Mapper
- *
- * @author 芋道源码
- */
-@Mapper
-public interface ImMessageMapper extends BaseMapperX {
-
- default PageResult selectPage(ImMessagePageReqVO reqVO) {
- return selectPage(reqVO, new LambdaQueryWrapperX()
- .eqIfPresent(ImMessageDO::getClientMessageId, reqVO.getClientMessageId())
- .eqIfPresent(ImMessageDO::getSenderId, reqVO.getSenderId())
- .eqIfPresent(ImMessageDO::getReceiverId, reqVO.getReceiverId())
- .likeIfPresent(ImMessageDO::getSenderNickname, reqVO.getSenderNickname())
- .eqIfPresent(ImMessageDO::getSenderAvatar, reqVO.getSenderAvatar())
- .eqIfPresent(ImMessageDO::getConversationType, reqVO.getConversationType())
- .eqIfPresent(ImMessageDO::getConversationNo, reqVO.getConversationNo())
- .eqIfPresent(ImMessageDO::getContentType, reqVO.getContentType())
- .eqIfPresent(ImMessageDO::getContent, reqVO.getContent())
- .betweenIfPresent(ImMessageDO::getSendTime, reqVO.getSendTime())
- .eqIfPresent(ImMessageDO::getSendFrom, reqVO.getSendFrom())
- .betweenIfPresent(ImMessageDO::getCreateTime, reqVO.getCreateTime())
- .orderByDesc(ImMessageDO::getId));
- }
-
- // TODO @hao:不链表哈;先从 ImInboxDO 查询出 messageId,然后再到 ImMessageDO 里 IN
- default List getGreaterThanSequenceMessage(Long userId, Long sequence, Integer size) {
- //查询 inbox 表中,大于 sequence 的消息,关联 message 表,按照 inbox 表 sequence 升序
- return selectJoinList(ImMessageDO.class, new MPJLambdaWrapper()
- .selectAll(ImMessageDO.class)
- .innerJoin(ImInboxDO.class, ImInboxDO::getMessageId, ImMessageDO::getId)
- .eq(ImInboxDO::getUserId, userId)
- .gt(ImInboxDO::getSequence, sequence)
- .orderByAsc(ImInboxDO::getSequence)
- .last("limit 0," + size));
- }
-
- // TODO @hao:在 dao 里,使用 selectListByUserId,查询用 select,条件用 by,这个算是 spring data 的 method dsl
- default List getAllMessage(Long userId, Integer size) {
- //查询 inbox 表中,100条消息,关联 message 表,按照 inbox 表 sequence 降序
- return selectJoinList(ImMessageDO.class, new MPJLambdaWrapper()
- .selectAll(ImMessageDO.class)
- .innerJoin(ImInboxDO.class, ImInboxDO::getMessageId, ImMessageDO::getId)
- .eq(ImInboxDO::getUserId, userId)
- .orderByDesc(ImInboxDO::getSequence)
- .last("limit 0," + size));
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/MessageMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/MessageMapper.java
new file mode 100755
index 0000000..90fa620
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/MessageMapper.java
@@ -0,0 +1,51 @@
+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 org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 消息 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface MessageMapper extends BaseMapperX {
+
+ // TODO @hao:不链表哈;先从 ImInboxDO 查询出 messageId,然后再到 ImMessageDO 里 IN
+ default List getGreaterThanSequenceMessage(Long userId, Long sequence, Integer size) {
+ //查询 inbox 表中,大于 sequence 的消息,关联 message 表,按照 inbox 表 sequence 升序
+ return selectJoinList(MessageDO.class, new MPJLambdaWrapper()
+ .selectAll(MessageDO.class)
+ .innerJoin(InboxDO.class, InboxDO::getMessageId, MessageDO::getId)
+ .eq(InboxDO::getUserId, userId)
+ .gt(InboxDO::getSequence, sequence)
+ .orderByAsc(InboxDO::getSequence)
+ .last("limit 0," + size));
+ }
+
+ // TODO @hao:在 dao 里,使用 selectListByUserId,查询用 select,条件用 by,这个算是 spring data 的 method dsl
+ default List getAllMessage(Long userId, Integer size) {
+ //查询 inbox 表中,100条消息,关联 message 表,按照 inbox 表 sequence 降序
+ return selectJoinList(MessageDO.class, new MPJLambdaWrapper()
+ .selectAll(MessageDO.class)
+ .innerJoin(InboxDO.class, InboxDO::getMessageId, MessageDO::getId)
+ .eq(InboxDO::getUserId, userId)
+ .orderByDesc(InboxDO::getSequence)
+ .last("limit 0," + size));
+ }
+
+ default List getMessagePage(MessagePageReqVO pageReqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .eqIfPresent(MessageDO::getConversationNo, pageReqVO.getConversationNo())
+ .betweenIfPresent(MessageDO::getSendTime, pageReqVO.getSendTime())
+ .orderByAsc(MessageDO::getSendTime));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/RedisKeyConstants.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/RedisKeyConstants.java
index 906c892..76dba12 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/RedisKeyConstants.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/RedisKeyConstants.java
@@ -14,4 +14,11 @@ public interface RedisKeyConstants {
* VALUE 数据类型: String
*/
String INBOX_SEQUENCE = "im_inbox_sequence:%s";
+
+ /**
+ * 收件箱的分布式锁
+ * KEY 格式: im:inbox:lock:{userId}
+ * VALUE 数据类型: String
+ */
+ String INBOX_LOCK = "im_inbox_lock:%s";
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/InboxLockRedisDAO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/InboxLockRedisDAO.java
new file mode 100644
index 0000000..a247d09
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/InboxLockRedisDAO.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.im.dal.redis.inbox;
+
+import jakarta.annotation.Resource;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.stereotype.Repository;
+
+import java.util.concurrent.TimeUnit;
+
+import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.INBOX_LOCK;
+
+/**
+ * 收件箱的锁 Redis DAO
+ *
+ * @author 芋道源码
+ */
+@Repository
+public class InboxLockRedisDAO {
+
+ @Resource
+ private RedissonClient redissonClient;
+
+ private static String formatKey(Long id) {
+ return String.format(INBOX_LOCK, id);
+ }
+
+ public void lock(Long id, Long timeoutMillis, Runnable runnable) {
+ String lockKey = formatKey(id);
+ RLock lock = redissonClient.getLock(lockKey);
+ try {
+ lock.lock(timeoutMillis, TimeUnit.MILLISECONDS);
+ // 执行逻辑
+ runnable.run();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceGeneratorRedisDao.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceRedisDao.java
index d1ceec7..ddbab25 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceGeneratorRedisDao.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/redis/inbox/SequenceRedisDao.java
@@ -1,19 +1,21 @@
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;
import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.INBOX_SEQUENCE;
// TODO @芋艿:这个名字,需要在考虑下;
+
/**
* 序号生成器 Redis DAO
*
* @author anhaohao
*/
@Repository
-public class SequenceGeneratorRedisDao {
+public class SequenceRedisDao {
@Resource
private RedisTemplate redisTemplate;
@@ -22,6 +24,12 @@ public class SequenceGeneratorRedisDao {
return String.format(INBOX_SEQUENCE, userId);
}
+ /**
+ * 生成序号
+ *
+ * @param userId 用户编号
+ * @return 序号
+ */
public Long generateSequence(Long userId) {
return redisTemplate.opsForValue().increment(formatKey(userId), 1);
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/jackson/ImMessageBodyDeserializer.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/jackson/ImMessageBodyDeserializer.java
deleted file mode 100644
index 2f7c4f8..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/jackson/ImMessageBodyDeserializer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package cn.iocoder.yudao.module.im.jackson;
-
-import cn.iocoder.yudao.module.im.dal.dataobject.message.body.*;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonNode;
-
-import java.io.IOException;
-
-// TODO @hao:可以讨论下:是不是前端传递 type + content,后端根据 type 判断后,直接 jsonutil 解析到对应的 body 就 ok 了
-public class ImMessageBodyDeserializer extends JsonDeserializer {
-
- @Override
- public ImMessageBody deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
- JsonNode node = p.getCodec().readTree(p);
- // 根据 node 中的内容来判断应该实例化哪个子类
- if (node.has("content")) {
- return new ImTextMessageBody(node.get("content").asText());
- }
- if (node.has("url")) {
- String url = node.get("url").asText();
- if (node.has("format")) {
- return new ImAudioMessageBody(url, node.get("format").asText());
- }
- return new ImImageMessageBody(url);
- }
- if (node.has("name")) {
- return new ImFileMessageBody(node.get("name").asText(), node.get("url").asText());
- }
- if (node.has("address")) {
- return new ImLocationMessageBody(node.get("address").asText(), node.get("longitude").asDouble(), node.get("latitude").asDouble());
- }
- // 如果没有匹配的属性,抛出异常
- throw ctxt.mappingException("Cannot deserialize to an instance of ImMessageBody");
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationService.java
index d235a7e..0fa3a47 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationService.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationService.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.im.service.conversation;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
import jakarta.validation.Valid;
import java.util.List;
@@ -13,7 +13,7 @@ import java.util.List;
*
* @author 芋道源码
*/
-public interface ImConversationService {
+public interface ConversationService {
/**
* 创建会话
@@ -43,7 +43,7 @@ public interface ImConversationService {
* @param id 编号
* @return 会话
*/
- ImConversationDO getConversation(Long id);
+ ConversationDO getConversation(Long id);
/**
* 获得会话分页
@@ -51,7 +51,7 @@ public interface ImConversationService {
* @param pageReqVO 分页查询
* @return 会话分页
*/
- PageResult getConversationPage(ImConversationPageReqVO pageReqVO);
+ PageResult getConversationPage(ImConversationPageReqVO pageReqVO);
/**
@@ -59,7 +59,7 @@ public interface ImConversationService {
*
* @return 会话列表
*/
- List getConversationList();
+ List getConversationList();
/**
* 置顶会话
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationServiceImpl.java
index a14a31b..7b1bd9a 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ConversationServiceImpl.java
@@ -5,8 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO;
import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO;
-import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper;
+import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ConversationDO;
+import cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -24,17 +24,17 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_N
*/
@Service
@Validated
-public class ImConversationServiceImpl implements ImConversationService {
+public class ConversationServiceImpl implements ConversationService {
// TODO @hao: 自己模块的注入,不用带 im 前缀哈;
@Resource
- private ImConversationMapper imConversationMapper;
+ private ConversationMapper conversationMapper;
// TODO @hao: 这个方法,是不是不需要哈
@Override
public Long createConversation(ImConversationSaveReqVO createReqVO) {
- ImConversationDO conversation = BeanUtils.toBean(createReqVO, ImConversationDO.class);
- imConversationMapper.insert(conversation);
+ ConversationDO conversation = BeanUtils.toBean(createReqVO, ConversationDO.class);
+ conversationMapper.insert(conversation);
return conversation.getId();
}
@@ -44,8 +44,8 @@ public class ImConversationServiceImpl implements ImConversationService {
// 校验存在
validateConversationExists(updateReqVO.getId());
// 更新
- ImConversationDO updateObj = BeanUtils.toBean(updateReqVO, ImConversationDO.class);
- imConversationMapper.updateById(updateObj);
+ ConversationDO updateObj = BeanUtils.toBean(updateReqVO, ConversationDO.class);
+ conversationMapper.updateById(updateObj);
}
// TODO @hao: 考虑到可能和端上不同步,可以不校验是不是存储。另外,不基于 id 删除。要基于 no + userId 删除哈。说白了,对端上要屏蔽 id 字段
@@ -54,28 +54,28 @@ public class ImConversationServiceImpl implements ImConversationService {
// 校验存在
validateConversationExists(id);
// 删除
- imConversationMapper.deleteById(id);
+ conversationMapper.deleteById(id);
}
private void validateConversationExists(Long id) {
- if (imConversationMapper.selectById(id) == null) {
+ if (conversationMapper.selectById(id) == null) {
throw exception(CONVERSATION_NOT_EXISTS);
}
}
@Override
- public ImConversationDO getConversation(Long id) {
- return imConversationMapper.selectById(id);
+ public ConversationDO getConversation(Long id) {
+ return conversationMapper.selectById(id);
}
@Override
- public PageResult getConversationPage(ImConversationPageReqVO pageReqVO) {
- return imConversationMapper.selectPage(pageReqVO);
+ public PageResult getConversationPage(ImConversationPageReqVO pageReqVO) {
+ return conversationMapper.selectPage(pageReqVO);
}
@Override
- public List getConversationList() {
- return imConversationMapper.selectList();
+ public List getConversationList() {
+ return conversationMapper.selectList();
}
@Override
@@ -95,20 +95,20 @@ public class ImConversationServiceImpl implements ImConversationService {
// 3. 做对应更新的 notify 推送
private void createOrUpdateConversation(ImConversationSaveReqVO updateReqVO) {
// 操作会话(已读、置顶)时,才会延迟创建,要先判断是否存在,根据 no 查询是否存在,不存在则新增
- ImConversationDO conversation = imConversationMapper.selectByNo(updateReqVO.getNo());
+ ConversationDO conversation = conversationMapper.selectByNo(updateReqVO.getNo());
if (conversation == null) {
- ImConversationDO conversationDO = new ImConversationDO();
+ ConversationDO conversationDO = new ConversationDO();
conversationDO.setNo(updateReqVO.getNo());
conversationDO.setUserId(updateReqVO.getUserId());
conversationDO.setTargetId(updateReqVO.getTargetId());
- conversationDO.setConversationType(updateReqVO.getConversationType());
+ conversationDO.setType(updateReqVO.getType());
conversationDO.setPinned(updateReqVO.getPinned());
conversationDO.setLastReadTime(DateUtil.toLocalDateTime(new Date()));
- imConversationMapper.insert(conversationDO);
+ conversationMapper.insert(conversationDO);
} else {
// 更新
- ImConversationDO updateObj = BeanUtils.toBean(updateReqVO, ImConversationDO.class);
- imConversationMapper.updateById(updateObj);
+ ConversationDO updateObj = BeanUtils.toBean(updateReqVO, ConversationDO.class);
+ conversationMapper.updateById(updateObj);
}
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java
index 4ebc373..cd395b8 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.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.ImGroupDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
/**
@@ -40,7 +40,7 @@ public interface ImGroupService {
* @param id 编号
* @return 群
*/
- ImGroupDO getGroup(Long id);
+ GroupDO getGroup(Long id);
/**
* 获得群分页
@@ -48,6 +48,6 @@ public interface ImGroupService {
* @param pageReqVO 分页查询
* @return 群分页
*/
- PageResult getGroupPage(ImGroupPageReqVO pageReqVO);
+ PageResult getGroupPage(ImGroupPageReqVO pageReqVO);
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
index e7e20e9..5cc2e1b 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
@@ -5,7 +5,7 @@ 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.ImGroupDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -29,7 +29,7 @@ public class ImGroupServiceImpl implements ImGroupService {
@Override
public Long createGroup(ImGroupSaveReqVO createReqVO) {
// 插入
- ImGroupDO group = BeanUtils.toBean(createReqVO, ImGroupDO.class);
+ GroupDO group = BeanUtils.toBean(createReqVO, GroupDO.class);
imGroupMapper.insert(group);
// 返回
return group.getId();
@@ -40,7 +40,7 @@ public class ImGroupServiceImpl implements ImGroupService {
// 校验存在
validateGroupExists(updateReqVO.getId());
// 更新
- ImGroupDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupDO.class);
+ GroupDO updateObj = BeanUtils.toBean(updateReqVO, GroupDO.class);
imGroupMapper.updateById(updateObj);
}
@@ -59,12 +59,12 @@ public class ImGroupServiceImpl implements ImGroupService {
}
@Override
- public ImGroupDO getGroup(Long id) {
+ public GroupDO getGroup(Long id) {
return imGroupMapper.selectById(id);
}
@Override
- public PageResult getGroupPage(ImGroupPageReqVO pageReqVO) {
+ public PageResult getGroupPage(ImGroupPageReqVO pageReqVO) {
return imGroupMapper.selectPage(pageReqVO);
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java
index 4ee73ae..4c27936 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.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.groupmember.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
import jakarta.validation.Valid;
import java.util.List;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java
index 3152f04..f4ebd31 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java
@@ -5,7 +5,7 @@ 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.groupmember.GroupMemberDO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.GroupMemberDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxService.java
index 98c164a..948b554 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxService.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxService.java
@@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.im.service.inbox;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxPageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
+import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveMessageReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.inbox.InboxDO;
import jakarta.validation.Valid;
// TODO @hao:不用的方法,删除下哈;
@@ -20,14 +21,14 @@ public interface ImInboxService {
* @param createReqVO 创建信息
* @return 编号
*/
- Long createInbox(@Valid ImInboxSaveReqVO createReqVO);
+ Long createInbox(@Valid InboxSaveReqVO createReqVO);
/**
* 更新收件箱
*
* @param updateReqVO 更新信息
*/
- void updateInbox(@Valid ImInboxSaveReqVO updateReqVO);
+ void updateInbox(@Valid InboxSaveReqVO updateReqVO);
/**
* 删除收件箱
@@ -42,7 +43,7 @@ public interface ImInboxService {
* @param id 编号
* @return 收件箱
*/
- ImInboxDO getInbox(Long id);
+ InboxDO getInbox(Long id);
/**
* 获得收件箱分页
@@ -50,6 +51,11 @@ public interface ImInboxService {
* @param pageReqVO 分页查询
* @return 收件箱分页
*/
- PageResult getInboxPage(ImInboxPageReqVO pageReqVO);
+ PageResult getInboxPage(ImInboxPageReqVO pageReqVO);
+ /**
+ * 保存收件箱和发送消息
+ * @param inboxSaveMessageReqVO 收件箱保存消息 Request VO
+ */
+ void saveInboxAndSendMessage(InboxSaveMessageReqVO inboxSaveMessageReqVO);
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java
index 2168fde..f7bea8c 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java
@@ -1,15 +1,27 @@
package cn.iocoder.yudao.module.im.service.inbox;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxPageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO;
+import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveMessageReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.InboxSaveReqVO;
+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.dal.mysql.inbox.ImInboxMapper;
+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.service.groupmember.ImGroupMemberService;
import jakarta.annotation.Resource;
+import org.dromara.hutool.core.date.DateUnit;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
+import java.util.List;
+
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.INBOX_NOT_EXISTS;
@@ -22,22 +34,33 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.INBOX_NOT_EXIS
@Validated
public class ImInboxServiceImpl implements ImInboxService {
+ private static final Long INBOX_LOCK_TIMEOUT = 120 * DateUnit.SECOND.getMillis();
+ private static final String IM_MESSAGE_RECEIVE = "im-message-receive";
+
@Resource
private ImInboxMapper imInboxMapper;
+ @Resource
+ private SequenceRedisDao sequenceRedisDao; // 序列生成器Redis DAO
+ @Resource
+ private InboxLockRedisDAO inboxLockRedisDAO; // 收件箱的锁 Redis DAO
+ @Resource
+ private WebSocketMessageSender webSocketMessageSender; // WebSocket消息发送器
+ @Resource
+ private ImGroupMemberService imGroupMemberService;
@Override
- public Long createInbox(ImInboxSaveReqVO createReqVO) {
- ImInboxDO inbox = BeanUtils.toBean(createReqVO, ImInboxDO.class);
+ public Long createInbox(InboxSaveReqVO createReqVO) {
+ InboxDO inbox = BeanUtils.toBean(createReqVO, InboxDO.class);
imInboxMapper.insert(inbox);
return inbox.getId();
}
@Override
- public void updateInbox(ImInboxSaveReqVO updateReqVO) {
+ public void updateInbox(InboxSaveReqVO updateReqVO) {
// 校验存在
validateInboxExists(updateReqVO.getId());
// 更新
- ImInboxDO updateObj = BeanUtils.toBean(updateReqVO, ImInboxDO.class);
+ InboxDO updateObj = BeanUtils.toBean(updateReqVO, InboxDO.class);
imInboxMapper.updateById(updateObj);
}
@@ -56,13 +79,45 @@ public class ImInboxServiceImpl implements ImInboxService {
}
@Override
- public ImInboxDO getInbox(Long id) {
+ public InboxDO getInbox(Long id) {
return imInboxMapper.selectById(id);
}
@Override
- public PageResult getInboxPage(ImInboxPageReqVO pageReqVO) {
+ public PageResult getInboxPage(ImInboxPageReqVO pageReqVO) {
return imInboxMapper.selectPage(pageReqVO);
}
+ @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 groupMembers = imGroupMemberService.selectByGroupId(inboxSaveMessage.getReceiverId());
+ groupMembers.forEach(groupMemberDO -> saveInboxAndSendMessageForUser(groupMemberDO.getUserId(), inboxSaveMessage));
+ }
+ }
+
+ private void saveInboxAndSendMessageForUser(Long userId, InboxSaveMessageReqVO inboxSaveMessage) {
+ inboxLockRedisDAO.lock(userId, INBOX_LOCK_TIMEOUT, () -> {
+ Long userSequence = sequenceRedisDao.generateSequence(userId);
+ InboxDO inbox = new InboxDO();
+ inbox.setUserId(userId);
+ inbox.setMessageId(inboxSaveMessage.getMessageId());
+ inbox.setSequence(userSequence);
+ imInboxMapper.insert(inbox);
+
+ //是发送人不发送
+ if (userId.equals(inboxSaveMessage.getFromId())) {
+ return;
+ }
+ InboxSendMessageReqVO message = BeanUtils.toBean(inboxSaveMessage, InboxSendMessageReqVO.class);
+ message.setSequence(userSequence);
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId, IM_MESSAGE_RECEIVE, message);
+ });
+ }
+
}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java
deleted file mode 100755
index 061e1d7..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package cn.iocoder.yudao.module.im.service.message;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
-import jakarta.validation.Valid;
-
-import java.util.List;
-
-/**
- * 消息 Service 接口
- *
- * @author 芋道源码
- */
-public interface ImMessageService {
-
- /**
- * 创建消息
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createMessage(@Valid ImMessageSaveReqVO createReqVO);
-
- /**
- * 更新消息
- *
- * @param updateReqVO 更新信息
- */
- void updateMessage(@Valid ImMessageSaveReqVO updateReqVO);
-
- /**
- * 删除消息
- *
- * @param id 编号
- */
- void deleteMessage(Long id);
-
- /**
- * 获得消息
- *
- * @param id 编号
- * @return 消息
- */
- ImMessageDO getMessage(Long id);
-
- /**
- * 获得消息分页
- *
- * @param pageReqVO 分页查询
- * @return 消息分页
- */
- PageResult getMessagePage(ImMessagePageReqVO pageReqVO);
-
-
- /**
- * 保存私聊消息
- *
- * @param imSendMessage 消息信息
- * @param fromUserId 发送人编号
- * @return id
- */
- ImMessageDO savePrivateMessage(ImSendMessage imSendMessage, Long fromUserId);
-
- /**
- * 更新消息状态
- *
- * @param messageId 消息id
- * @param messageStatus 消息状态
- */
- void updateMessageStatus(Long messageId, Integer messageStatus);
-
- /**
- * 保存群聊消息
- *
- * @param message 消息
- * @param fromUserId 发送者用户ID
- * @return id
- */
- ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId);
-
- /**
- * 拉取消息-大于 seq 的消息
- *
- * @param userId 用户id
- * @param sequence 序列号
- * @param size 数量
- * @return 消息列表
- */
- List loadMessage(Long userId, Long sequence, Integer size);
-
- // TODO @hao;这种接口,项目里叫 getMessageListByUserId,尽量保持 getList 获取列表哈;
- /**
- * 拉取全部消息
- *
- * @param userId 登录用户编号
- * @param size 数量
- * @return 消息列表
- */
- List loadAllMessage(Long userId, Integer size);
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java
deleted file mode 100755
index 6c5a98f..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package cn.iocoder.yudao.module.im.service.message;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import cn.iocoder.yudao.module.im.dal.mysql.message.ImMessageMapper;
-import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
-import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
-import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import jakarta.annotation.Resource;
-import org.dromara.hutool.core.date.TimeUtil;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.MESSAGE_NOT_EXISTS;
-
-/**
- * 消息 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-@Validated
-public class ImMessageServiceImpl implements ImMessageService {
-
- @Resource
- private ImMessageMapper imMessageMapper;
- @Resource
- private AdminUserApi adminUserApi;
-
- @Override
- public Long createMessage(ImMessageSaveReqVO createReqVO) {
- // 插入
- ImMessageDO message = BeanUtils.toBean(createReqVO, ImMessageDO.class);
- imMessageMapper.insert(message);
- // 返回
- return message.getId();
- }
-
- @Override
- public void updateMessage(ImMessageSaveReqVO updateReqVO) {
- // 校验存在
- validateMessageExists(updateReqVO.getId());
- // 更新
- ImMessageDO updateObj = BeanUtils.toBean(updateReqVO, ImMessageDO.class);
- imMessageMapper.updateById(updateObj);
- }
-
- @Override
- public void deleteMessage(Long id) {
- // 校验存在
- validateMessageExists(id);
- // 删除
- imMessageMapper.deleteById(id);
- }
-
- private void validateMessageExists(Long id) {
- if (imMessageMapper.selectById(id) == null) {
- throw exception(MESSAGE_NOT_EXISTS);
- }
- }
-
- @Override
- public ImMessageDO getMessage(Long id) {
- return imMessageMapper.selectById(id);
- }
-
- @Override
- public PageResult getMessagePage(ImMessagePageReqVO pageReqVO) {
- return imMessageMapper.selectPage(pageReqVO);
- }
-
-
- @Override
- public ImMessageDO savePrivateMessage(ImSendMessage message, Long fromUserId) {
- return saveImMessageDO(message, fromUserId);
- }
-
- private ImMessageDO saveImMessageDO(ImSendMessage message, Long fromUserId) {
- // TODO @hao:可以搞成 messageDO
- // TODO @hao:链式调用
- ImMessageDO imMessageDO = new ImMessageDO();
- imMessageDO.setClientMessageId(message.getClientMessageId());
- imMessageDO.setSenderId(fromUserId);
- imMessageDO.setReceiverId(message.getReceiverId());
- // 查询发送人昵称和发送人头像
- AdminUserRespDTO user = adminUserApi.getUser(fromUserId);
- imMessageDO.setSenderNickname(user.getNickname());
- imMessageDO.setSenderAvatar(user.getAvatar());
- imMessageDO.setConversationType(message.getConversationType());
- imMessageDO.setContentType(message.getContentType());
- // 单聊:s_{userId}_{targetId} 群聊:群聊:g_{groupId}
- // TODO @hao:这里的 conversationNo 的生成,可以写到工具类里,或者干脆放到 ImConversationTypeEnum 里;
- if (message.getConversationType().equals(ImConversationTypeEnum.PRIVATE.getType())) {
- imMessageDO.setConversationNo("s_" + fromUserId + "_" + message.getReceiverId());
- } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
- imMessageDO.setConversationNo("g_" + message.getReceiverId());
- }
- imMessageDO.setContent(message.getContent());
- // TODO @hao:枚举哈;
- // 消息来源 100-用户发送;200-系统发送(一般是通知);不能为空
- imMessageDO.setSendFrom(100);
- imMessageDO.setSendTime(TimeUtil.now());
- // TODO @hao:服务端的消息,就是默认生成哈;
- imMessageDO.setMessageStatus(ImMessageStatusEnum.SENDING.getStatus());
- imMessageMapper.insert(imMessageDO);
- return imMessageDO;
- }
-
- @Override
- public void updateMessageStatus(Long messageId, Integer messageStatus) {
- // 校验 id 是否存在
- validateMessageExists(messageId);
- //更新消息状态
- ImMessageDO imMessageDO = new ImMessageDO();
- imMessageDO.setId(messageId);
- imMessageDO.setMessageStatus(messageStatus);
- imMessageMapper.updateById(imMessageDO);
- }
-
- @Override
- public ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId) {
- return saveImMessageDO(message, fromUserId);
- }
-
- @Override
- public List loadMessage(Long userId, Long sequence, Integer size) {
- return imMessageMapper.getGreaterThanSequenceMessage(userId, sequence, size);
- }
-
- @Override
- public List loadAllMessage(Long userId, Integer size) {
- return imMessageMapper.getAllMessage(userId, size);
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageService.java
new file mode 100755
index 0000000..82b03dc
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageService.java
@@ -0,0 +1,43 @@
+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 java.util.List;
+
+/**
+ * 消息 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface MessageService {
+
+ /**
+ * 获得消息分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 消息分页
+ */
+ List getMessagePage(MessagePageReqVO pageReqVO);
+
+
+ /**
+ * 拉取消息-大于 seq 的消息
+ *
+ * @param userId 用户id
+ * @param sequence 序列号
+ * @param size 数量
+ * @return 消息列表
+ */
+ List getMessageListBySequence(Long userId, Long sequence, Integer size);
+
+ /**
+ * 发送消息
+ * @param loginUserId 登录用户编号
+ * @param message 消息
+ * @return 消息编号
+ */
+ SendMessageRespVO sendMessage(Long loginUserId, SendMessageReqVO message);
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
new file mode 100755
index 0000000..76d2623
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
@@ -0,0 +1,122 @@
+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.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.service.groupmember.ImGroupMemberService;
+import cn.iocoder.yudao.module.im.service.inbox.ImInboxService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.hutool.core.date.TimeUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.MESSAGE_RECEIVER_NOT_EXISTS;
+
+/**
+ * 消息 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+@Slf4j
+public class MessageServiceImpl implements MessageService {
+
+ @Resource
+ private MessageMapper messageMapper;
+ @Resource
+ private ImInboxService imInboxService; // IM收件箱服务
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private ImGroupMemberService imGroupMemberService;
+
+ @Override
+ public List getMessagePage(MessagePageReqVO pageReqVO) {
+ return messageMapper.getMessagePage(pageReqVO);
+ }
+
+ @Override
+ public List getMessageListBySequence(Long userId, Long sequence, Integer size) {
+ return messageMapper.getGreaterThanSequenceMessage(userId, sequence, size);
+ }
+
+ @Override
+ public SendMessageRespVO sendMessage(Long fromUserId, SendMessageReqVO message) {
+ // 保存消息
+ InboxSaveMessageReqVO inboxSaveMessageReqVO = new InboxSaveMessageReqVO();
+ SendMessageRespVO sendMessageRespVO = saveMessage(fromUserId, message, inboxSaveMessageReqVO);
+
+ // 保存收件箱 + 发送消息给用户
+ imInboxService.saveInboxAndSendMessage(inboxSaveMessageReqVO);
+ return sendMessageRespVO;
+ }
+
+ public SendMessageRespVO saveMessage(Long fromUserId, SendMessageReqVO message, InboxSaveMessageReqVO inboxSaveMessageReqVO) {
+ //需要校验 receiverId 存在
+ validateReceiverIdExists(message);
+ // 查询发送人昵称和发送人头像
+ AdminUserRespDTO fromUser = adminUserApi.getUser(fromUserId);
+ // 使用链式调用创建 MessageDO 对象
+ MessageDO messageDO = new MessageDO()
+ .setClientMessageId(message.getClientMessageId())
+ .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());
+ inboxSaveMessageReqVO.setFromId(fromUserId);
+ inboxSaveMessageReqVO.setReceiverId(message.getReceiverId());
+ inboxSaveMessageReqVO.setMessageId(messageDO.getId());
+ inboxSaveMessageReqVO.setContentType(message.getContentType());
+ inboxSaveMessageReqVO.setContent(message.getContent());
+ inboxSaveMessageReqVO.setSendTime(messageDO.getSendTime());
+
+ // 返回 SendMessageRespVO 对象
+ return new SendMessageRespVO(messageDO.getId(), messageDO.getSendTime());
+ }
+
+ private void validateReceiverIdExists(SendMessageReqVO message) {
+ if (message.getReceiverId() == null) {
+ throw exception(MESSAGE_RECEIVER_NOT_EXISTS);
+ }
+ if (message.getConversationType().equals(ConversationTypeEnum.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 groupMemberDOS = imGroupMemberService.selectByGroupId(message.getReceiverId());
+ if (groupMemberDOS.isEmpty()) {
+ throw exception(MESSAGE_RECEIVER_NOT_EXISTS);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
deleted file mode 100644
index be816f7..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package cn.iocoder.yudao.module.im.websocket;
-
-import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
-import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
-import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
-import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
-import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
-import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceGeneratorRedisDao;
-import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
-import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
-import cn.iocoder.yudao.module.im.service.conversation.ImConversationService;
-import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
-import cn.iocoder.yudao.module.im.service.inbox.ImInboxService;
-import cn.iocoder.yudao.module.im.service.message.ImMessageService;
-import cn.iocoder.yudao.module.im.websocket.message.ImReceiveMessage;
-import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.springframework.web.socket.WebSocketSession;
-
-import java.util.List;
-
-// TODO @hao:消息发送,使用 http 上行。因为在 cloud 框架下,我们比较难去 Listener。因为 im-server 不会自己启动 websocket 路径
-/**
- * WebSocket im
- *
- * @author 芋道源码
- */
-@Component
-@Slf4j
-public class ImWebSocketMessageListener implements WebSocketMessageListener {
-
- public static final String IM_MESSAGE_RECEIVE = "im-message-receive";
- @Resource
- private WebSocketMessageSender webSocketMessageSender; // WebSocket消息发送器
- @Resource
- private ImMessageService imMessageService; // IM消息服务
- @Resource
- private ImConversationService imConversationService; // IM会话服务
- @Resource
- private ImInboxService imInboxService; // IM收件箱服务
- @Resource
- private ImGroupMemberService imGroupMemberService; // 群成员服务
- @Resource
- private SequenceGeneratorRedisDao sequenceGeneratorRedisDao; // 序列生成器Redis DAO
-
- /**
- * 处理WebSocket消息
- *
- * @param session WebSocket会话
- * @param message 发送的IM消息
- */
- @Override
- public void onMessage(WebSocketSession session, ImSendMessage message) {
- Long fromUserId = WebSocketFrameworkUtils.getLoginUserId(session); // 获取登录用户ID
-
- // 如果是私人消息,处理私人消息
- if (message.getConversationType().equals(ImConversationTypeEnum.PRIVATE.getType())) {
- handlePrivateMessage(fromUserId, message);
- } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) {
- // 处理群聊消息
- handleGroupMessage(fromUserId, message);
- } else {
- // TODO @hao:是不是应该会话类型哈?然后打印这种错误日志,最好把 message 整个打进去,这样更好定位完整的消息;
- log.error("[onMessage][消息类型({}) 未支持]", message.getConversationType());
- }
- }
-
- /**
- * 处理群聊消息
- *
- * @param fromUserId 发送者用户ID
- * @param message 发送的IM消息
- */
- private void handleGroupMessage(Long fromUserId, ImSendMessage message) {
- // TODO @hao:群存在;
- // TODO @hao:发送人在群里;
- ImMessageDO imMessageDO = imMessageService.saveGroupMessage(message, fromUserId); // 保存群聊消息
- Long groupId = message.getReceiverId();
-
- // 发送消息给群聊成员
- // TODO @hao:变量名可以叫 groupMembers;一般不用 DO 后缀,除非为了区分;
- List groupMemberDOList = imGroupMemberService.selectByGroupId(groupId);
- groupMemberDOList.forEach(groupMemberDO -> {
- // 过滤掉自己
- // TODO @hao:98 到 99 的代码,是不是可以融合到这里来;
- if (groupMemberDO.getUserId().equals(fromUserId)) {
- return;
- }
- Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(groupMemberDO.getUserId()); // 生成接收者序列
- Long receiverInboxId = createAndSaveInbox(groupMemberDO.getUserId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱
- sendMessage(groupMemberDO.getUserId(), receiverInboxId, imMessageDO, message, receiverSequence);
- });
-
- Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列
- Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱
-
- // 发送消息给发送者
- sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, fromUserSequence);
-
- // 更新消息状态为成功
- imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus());
- }
-
- /**
- * 处理私人消息
- *
- * @param fromUserId 发送者用户ID
- * @param message 发送的IM消息
- */
- private void handlePrivateMessage(Long fromUserId, ImSendMessage message) {
- // TODO @hao:需要校验 receiverId 存在;
- ImMessageDO imMessageDO = imMessageService.savePrivateMessage(message, fromUserId); // 保存私人消息
- Long receiverId = message.getReceiverId();
-
- // TODO @hao:sequenceGeneratorRedisDao.generateSequence 和 createAndSaveInbox 步骤,要加锁;不然会有并发问题;如果有疑问,可以微信招我沟通哈;另外,创建 seq、保存收件箱、发送,可以统一封装到 imInboxService 里哈;这样,后续要发某个消息,就是丢个 message 对象进去;
- Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列
- Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱
-
- Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(message.getReceiverId()); // 生成接收者序列
- Long receiverInboxId = createAndSaveInbox(message.getReceiverId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱
-
- // 发送消息给接收者和发送者
- sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, fromUserSequence);
- sendMessage(receiverId, receiverInboxId, imMessageDO, message, receiverSequence);
-
- // 更新消息状态为成功
- // TODO @hao:后端消息的发送,默认就是 success 哈,不要区分 status;status 更多是前端使用的;
- imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus());
- // 保存私人会话,只有在 client 操作会话(已读、置顶)时,才会延迟创建
- //imConversationService.savePrivateConversation(fromUserId, receiverId);
- }
-
- /**
- * 创建并保存收件箱
- *
- * @param userId 用户ID
- * @param messageId 消息ID
- * @param sequence 序列
- * @return 收件箱ID
- */
- private Long createAndSaveInbox(Long userId, Long messageId, Long sequence) {
- ImInboxSaveReqVO inboxSaveReqVO = new ImInboxSaveReqVO(userId, messageId, sequence); // 创建收件箱保存请求VO
- return imInboxService.createInbox(inboxSaveReqVO); // 创建收件箱
- }
-
- // TODO @hao:这个使用 WebSocketSenderApi 发送哈;
- /**
- * 发送消息
- *
- * @param fromUserId 发送者用户ID
- * @param inboxId 收件箱ID
- * @param imMessageDO IM消息数据对象
- * @param message 发送的IM消息
- * @param sequence 序列
- */
- private void sendMessage(Long fromUserId, Long inboxId, ImMessageDO imMessageDO, ImSendMessage message, Long sequence) {
- // TODO @hao:不要每个字段 set 占一行;想同类型的字段用一行,然后链式 set,会更简洁干净。
- ImReceiveMessage receiveMessage = new ImReceiveMessage(); // 创建接收消息
- receiveMessage.setFromId(fromUserId); // 设置发送者ID
- receiveMessage.setConversationType(message.getConversationType()); // 设置会话类型
- receiveMessage.setContentType(message.getContentType()); // 设置内容类型
- receiveMessage.setContent(message.getContent()); // 设置内容
- receiveMessage.setMessageId(imMessageDO.getId()); // 设置消息ID
- receiveMessage.setInboxId(inboxId); // 设置收件箱ID
- receiveMessage.setSendTime(imMessageDO.getSendTime()); // 设置发送时间
- receiveMessage.setSequence(sequence); // 设置序列
- webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), fromUserId, ImWebSocketMessageListener.IM_MESSAGE_RECEIVE, receiveMessage); // 发送消息
- }
-
- /**
- * 获取类型
- *
- * @return 类型
- */
- @Override
- public String getType() {
- return "im-message-send";
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java
deleted file mode 100644
index 440e308..0000000
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package cn.iocoder.yudao.module.im.websocket.message;
-
-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")
- // TODO @hao:用下 InEnum 校验。这样可以少写 15 的注释哈;类似 contentType 也是;
- private Integer conversationType; // 对应 ImConversationTypeEnum 枚举
-
- @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
- private Long receiverId; // 根据 conversationType 区分
-
- @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
- private Integer contentType; // 参见 ImMessageTypeEnum 枚举
-
- @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
- private String content;
-
-}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ImConversationMapper.xml b/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ConversationMapper.xml
index 37fd6fb..f6a9d5a 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ImConversationMapper.xml
+++ b/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/ConversationMapper.xml
@@ -1,6 +1,6 @@
-
+