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
index e6f6cfb..0b399bd 100644
--- 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
@@ -1,50 +1,24 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
-// TODO @anhaohao:要有 IM;
-// TODO @芋艿:后续要挪到 api 包下,主要是给外部接口使用
/**
- * 语音消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author 芋道源码
+ * 语音消息内容
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
public class AudioMessage {
/**
- * 语音文件唯一 ID
+ * 语音文件 URL
*/
- private String uuid;
-
- /**
- * 语音文件的本地路径
- */
- private String soundPath;
-
+ private String url;
/**
- * 语音文件下载地址
+ * 语音时长(秒)
*/
- private String sourceUrl;
-
- /**
- * 语音文件大小
- */
- private int dataSize;
-
- /**
- * 语音时长
- */
- private int duration;
-
+ private Integer duration;
/**
- * 语音文件类型
+ * 文件大小(字节)
*/
- private String soundType;
+ private Long 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/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
index 4199f79..fd1d082 100644
--- 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
@@ -1,38 +1,24 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
/**
- * 名片消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author anhaohao
- * @since 2024/3/23 下午5:53
+ * 名片消息内容
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
public class CardMessage {
/**
- * 用户 ID
+ * 用户编号
*/
- private String userID;
-
+ private Long userId;
/**
- * 用户名
+ * 用户昵称
*/
private String nickname;
-
/**
* 用户头像
*/
- private int faceURL;
+ private String avatar;
- /**
- * 扩展字段
- */
- private String ex;
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
index 0cb112e..aabba54 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/FileMessage.java
@@ -1,27 +1,28 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
/**
- * 文件消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author 芋道源码
+ * 文件消息内容
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
public class FileMessage {
/**
+ * 文件 URL
+ */
+ private String url;
+ /**
* 文件名
*/
private String name;
/**
- * 文件 URL
+ * 文件大小(字节)
*/
- private String url;
+ private Long size;
+ /**
+ * 文件类型(扩展名)
+ */
+ private String type;
-}
\ 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/ImageMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
index 2cd0dfb..547937c 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/ImageMessage.java
@@ -1,23 +1,32 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
/**
- * 图片消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author 芋道源码
+ * 图片消息内容
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
public class ImageMessage {
/**
- * 图片地址
+ * 图片 URL
*/
private String url;
+ /**
+ * 缩略图 URL
+ */
+ private String thumbnailUrl;
+ /**
+ * 图片宽度
+ */
+ private Integer width;
+ /**
+ * 图片高度
+ */
+ private Integer height;
+ /**
+ * 图片大小(字节)
+ */
+ private Long size;
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
index 439b18f..fdbb7c7 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/LocationMessage.java
@@ -1,26 +1,17 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
/**
- * 地址位置消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author 芋道源码
+ * 位置消息内容
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
public class LocationMessage {
/**
- * 地理位置
- *
- * 例如说:中国 浙江省 杭州市 网商路 599号
+ * 位置描述
*/
- private String address;
+ private String description;
/**
* 经度
*/
@@ -30,4 +21,4 @@ public class LocationMessage {
*/
private Double latitude;
-}
\ 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/TextMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
index 35edfff..73a45b0 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/TextMessage.java
@@ -1,23 +1,16 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
/**
- * 文本消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author 芋道源码
+ * 文本消息内容
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
public class TextMessage {
/**
- * 文本消息的具体内容
+ * 文本内容
*/
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/dal/dataobject/message/content/VideoMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
index 166954c..822042c 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/content/VideoMessage.java
@@ -1,19 +1,36 @@
package cn.iocoder.yudao.module.im.dal.dataobject.message.content;
-import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
import lombok.Data;
/**
- * 视频消息的 {@link ImMessageDO 字段 content} 的内容
- *
- * @author 芋道源码
+ * 视频消息内容
*/
@Data
public class VideoMessage {
/**
- * 视频地址
+ * 视频文件 URL
*/
private String url;
+ /**
+ * 视频封面 URL
+ */
+ private String coverUrl;
+ /**
+ * 视频时长(秒)
+ */
+ private Integer duration;
+ /**
+ * 视频宽度
+ */
+ private Integer width;
+ /**
+ * 视频高度
+ */
+ private Integer height;
+ /**
+ * 文件大小(字节)
+ */
+ private Long 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/group/ImGroupMemberService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java
new file mode 100644
index 0000000..0f63bc4
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java
@@ -0,0 +1,80 @@
+package cn.iocoder.yudao.module.im.service.group;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 群成员 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface ImGroupMemberService {
+
+ /**
+ * 创建群成员
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createGroupMember(@Valid ImGroupMemberSaveReqVO createReqVO);
+
+ /**
+ * 更新群成员
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateGroupMember(@Valid ImGroupMemberSaveReqVO updateReqVO);
+
+ /**
+ * 删除群成员
+ *
+ * @param id 编号
+ */
+ void deleteGroupMember(Long id);
+
+ /**
+ * 获得群成员
+ *
+ * @param id 编号
+ * @return 群成员
+ */
+ ImGroupMemberDO getGroupMember(Long id);
+
+ /**
+ * 获得群成员分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 群成员分页
+ */
+ PageResult getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO);
+
+ /**
+ * 根据群组id查询群成员
+ *
+ * @param groupId 群组id
+ * @return 群成员列表
+ */
+ List selectByGroupId(Long groupId);
+
+ /**
+ * 根据群编号和用户编号查询群成员
+ *
+ * @param groupId 群编号
+ * @param userId 用户编号
+ * @return 群成员
+ */
+ ImGroupMemberDO getGroupMember(Long groupId, Long userId);
+
+ /**
+ * 查询用户所在的所有群的成员记录
+ *
+ * @param userId 用户编号
+ * @return 群成员记录列表
+ */
+ List getGroupMembersByUserId(Long userId);
+}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java
new file mode 100644
index 0000000..fac59ed
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java
@@ -0,0 +1,88 @@
+package cn.iocoder.yudao.module.im.service.group;
+
+import org.springframework.stereotype.Service;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*;
+import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
+
+/**
+ * 群成员 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class ImGroupMemberServiceImpl implements ImGroupMemberService {
+
+ @Resource
+ private ImGroupMemberMapper imGroupMemberMapper;
+
+ @Override
+ public Long createGroupMember(ImGroupMemberSaveReqVO createReqVO) {
+ // 插入
+ ImGroupMemberDO groupMember = BeanUtils.toBean(createReqVO, ImGroupMemberDO.class);
+ imGroupMemberMapper.insert(groupMember);
+ // 返回
+ return groupMember.getId();
+ }
+
+ @Override
+ public void updateGroupMember(ImGroupMemberSaveReqVO updateReqVO) {
+ // 校验存在
+ validateGroupMemberExists(updateReqVO.getId());
+ // 更新
+ ImGroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupMemberDO.class);
+ imGroupMemberMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteGroupMember(Long id) {
+ // 校验存在
+ validateGroupMemberExists(id);
+ // 删除
+ imGroupMemberMapper.deleteById(id);
+ }
+
+ private void validateGroupMemberExists(Long id) {
+ if (imGroupMemberMapper.selectById(id) == null) {
+ throw exception(GROUP_MEMBER_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public ImGroupMemberDO getGroupMember(Long id) {
+ return imGroupMemberMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO) {
+ return imGroupMemberMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public List selectByGroupId(Long groupId) {
+ return imGroupMemberMapper.selectListByGroupId(groupId);
+ }
+
+ @Override
+ public ImGroupMemberDO getGroupMember(Long groupId, Long userId) {
+ return imGroupMemberMapper.selectByGroupIdAndUserId(groupId, userId);
+ }
+
+ @Override
+ public List getGroupMembersByUserId(Long userId) {
+ return imGroupMemberMapper.selectListByUserId(userId);
+ }
+
+}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
index 267385d..b2c9505 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
@@ -15,9 +15,9 @@ import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
import cn.iocoder.yudao.module.im.enums.message.ImWebSocketTypeConstants;
import cn.iocoder.yudao.module.im.service.group.ImGroupService;
-import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
+import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
-import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
+import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -54,7 +54,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
@Resource
private GroupReadPositionRedisDAO groupReadPositionRedisDAO;
@Resource
- private WebSocketSenderApi webSocketSenderApi;
+ private WebSocketMessageSender webSocketMessageSender;
@Override
public ImGroupMessageDO sendMessage(Long senderId, ImGroupMessageSendReqVO reqVO) {
@@ -170,7 +170,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
Map readEvent = new HashMap<>();
readEvent.put("groupId", groupId.toString());
readEvent.put("messageScene", "group");
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
ImWebSocketTypeConstants.READ, readEvent);
// 5. 刷新群回执
@@ -209,7 +209,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
if (ImGroupMemberStatusEnum.QUIT.getStatus().equals(m.getStatus())) {
continue;
}
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
ImWebSocketTypeConstants.RECALL, recallEvent);
}
}
@@ -302,7 +302,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
if (ImGroupMemberStatusEnum.QUIT.getStatus().equals(m.getStatus())) {
continue;
}
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), m.getUserId(),
ImWebSocketTypeConstants.RECEIPT, receiptEvent);
}
}
@@ -382,7 +382,7 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
&& !member.getUserId().equals(message.getSenderId())) {
continue;
}
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), member.getUserId(),
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), member.getUserId(),
ImWebSocketTypeConstants.GROUP_MESSAGE, event);
}
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
index 05950af..d885d3f 100644
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
import cn.iocoder.yudao.module.im.enums.message.ImWebSocketTypeConstants;
import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
-import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
+import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -48,7 +48,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
// TODO @AI:这个类貌似路径不对?!
@Resource
- private WebSocketSenderApi webSocketSenderApi;
+ private WebSocketMessageSender webSocketMessageSender;
@Override
public ImPrivateMessageDO sendMessage(Long senderId, ImPrivateMessageSendReqVO reqVO) {
@@ -107,7 +107,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
// TODO @AI:需要整理下,相关的 websocket DTO;可维护性变强!
readEvent.put("friendId", friendId.toString());
readEvent.put("messageScene", "private");
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
ImWebSocketTypeConstants.READ, readEvent);
// 3. 发送 RECEIPT 事件给对方(已读回执)
@@ -115,7 +115,7 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
// TODO @AI:需要整理下,相关的 websocket DTO;可维护性变强!
receiptEvent.put("userId", userId.toString());
receiptEvent.put("messageScene", "private");
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), friendId,
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), friendId,
ImWebSocketTypeConstants.RECEIPT, receiptEvent);
}
@@ -147,11 +147,11 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
recallEvent.put("messageId", messageId.toString());
recallEvent.put("messageScene", "private");
recallEvent.put("senderId", userId.toString());
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
ImWebSocketTypeConstants.RECALL, recallEvent);
// 3.2 也通知发送方自己的其他终端
// TODO @AI:需要整理下,相关的 websocket DTO;可维护性变强!
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
ImWebSocketTypeConstants.RECALL, recallEvent);
}
@@ -171,10 +171,10 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
event.put("sendTime", message.getSendTime().toString());
event.put("messageScene", "private");
// 推送给接收方
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(),
ImWebSocketTypeConstants.PRIVATE_MESSAGE, event);
// 推送给发送方自己的其他终端(多端同步)
- webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), message.getSenderId(),
+ webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getSenderId(),
ImWebSocketTypeConstants.PRIVATE_MESSAGE, event);
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java
index cfbf5d8..837a5f7 100644
--- a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java
+++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java
@@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.im.service.message;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
-import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImGroupMessageSendReqVO;
+import cn.iocoder.yudao.module.im.controller.admin.message.vo.group.ImGroupMessageSendReqVO;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO;
import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
@@ -11,9 +11,9 @@ import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberStatusEnum;
import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum;
import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
import cn.iocoder.yudao.module.im.service.group.ImGroupService;
-import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService;
+import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
-import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
+import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -51,7 +51,7 @@ public class ImGroupMessageServiceImplTest {
@Mock
private GroupReadPositionRedisDAO groupReadPositionRedisDAO;
@Mock
- private WebSocketSenderApi webSocketSenderApi;
+ private WebSocketMessageSender webSocketMessageSender;
private ImGroupMessageSendReqVO buildSendReqVO() {
ImGroupMessageSendReqVO reqVO = new ImGroupMessageSendReqVO();
@@ -89,7 +89,11 @@ public class ImGroupMessageServiceImplTest {
.status(ImGroupMemberStatusEnum.NORMAL.getStatus()).build()
);
when(imGroupMemberService.selectByGroupId(10L)).thenReturn(allMembers);
- when(imGroupMessageMapper.insert(any())).thenReturn(1);
+ when(imGroupMessageMapper.insert(any(ImGroupMessageDO.class))).thenAnswer(invocation -> {
+ ImGroupMessageDO msg = invocation.getArgument(0);
+ msg.setId(99L);
+ return 1;
+ });
// 调用
ImGroupMessageDO result = groupMessageService.sendMessage(1L, reqVO);
@@ -102,7 +106,7 @@ public class ImGroupMessageServiceImplTest {
assertEquals(ImGroupMessageReceiptStatusEnum.NO_RECEIPT.getStatus(), result.getReceiptStatus());
// 验证推送给 3 个群成员
- verify(webSocketSenderApi, times(3)).sendObject(anyInt(), anyLong(), anyString(), any());
+ verify(webSocketMessageSender, times(3)).sendObject(anyInt(), anyLong(), anyString(), any());
}
@Test
@@ -121,7 +125,7 @@ public class ImGroupMessageServiceImplTest {
// 断言
assertEquals(100L, result.getId());
- verify(imGroupMessageMapper, never()).insert(any());
+ verify(imGroupMessageMapper, never()).insert(any(ImGroupMessageDO.class));
}
@Test
@@ -262,7 +266,7 @@ public class ImGroupMessageServiceImplTest {
.id(50L).senderId(1L).groupId(10L)
.status(ImMessageStatusEnum.NORMAL).build();
when(imGroupMessageMapper.selectById(50L)).thenReturn(message);
- when(imGroupMessageMapper.updateById(any())).thenReturn(1);
+ when(imGroupMessageMapper.updateById(any(ImGroupMessageDO.class))).thenReturn(1);
List members = List.of(
ImGroupMemberDO.builder().groupId(10L).userId(1L)
@@ -278,7 +282,7 @@ public class ImGroupMessageServiceImplTest {
groupMessageService.recallMessage(1L, 50L);
// 断言:只给 2 个活跃成员发送 RECALL 事件(userId=3 已退群)
- verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
+ verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
}
// ========== 群已读测试 ==========
diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java
index ddb59a6..6abb416 100644
--- a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java
+++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
-import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
+import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -40,7 +40,7 @@ public class ImPrivateMessageServiceImplTest {
@Mock
private ImSensitiveWordService imSensitiveWordService;
@Mock
- private WebSocketSenderApi webSocketSenderApi;
+ private WebSocketMessageSender webSocketMessageSender;
private ImPrivateMessageSendReqVO buildSendReqVO() {
ImPrivateMessageSendReqVO reqVO = new ImPrivateMessageSendReqVO();
@@ -59,7 +59,11 @@ public class ImPrivateMessageServiceImplTest {
ImPrivateMessageSendReqVO reqVO = buildSendReqVO();
when(imPrivateMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-001"))
.thenReturn(null);
- when(imPrivateMessageMapper.insert(any())).thenReturn(1);
+ when(imPrivateMessageMapper.insert(any(ImPrivateMessageDO.class))).thenAnswer(invocation -> {
+ ImPrivateMessageDO msg = invocation.getArgument(0);
+ msg.setId(99L);
+ return 1;
+ });
// 调用
ImPrivateMessageDO result = privateMessageService.sendMessage(1L, reqVO);
@@ -75,8 +79,8 @@ public class ImPrivateMessageServiceImplTest {
// 验证调用
verify(imFriendService).validateIsFriend(1L, 2L);
verify(imSensitiveWordService).validateText(reqVO.getContent());
- verify(imPrivateMessageMapper).insert(any());
- verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
+ verify(imPrivateMessageMapper).insert(any(ImPrivateMessageDO.class));
+ verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
}
@Test
@@ -96,7 +100,7 @@ public class ImPrivateMessageServiceImplTest {
// 断言:返回已存在的消息
assertEquals(100L, result.getId());
// 验证不会重复插入
- verify(imPrivateMessageMapper, never()).insert(any());
+ verify(imPrivateMessageMapper, never()).insert(any(ImPrivateMessageDO.class));
}
@Test
@@ -151,7 +155,7 @@ public class ImPrivateMessageServiceImplTest {
privateMessageService.readMessages(1L, 2L);
// 断言:发送了 READ 和 RECEIPT 事件
- verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
+ verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
}
// ========== 撤回测试 ==========
@@ -163,15 +167,15 @@ public class ImPrivateMessageServiceImplTest {
.id(10L).senderId(1L).receiverId(2L)
.status(ImMessageStatusEnum.UNREAD.getStatus()).build();
when(imPrivateMessageMapper.selectById(10L)).thenReturn(message);
- when(imPrivateMessageMapper.updateById(any())).thenReturn(1);
+ when(imPrivateMessageMapper.updateById(any(ImPrivateMessageDO.class))).thenReturn(1);
// 调用
privateMessageService.recallMessage(1L, 10L);
// 断言
- verify(imPrivateMessageMapper).updateById(any());
+ verify(imPrivateMessageMapper).updateById(any(ImPrivateMessageDO.class));
// 验证推送了 RECALL 事件(给接收方和发送方)
- verify(webSocketSenderApi, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
+ verify(webSocketMessageSender, times(2)).sendObject(anyInt(), anyLong(), anyString(), any());
}
@Test
diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImWebSocketEventTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImWebSocketEventTest.java
index 8732178..23ffa94 100644
--- a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImWebSocketEventTest.java
+++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/message/ImWebSocketEventTest.java
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
import cn.iocoder.yudao.module.im.enums.message.ImWebSocketTypeConstants;
import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
-import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
+import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
@@ -40,7 +40,7 @@ public class ImWebSocketEventTest {
@Mock
private ImSensitiveWordService imSensitiveWordService;
@Mock
- private WebSocketSenderApi webSocketSenderApi;
+ private WebSocketMessageSender webSocketMessageSender;
@Test
public void testSendMessage_websocketEvent() {
@@ -52,7 +52,12 @@ public class ImWebSocketEventTest {
reqVO.setContent("{\"content\":\"事件测试\"}");
when(imPrivateMessageMapper.selectBySenderIdAndClientMessageId(1L, "evt-uuid")).thenReturn(null);
- when(imPrivateMessageMapper.insert(any())).thenReturn(1);
+ // mock insert:通过 doAnswer 模拟 MyBatis-Plus 设置 ID
+ when(imPrivateMessageMapper.insert(any(ImPrivateMessageDO.class))).thenAnswer(invocation -> {
+ ImPrivateMessageDO msg = invocation.getArgument(0);
+ msg.setId(99L);
+ return 1;
+ });
// 调用
privateMessageService.sendMessage(1L, reqVO);
@@ -60,7 +65,7 @@ public class ImWebSocketEventTest {
// 捕获 WebSocket 调用
ArgumentCaptor typeCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor