From 77f3131ef3a174dc77e5e4c8fc6ad46364801c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Wed, 13 Mar 2024 23:57:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9A=E7=A7=81=E8=81=8A?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=88=A4=E6=96=AD=E5=8F=91=E9=80=81=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../im/enums/message/ImMessageStatusEnum.java | 28 +++++++++++++++++++ .../im/enums/message/ImMessageTypeEnum.java | 12 ++++++-- .../admin/message/vo/ImMessagePageReqVO.java | 4 +++ .../admin/message/vo/ImMessageRespVO.java | 10 +++++++ .../admin/message/vo/ImMessageSaveReqVO.java | 5 +++- .../dal/dataobject/message/ImMessageDO.java | 5 ++++ .../im/service/message/ImMessageService.java | 8 ++++++ .../service/message/ImMessageServiceImpl.java | 23 ++++++++++++--- .../websocket/ImWebSocketMessageListener.java | 21 +++++++++++++- 9 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java 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/ImMessageStatusEnum.java new file mode 100644 index 0000000000..2333a42c44 --- /dev/null +++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageStatusEnum.java @@ -0,0 +1,28 @@ +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; + +@RequiredArgsConstructor +@Getter +public enum ImMessageStatusEnum implements IntArrayValuable { + + SENDING(1, "发送中"), + SUCCESS(2, "发送成功"), + FAILURE(3, "发送失败"), + DELETED(4, "已删除"), + RECALL(5, "已撤回"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageStatusEnum::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/ImMessageTypeEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java index 92df801fff..09fa280a25 100644 --- 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 @@ -1,18 +1,21 @@ 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 芋道源码 */ @Getter @AllArgsConstructor -public enum ImMessageTypeEnum { +public enum ImMessageTypeEnum implements IntArrayValuable { TEXT(1, "文本"), // 消息内容为普通文本 IMAGE(2, "图片"), // 消息内容为图片 URL 地址、尺寸、图片大小等信息 @@ -25,6 +28,7 @@ public enum ImMessageTypeEnum { NOTIFICATION(8, "通知"), // 主要用于群组、聊天室和超大群的事件通知,由服务端下发,客户端无法发送事件通知消息。通知类消息有在线、离线、漫游机制;没有通知栏提醒 ; + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ImMessageTypeEnum::getType).toArray(); /** * 类型 */ @@ -34,4 +38,8 @@ public enum ImMessageTypeEnum { */ 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-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 index 78649d1d4f..ed8c2dbd2c 100755 --- 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 @@ -1,6 +1,7 @@ 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; @@ -55,4 +56,7 @@ public class ImMessagePageReqVO extends PageParam { @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/ImMessageRespVO.java index e732c94e67..19e3886711 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/ImMessageRespVO.java @@ -1,8 +1,12 @@ 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 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; @@ -46,6 +50,7 @@ public class ImMessageRespVO { @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("消息类型") + @InEnum(ImMessageTypeEnum.class) private Integer contentType; @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED) @@ -64,4 +69,9 @@ public class ImMessageRespVO { @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/ImMessageSaveReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSaveReqVO.java index cea5573b6b..53d6f13d27 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageSaveReqVO.java +++ b/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 { @NotNull(message = "会话类型不能为空") private Integer conversationType; - @Schema(description = "会话标志", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "会话标志 conversation_no = a_b", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "会话标志不能为空") private String conversationNo; @@ -57,4 +57,7 @@ public class ImMessageSaveReqVO { @NotNull(message = "消息来源 100-用户发送;200-系统发送(一般是通知);不能为空") private Integer sendFrom; + @Schema(description = "消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "消息状态不能为空") + 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/dal/dataobject/message/ImMessageDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/message/ImMessageDO.java index 14e88c1cac..becf06be41 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/ImMessageDO.java @@ -73,4 +73,9 @@ public class ImMessageDO extends BaseDO { */ private Integer sendFrom; + /** + * 消息状态 1 发送中、2 发送成功、3 发送失败、4 已删除、5 已撤回 + */ + 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/service/message/ImMessageService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java index 6a53f613be..073f89d9d2 100755 --- 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 @@ -61,4 +61,12 @@ public interface ImMessageService { * @return id */ Long savePrivateMessage(ImSendMessage imSendMessage, Long fromUserId); + + /** + * 更新消息状态 + * + * @param messageId 消息id + * @param messageStatus 消息状态 + */ + void updateMessageStatus(Long messageId, 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/service/message/ImMessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java index 2110503516..8e08493e09 100755 --- 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 @@ -6,10 +6,12 @@ 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.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; @@ -74,22 +76,35 @@ public class ImMessageServiceImpl implements ImMessageService { @Override - public Long savePrivateMessage(ImSendMessage message, Long fromUserId) { + public Long savePrivateMessage(ImSendMessage message, Long senderId) { ImMessageSaveReqVO imMessageSaveReqVO = new ImMessageSaveReqVO(); imMessageSaveReqVO.setClientMessageId(message.getClientMessageId()); - imMessageSaveReqVO.setSenderId(fromUserId); + imMessageSaveReqVO.setSenderId(senderId); imMessageSaveReqVO.setReceiverId(message.getReceiverId()); //查询发送人昵称和发送人头像 - AdminUserRespDTO user = adminUserApi.getUser(fromUserId); + AdminUserRespDTO user = adminUserApi.getUser(senderId); imMessageSaveReqVO.setSenderNickname(user.getNickname()); imMessageSaveReqVO.setSenderAvatar(user.getAvatar()); imMessageSaveReqVO.setConversationType(message.getConversationType()); imMessageSaveReqVO.setContentType(message.getContentType()); - imMessageSaveReqVO.setConversationNo("1"); + imMessageSaveReqVO.setConversationNo(senderId + "_" + message.getReceiverId()); imMessageSaveReqVO.setContent(message.getContent()); //消息来源 100-用户发送;200-系统发送(一般是通知);不能为空 imMessageSaveReqVO.setSendFrom(100); + imMessageSaveReqVO.setSendTime(TimeUtil.now()); + imMessageSaveReqVO.setMessageStatus(ImMessageStatusEnum.SENDING.getStatus()); return createMessage(imMessageSaveReqVO); } + @Override + public void updateMessageStatus(Long messageId, Integer messageStatus) { + //校验 id 是否存在 + validateMessageExists(messageId); + //更新消息状态 + ImMessageDO imMessageDO = new ImMessageDO(); + imMessageDO.setId(messageId); + imMessageDO.setMessageStatus(messageStatus); + imMessageMapper.updateById(imMessageDO); + } + } \ 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 index 17bf9e66a6..7263eb67a3 100644 --- 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 @@ -3,25 +3,31 @@ 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.session.WebSocketSessionManager; 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.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.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; + /** - * WebSocket 示例:单发消息 + * WebSocket im * * @author 芋道源码 */ @Component +@Slf4j public class ImWebSocketMessageListener implements WebSocketMessageListener { @Resource @@ -34,6 +40,8 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener sessions = (List) webSocketSessionManager.getSessionList(UserTypeEnum.ADMIN.getValue(), message.getReceiverId()); + if (sessions.isEmpty()) { + //更新消息状态,为发送失败 + imMessageService.updateMessageStatus(messageId, ImMessageStatusEnum.FAILURE.getStatus()); + return; + } + //3.2发送 ImReceiveMessage toMessage = new ImReceiveMessage(); toMessage.setFromId(fromUserId); toMessage.setConversationType(ImConversationTypeEnum.PRIVATE.getType()); @@ -55,6 +71,9 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener