Commit 788c24dff4f57baf0743f03519f2f849e3a8c9e1
1 parent
b540f8d4
会话和消息处理
Showing
10 changed files
with
152 additions
and
15 deletions
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationController.java
| ... | ... | @@ -5,8 +5,14 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | 5 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationRespVO; |
| 7 | 7 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; |
| 8 | +import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListByNoReqVO; | |
| 8 | 9 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| 10 | +import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; | |
| 11 | +import cn.iocoder.yudao.module.im.enums.message.ImMessageContentTypeEnum; | |
| 9 | 12 | import cn.iocoder.yudao.module.im.service.conversation.ImConversationService; |
| 13 | +import cn.iocoder.yudao.module.im.service.message.ImMessageService; | |
| 14 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 15 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 10 | 16 | import io.swagger.v3.oas.annotations.Operation; |
| 11 | 17 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 12 | 18 | import jakarta.annotation.Resource; |
| ... | ... | @@ -15,6 +21,7 @@ import org.springframework.validation.annotation.Validated; |
| 15 | 21 | import org.springframework.web.bind.annotation.*; |
| 16 | 22 | |
| 17 | 23 | import java.util.List; |
| 24 | +import java.util.Objects; | |
| 18 | 25 | |
| 19 | 26 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 20 | 27 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| ... | ... | @@ -28,11 +35,50 @@ public class ImConversationController { |
| 28 | 35 | @Resource |
| 29 | 36 | private ImConversationService imConversationService; |
| 30 | 37 | |
| 38 | + @Resource | |
| 39 | + private ImMessageService imMessageService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + AdminUserApi adminUserApi; | |
| 43 | + | |
| 31 | 44 | @GetMapping("/list") |
| 32 | 45 | @Operation(summary = "获得用户的会话列表") |
| 33 | 46 | public CommonResult<List<ImConversationRespVO>> getConversationList() { |
| 34 | - List<ImConversationDO> conversationList = imConversationService.getConversationList(); | |
| 35 | - return success(BeanUtils.toBean(conversationList, ImConversationRespVO.class)); | |
| 47 | + List<ImConversationDO> conversationList = imConversationService.getConversationList(getLoginUserId()); | |
| 48 | + List<ImConversationRespVO> imConversationRespVOList = BeanUtils.toBean(conversationList, ImConversationRespVO.class); | |
| 49 | + imConversationRespVOList.forEach(item -> { | |
| 50 | + // 处理个人图像和昵称 | |
| 51 | + Long receiverId = item.getTargetId(); | |
| 52 | + AdminUserRespDTO receiverUser = adminUserApi.getUser(receiverId); | |
| 53 | + if (receiverUser != null) { | |
| 54 | + item.setAvatar(receiverUser.getAvatar()); | |
| 55 | + item.setNickname(receiverUser.getNickname()); | |
| 56 | + } | |
| 57 | + | |
| 58 | + // 处理未读消息条数【TODO:】 | |
| 59 | + | |
| 60 | + | |
| 61 | + // 处理最后一条消息描述 | |
| 62 | + ImMessageListByNoReqVO imMessageListByNoReqVO = new ImMessageListByNoReqVO(); | |
| 63 | + imMessageListByNoReqVO.setConversationNo(item.getNo()); | |
| 64 | + List<ImMessageDO> listMessage = imMessageService.getMessageListByConversationNo(imMessageListByNoReqVO); | |
| 65 | + | |
| 66 | + if (!listMessage.isEmpty()) { | |
| 67 | + ImMessageDO lastMessage = listMessage.get(listMessage.size() - 1); | |
| 68 | + if (lastMessage != null) { | |
| 69 | + if (Objects.equals(lastMessage.getContentType(), ImMessageContentTypeEnum.TEXT.getType())) { | |
| 70 | + item.setLastMessageDescription(lastMessage.getContent()); | |
| 71 | + } else if (Objects.equals(lastMessage.getContentType(), ImMessageContentTypeEnum.PICTURE.getType())) { | |
| 72 | + item.setLastMessageDescription("[图片]"); | |
| 73 | + } else { | |
| 74 | + item.setLastMessageDescription("[未知类型]"); | |
| 75 | + } | |
| 76 | + } | |
| 77 | + } | |
| 78 | + | |
| 79 | + | |
| 80 | + }); | |
| 81 | + return success(imConversationRespVOList); | |
| 36 | 82 | } |
| 37 | 83 | |
| 38 | 84 | @PostMapping("/update-pinned") | ... | ... |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationRespVO.java
| ... | ... | @@ -35,4 +35,16 @@ public class ImConversationRespVO { |
| 35 | 35 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 36 | 36 | private LocalDateTime createTime; |
| 37 | 37 | |
| 38 | + @Schema(description = "会话接受者头像", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 39 | + private String avatar; | |
| 40 | + | |
| 41 | + @Schema(description = "会话接受者昵称", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 42 | + private String nickname; | |
| 43 | + | |
| 44 | + @Schema(description = "最后一条消息的描述", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 45 | + private String lastMessageDescription; | |
| 46 | + | |
| 47 | + @Schema(description = "未读消息条数", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 48 | + private String unreadMessagesCount; | |
| 49 | + | |
| 38 | 50 | } |
| 39 | 51 | \ No newline at end of file | ... | ... |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImMessageController.java
| ... | ... | @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.im.controller.admin.message; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | -import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListReqVO; | |
| 6 | -import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageRespVO; | |
| 7 | -import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendReqVO; | |
| 8 | -import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendRespVO; | |
| 5 | +import cn.iocoder.yudao.module.im.controller.admin.message.vo.*; | |
| 9 | 6 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; |
| 10 | 7 | import cn.iocoder.yudao.module.im.service.message.ImMessageService; |
| 11 | 8 | import io.swagger.v3.oas.annotations.Operation; |
| ... | ... | @@ -50,7 +47,14 @@ public class ImMessageController { |
| 50 | 47 | @GetMapping("/list") |
| 51 | 48 | @Operation(summary = "消息列表-根据接收人和发送时间进行分页查询") |
| 52 | 49 | public CommonResult<List<ImMessageRespVO>> getMessageList(@Valid ImMessageListReqVO listReqVO) { |
| 53 | - List<ImMessageDO> messagePage = imMessageService.getMessageList(getLoginUserId(), listReqVO); | |
| 50 | + List<ImMessageDO> messagePage = imMessageService.getMessageList(listReqVO); | |
| 51 | + return success(BeanUtils.toBean(messagePage, ImMessageRespVO.class)); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @GetMapping("/listByNo") | |
| 55 | + @Operation(summary = "消息列表-根据接收人和发送时间进行分页查询") | |
| 56 | + public CommonResult<List<ImMessageRespVO>> getMessageListByNo(@Valid ImMessageListByNoReqVO listReqVO) { | |
| 57 | + List<ImMessageDO> messagePage = imMessageService.getMessageListByConversationNo(listReqVO); | |
| 54 | 58 | return success(BeanUtils.toBean(messagePage, ImMessageRespVO.class)); |
| 55 | 59 | } |
| 56 | 60 | ... | ... |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/vo/ImMessageListByNoReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.im.controller.admin.message.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 4 | +import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import jakarta.validation.constraints.NotNull; | |
| 7 | +import lombok.Data; | |
| 8 | +import lombok.ToString; | |
| 9 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 10 | + | |
| 11 | +import java.time.LocalDateTime; | |
| 12 | + | |
| 13 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; | |
| 14 | + | |
| 15 | +@Schema(description = "管理后台 - 消息列表 Request VO") | |
| 16 | +@Data | |
| 17 | +@ToString(callSuper = true) | |
| 18 | +public class ImMessageListByNoReqVO { | |
| 19 | + | |
| 20 | + @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-03-27 12:00:00") | |
| 21 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) | |
| 22 | + private LocalDateTime sendTime; | |
| 23 | + | |
| 24 | + @Schema(description = "会话编号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494") | |
| 25 | + @NotNull(message = "会话编号不能为空") | |
| 26 | + private String conversationNo ; | |
| 27 | + | |
| 28 | +} | |
| 0 | 29 | \ 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/ImMessageListReqVO.java
| ... | ... | @@ -21,6 +21,10 @@ public class ImMessageListReqVO { |
| 21 | 21 | @NotNull(message = "接收人编号不能为空") |
| 22 | 22 | private Long receiverId; |
| 23 | 23 | |
| 24 | + @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494") | |
| 25 | + @NotNull(message = "发送人编号不能为空") | |
| 26 | + private Long senderId; | |
| 27 | + | |
| 24 | 28 | @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 25 | 29 | @InEnum(value = ImConversationTypeEnum.class,message = "会话类型必须是 {value}") |
| 26 | 30 | @NotNull(message = "会话类型不能为空") |
| ... | ... | @@ -30,4 +34,8 @@ public class ImMessageListReqVO { |
| 30 | 34 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) |
| 31 | 35 | private LocalDateTime sendTime; |
| 32 | 36 | |
| 37 | + @Schema(description = "会话编号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32494") | |
| 38 | + @NotNull(message = "会话编号不能为空") | |
| 39 | + private String conversationNo ; | |
| 40 | + | |
| 33 | 41 | } |
| 34 | 42 | \ 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/ImMessageSendReqVO.java
| ... | ... | @@ -24,6 +24,10 @@ public class ImMessageSendReqVO { |
| 24 | 24 | @NotNull(message = "会话类型不能为空") |
| 25 | 25 | private Integer conversationType; |
| 26 | 26 | |
| 27 | + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 28 | + @NotNull(message = "会话编号不能为空") | |
| 29 | + private String conversationNo; | |
| 30 | + | |
| 27 | 31 | @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 28 | 32 | @InEnum(ImMessageContentTypeEnum.class) |
| 29 | 33 | @NotNull(message = "消息类型不能为空") | ... | ... |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationService.java
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java
| ... | ... | @@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversatio |
| 5 | 5 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| 6 | 6 | import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper; |
| 7 | 7 | import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum; |
| 8 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 9 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 8 | 10 | import jakarta.annotation.Resource; |
| 9 | 11 | import org.springframework.stereotype.Service; |
| 10 | 12 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -24,8 +26,20 @@ public class ImConversationServiceImpl implements ImConversationService { |
| 24 | 26 | private ImConversationMapper imConversationMapper; |
| 25 | 27 | |
| 26 | 28 | @Override |
| 27 | - public List<ImConversationDO> getConversationList() { | |
| 28 | - return imConversationMapper.selectList(); | |
| 29 | + public List<ImConversationDO> getConversationList(Long loginUserId) { | |
| 30 | + // 根据loginUserId判断targetId, 自己不能做targetId | |
| 31 | + // 如何loginUserId和targetId相同,则需要调换userId和targetId | |
| 32 | + List<ImConversationDO> conversationList = imConversationMapper.selectList(); | |
| 33 | + // 遍历判断loginUserId和targetId相同,相同则将userId设置为targetId, targetId设置为userId | |
| 34 | + conversationList.forEach(item -> { | |
| 35 | + if (item.getTargetId().equals(loginUserId)) { | |
| 36 | + Long targetId = item.getTargetId(); | |
| 37 | + Long userId = item.getUserId(); | |
| 38 | + item.setTargetId(userId); | |
| 39 | + item.setUserId(targetId); | |
| 40 | + } | |
| 41 | + }); | |
| 42 | + return conversationList; | |
| 29 | 43 | } |
| 30 | 44 | |
| 31 | 45 | @Override | ... | ... |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java
| 1 | 1 | package cn.iocoder.yudao.module.im.service.message; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListByNoReqVO; | |
| 3 | 4 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListReqVO; |
| 4 | 5 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendReqVO; |
| 5 | 6 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; |
| ... | ... | @@ -16,11 +17,19 @@ public interface ImMessageService { |
| 16 | 17 | /** |
| 17 | 18 | * 获得历史消息 |
| 18 | 19 | * |
| 19 | - * @param loginUserId 登录用户编号 | |
| 20 | 20 | * @param listReqVO 分页查询 |
| 21 | 21 | * @return 消息分页 |
| 22 | 22 | */ |
| 23 | - List<ImMessageDO> getMessageList(Long loginUserId, ImMessageListReqVO listReqVO); | |
| 23 | + List<ImMessageDO> getMessageList(ImMessageListReqVO listReqVO); | |
| 24 | + | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 获得历史消息 | |
| 28 | + * | |
| 29 | + * @param listReqVO 分页查询 | |
| 30 | + * @return 消息分页 | |
| 31 | + */ | |
| 32 | + List<ImMessageDO> getMessageListByConversationNo(ImMessageListByNoReqVO listReqVO); | |
| 24 | 33 | |
| 25 | 34 | /** |
| 26 | 35 | * 拉取消息-大于 seq 的消息 | ... | ... |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.im.service.message; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | 4 | import cn.hutool.core.collection.CollUtil; |
| 5 | +import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListByNoReqVO; | |
| 5 | 6 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageListReqVO; |
| 6 | 7 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSendReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; |
| ... | ... | @@ -46,9 +47,9 @@ public class ImMessageServiceImpl implements ImMessageService { |
| 46 | 47 | private ImGroupMemberService imGroupMemberService; |
| 47 | 48 | |
| 48 | 49 | @Override |
| 49 | - public List<ImMessageDO> getMessageList(Long loginUserId, ImMessageListReqVO listReqVO) { | |
| 50 | + public List<ImMessageDO> getMessageList(ImMessageListReqVO listReqVO) { | |
| 50 | 51 | // 1. 获得会话编号 |
| 51 | - String no = ImConversationTypeEnum.generateConversationNo(loginUserId, listReqVO.getReceiverId(), listReqVO.getConversationType()); | |
| 52 | + String no = ImConversationTypeEnum.generateConversationNo(listReqVO.getSenderId(), listReqVO.getReceiverId(), listReqVO.getConversationType()); | |
| 52 | 53 | // 2. 查询历史消息 |
| 53 | 54 | ImMessageDO message = new ImMessageDO() |
| 54 | 55 | .setSendTime(listReqVO.getSendTime()) |
| ... | ... | @@ -57,6 +58,17 @@ public class ImMessageServiceImpl implements ImMessageService { |
| 57 | 58 | } |
| 58 | 59 | |
| 59 | 60 | @Override |
| 61 | + public List<ImMessageDO> getMessageListByConversationNo(ImMessageListByNoReqVO listReqVO) { | |
| 62 | + | |
| 63 | + // 1. 查询历史消息 | |
| 64 | + ImMessageDO message = new ImMessageDO() | |
| 65 | + .setSendTime(listReqVO.getSendTime()) | |
| 66 | + .setConversationNo(listReqVO.getConversationNo()); | |
| 67 | + return imMessageMapper.selectMessageList(message); | |
| 68 | + } | |
| 69 | + | |
| 70 | + | |
| 71 | + @Override | |
| 60 | 72 | public List<ImMessageDO> pullMessageList(Long userId, Long sequence, Integer size) { |
| 61 | 73 | List<Long> messageIds = imInboxService.selectMessageIdsByUserIdAndSequence(userId, sequence, size); |
| 62 | 74 | if (CollUtil.isEmpty(messageIds)) { |
| ... | ... | @@ -84,7 +96,7 @@ public class ImMessageServiceImpl implements ImMessageService { |
| 84 | 96 | ImMessageDO imMessageDO = BeanUtil.copyProperties(message, ImMessageDO.class) |
| 85 | 97 | .setSenderNickname(fromUser.getNickname()).setSenderAvatar(fromUser.getAvatar()) |
| 86 | 98 | .setSenderId(fromUserId) |
| 87 | - .setConversationNo(ImConversationTypeEnum.generateConversationNo(fromUserId, message.getReceiverId(), message.getConversationType())) | |
| 99 | + .setConversationNo(message.getConversationNo()) | |
| 88 | 100 | .setSendFrom(ImMessageSourceEnum.USER_SEND.getSource()) |
| 89 | 101 | .setMessageStatus(ImMessageStatusEnum.SENDING.getStatus()) |
| 90 | 102 | .setSendTime(LocalDateTime.now()); | ... | ... |