Commit 77f3131ef3a174dc77e5e4c8fc6ad46364801c9c

Authored by 安浩浩
1 parent 2d052ea7

修改:私聊消息判断发送状态

yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.im.enums.message;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.Getter;
  5 +import lombok.RequiredArgsConstructor;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +@RequiredArgsConstructor
  10 +@Getter
  11 +public enum ImMessageStatusEnum implements IntArrayValuable {
  12 +
  13 + SENDING(1, "发送中"),
  14 + SUCCESS(2, "发送成功"),
  15 + FAILURE(3, "发送失败"),
  16 + DELETED(4, "已删除"),
  17 + RECALL(5, "已撤回");
  18 +
  19 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageStatusEnum::getStatus).toArray();
  20 + private final Integer status;
  21 + private final String name;
  22 +
  23 + @Override
  24 + public int[] array() {
  25 + return ARRAYS;
  26 + }
  27 +
  28 +}
0 29 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java
1 1 package cn.iocoder.yudao.module.im.enums.message;
2 2  
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
3 4 import lombok.AllArgsConstructor;
4 5 import lombok.Getter;
5 6  
  7 +import java.util.Arrays;
  8 +
6 9 /**
7 10 * IM 消息的类型枚举
8   - *
  11 + * <p>
9 12 * 参考 <a href="https://doc.yunxin.163.com/messaging/docs/zg3NzA3NTA?platform=web#消息类型">“消息类型”</a> 文档
10 13 *
11 14 * @author 芋道源码
12 15 */
13 16 @Getter
14 17 @AllArgsConstructor
15   -public enum ImMessageTypeEnum {
  18 +public enum ImMessageTypeEnum implements IntArrayValuable {
16 19  
17 20 TEXT(1, "文本"), // 消息内容为普通文本
18 21 IMAGE(2, "图片"), // 消息内容为图片 URL 地址、尺寸、图片大小等信息
... ... @@ -25,6 +28,7 @@ public enum ImMessageTypeEnum {
25 28 NOTIFICATION(8, "通知"), // 主要用于群组、聊天室和超大群的事件通知,由服务端下发,客户端无法发送事件通知消息。通知类消息有在线、离线、漫游机制;没有通知栏提醒
26 29 ;
27 30  
  31 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageTypeEnum::getType).toArray();
28 32 /**
29 33 * 类型
30 34 */
... ... @@ -34,4 +38,8 @@ public enum ImMessageTypeEnum {
34 38 */
35 39 private final String name;
36 40  
  41 + @Override
  42 + public int[] array() {
  43 + return ARRAYS;
  44 + }
37 45 }
38 46 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessagePageReqVO.java
1 1 package cn.iocoder.yudao.module.im.controller.admin.message.vo;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import com.alibaba.excel.annotation.ExcelProperty;
4 5 import io.swagger.v3.oas.annotations.media.Schema;
5 6 import lombok.Data;
6 7 import lombok.EqualsAndHashCode;
... ... @@ -55,4 +56,7 @@ public class ImMessagePageReqVO extends PageParam {
55 56 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
56 57 private LocalDateTime[] createTime;
57 58  
  59 + @Schema(description = "消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回", requiredMode = Schema.RequiredMode.REQUIRED)
  60 + private Integer messageStatus;
  61 +
58 62 }
59 63 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageRespVO.java
1 1 package cn.iocoder.yudao.module.im.controller.admin.message.vo;
2 2  
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
  5 +import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
3 6 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4 7 import com.alibaba.excel.annotation.ExcelProperty;
5 8 import io.swagger.v3.oas.annotations.media.Schema;
  9 +import jakarta.validation.constraints.NotNull;
6 10 import lombok.Data;
7 11  
8 12 import java.time.LocalDateTime;
... ... @@ -46,6 +50,7 @@ public class ImMessageRespVO {
46 50  
47 51 @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
48 52 @ExcelProperty("消息类型")
  53 + @InEnum(ImMessageTypeEnum.class)
49 54 private Integer contentType;
50 55  
51 56 @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
... ... @@ -64,4 +69,9 @@ public class ImMessageRespVO {
64 69 @ExcelProperty("创建时间")
65 70 private LocalDateTime createTime;
66 71  
  72 + @Schema(description = "消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回", requiredMode = Schema.RequiredMode.REQUIRED)
  73 + @ExcelProperty("消息状态")
  74 + @InEnum(ImMessageStatusEnum.class)
  75 + private Integer messageStatus;
  76 +
67 77 }
68 78 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSaveReqVO.java
... ... @@ -38,7 +38,7 @@ public class ImMessageSaveReqVO {
38 38 @NotNull(message = "会话类型不能为空")
39 39 private Integer conversationType;
40 40  
41   - @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED)
  41 + @Schema(description = "会话标志 conversation_no = a_b", requiredMode = Schema.RequiredMode.REQUIRED)
42 42 @NotEmpty(message = "会话标志不能为空")
43 43 private String conversationNo;
44 44  
... ... @@ -57,4 +57,7 @@ public class ImMessageSaveReqVO {
57 57 @NotNull(message = "消息来源 100-用户发送;200-系统发送(一般是通知);不能为空")
58 58 private Integer sendFrom;
59 59  
  60 + @Schema(description = "消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回", requiredMode = Schema.RequiredMode.REQUIRED)
  61 + @NotNull(message = "消息状态不能为空")
  62 + private Integer messageStatus;
60 63 }
61 64 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImMessageDO.java
... ... @@ -73,4 +73,9 @@ public class ImMessageDO extends BaseDO {
73 73 */
74 74 private Integer sendFrom;
75 75  
  76 + /**
  77 + * 消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回
  78 + */
  79 + private Integer messageStatus;
  80 +
76 81 }
77 82 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java
... ... @@ -61,4 +61,12 @@ public interface ImMessageService {
61 61 * @return id
62 62 */
63 63 Long savePrivateMessage(ImSendMessage imSendMessage, Long fromUserId);
  64 +
  65 + /**
  66 + * 更新消息状态
  67 + *
  68 + * @param messageId 消息id
  69 + * @param messageStatus 消息状态
  70 + */
  71 + void updateMessageStatus(Long messageId, Integer messageStatus);
64 72 }
65 73 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java
... ... @@ -6,10 +6,12 @@ import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO
6 6 import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSaveReqVO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO;
8 8 import cn.iocoder.yudao.module.im.dal.mysql.message.ImMessageMapper;
  9 +import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
9 10 import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
10 11 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
11 12 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
12 13 import jakarta.annotation.Resource;
  14 +import org.dromara.hutool.core.date.TimeUtil;
13 15 import org.springframework.stereotype.Service;
14 16 import org.springframework.validation.annotation.Validated;
15 17  
... ... @@ -74,22 +76,35 @@ public class ImMessageServiceImpl implements ImMessageService {
74 76  
75 77  
76 78 @Override
77   - public Long savePrivateMessage(ImSendMessage message, Long fromUserId) {
  79 + public Long savePrivateMessage(ImSendMessage message, Long senderId) {
78 80 ImMessageSaveReqVO imMessageSaveReqVO = new ImMessageSaveReqVO();
79 81 imMessageSaveReqVO.setClientMessageId(message.getClientMessageId());
80   - imMessageSaveReqVO.setSenderId(fromUserId);
  82 + imMessageSaveReqVO.setSenderId(senderId);
81 83 imMessageSaveReqVO.setReceiverId(message.getReceiverId());
82 84 //查询发送人昵称和发送人头像
83   - AdminUserRespDTO user = adminUserApi.getUser(fromUserId);
  85 + AdminUserRespDTO user = adminUserApi.getUser(senderId);
84 86 imMessageSaveReqVO.setSenderNickname(user.getNickname());
85 87 imMessageSaveReqVO.setSenderAvatar(user.getAvatar());
86 88 imMessageSaveReqVO.setConversationType(message.getConversationType());
87 89 imMessageSaveReqVO.setContentType(message.getContentType());
88   - imMessageSaveReqVO.setConversationNo("1");
  90 + imMessageSaveReqVO.setConversationNo(senderId + "_" + message.getReceiverId());
89 91 imMessageSaveReqVO.setContent(message.getContent());
90 92 //消息来源 100-用户发送;200-系统发送(一般是通知);不能为空
91 93 imMessageSaveReqVO.setSendFrom(100);
  94 + imMessageSaveReqVO.setSendTime(TimeUtil.now());
  95 + imMessageSaveReqVO.setMessageStatus(ImMessageStatusEnum.SENDING.getStatus());
92 96 return createMessage(imMessageSaveReqVO);
93 97 }
94 98  
  99 + @Override
  100 + public void updateMessageStatus(Long messageId, Integer messageStatus) {
  101 + //校验 id 是否存在
  102 + validateMessageExists(messageId);
  103 + //更新消息状态
  104 + ImMessageDO imMessageDO = new ImMessageDO();
  105 + imMessageDO.setId(messageId);
  106 + imMessageDO.setMessageStatus(messageStatus);
  107 + imMessageMapper.updateById(imMessageDO);
  108 + }
  109 +
95 110 }
96 111 \ No newline at end of file
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
... ... @@ -3,25 +3,31 @@ package cn.iocoder.yudao.module.im.websocket;
3 3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4 4 import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
5 5 import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
  6 +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager;
6 7 import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
7 8 import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO;
8 9 import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceGeneratorRedisDao;
9 10 import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum;
  11 +import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
10 12 import cn.iocoder.yudao.module.im.service.conversation.ImConversationService;
11 13 import cn.iocoder.yudao.module.im.service.inbox.ImInboxService;
12 14 import cn.iocoder.yudao.module.im.service.message.ImMessageService;
13 15 import cn.iocoder.yudao.module.im.websocket.message.ImReceiveMessage;
14 16 import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
15 17 import jakarta.annotation.Resource;
  18 +import lombok.extern.slf4j.Slf4j;
16 19 import org.springframework.stereotype.Component;
17 20 import org.springframework.web.socket.WebSocketSession;
18 21  
  22 +import java.util.List;
  23 +
19 24 /**
20   - * WebSocket 示例:单发消息
  25 + * WebSocket im
21 26 *
22 27 * @author 芋道源码
23 28 */
24 29 @Component
  30 +@Slf4j
25 31 public class ImWebSocketMessageListener implements WebSocketMessageListener<ImSendMessage> {
26 32  
27 33 @Resource
... ... @@ -34,6 +40,8 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
34 40 private ImInboxService imInboxService;
35 41 @Resource
36 42 private SequenceGeneratorRedisDao sequenceGeneratorRedisDao;
  43 + @Resource
  44 + private WebSocketSessionManager webSocketSessionManager;
37 45  
38 46 @Override
39 47 public void onMessage(WebSocketSession session, ImSendMessage message) {
... ... @@ -48,6 +56,14 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
48 56 imInboxService.createInbox(new ImInboxSaveReqVO(fromUserId, messageId, sequenceGeneratorRedisDao.generateSequence(fromUserId)));
49 57  
50 58 //3、推送消息
  59 + // 3.1判断是否在线
  60 + List<WebSocketSession> sessions = (List<WebSocketSession>) webSocketSessionManager.getSessionList(UserTypeEnum.ADMIN.getValue(), message.getReceiverId());
  61 + if (sessions.isEmpty()) {
  62 + //更新消息状态,为发送失败
  63 + imMessageService.updateMessageStatus(messageId, ImMessageStatusEnum.FAILURE.getStatus());
  64 + return;
  65 + }
  66 + //3.2发送
51 67 ImReceiveMessage toMessage = new ImReceiveMessage();
52 68 toMessage.setFromId(fromUserId);
53 69 toMessage.setConversationType(ImConversationTypeEnum.PRIVATE.getType());
... ... @@ -55,6 +71,9 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener&lt;ImSe
55 71 toMessage.setContent(message.getContent());
56 72 webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getReceiverId(), // 给指定用户
57 73 "im-message-receive", toMessage);
  74 + //4、更新消息状态,为发送成功
  75 + imMessageService.updateMessageStatus(messageId, ImMessageStatusEnum.SUCCESS.getStatus());
  76 +
58 77 }
59 78 }
60 79  
... ...