Commit d67362043e94f428ecc6f8b6d2f0929f97315bec
1 parent
29a3ad42
创建会话
Showing
8 changed files
with
145 additions
and
14 deletions
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/ImConversationController.java
| 1 | package cn.iocoder.yudao.module.im.controller.admin.conversation; | 1 | package cn.iocoder.yudao.module.im.controller.admin.conversation; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; | ||
| 7 | +import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationCreateReqVO; | ||
| 5 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; | 8 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; |
| 6 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationRespVO; | 9 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationRespVO; |
| 7 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; | 10 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; |
| @@ -75,4 +78,11 @@ public class ImConversationController { | @@ -75,4 +78,11 @@ public class ImConversationController { | ||
| 75 | return success(true); | 78 | return success(true); |
| 76 | } | 79 | } |
| 77 | 80 | ||
| 81 | + @PostMapping("/create") | ||
| 82 | + @Operation(summary = "创建会话") | ||
| 83 | + public CommonResult<ImConversationDO> createConversation(@Valid @RequestBody ImConversationCreateReqVO createReqVO) { | ||
| 84 | + ImConversationDO conversation = imConversationService.createConversation(getLoginUserId(), createReqVO); | ||
| 85 | + return success(conversation); | ||
| 86 | + } | ||
| 87 | + | ||
| 78 | } | 88 | } |
| 79 | \ No newline at end of file | 89 | \ No newline at end of file |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/conversation/vo/ImConversationCreateReqVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.im.controller.admin.conversation.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 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - 会话最后已读时间 Request VO") | ||
| 12 | +@Data | ||
| 13 | +public class ImConversationCreateReqVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "聊天对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 16 | + private Long targetId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 19 | + @InEnum(value = ImConversationTypeEnum.class, message = "会话类型必须是 {value}") | ||
| 20 | + private Integer type; | ||
| 21 | + | ||
| 22 | +} | ||
| 0 | \ No newline at end of file | 23 | \ No newline at end of file |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationService.java
| 1 | package cn.iocoder.yudao.module.im.service.conversation; | 1 | package cn.iocoder.yudao.module.im.service.conversation; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationCreateReqVO; | ||
| 3 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; | 4 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; |
| 4 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; | 5 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; |
| 5 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; | 6 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| @@ -36,4 +37,6 @@ public interface ImConversationService { | @@ -36,4 +37,6 @@ public interface ImConversationService { | ||
| 36 | */ | 37 | */ |
| 37 | void updateLastReadTime(Long loginUserId, ImConversationUpdateLastReadTimeReqVO updateReqVO); | 38 | void updateLastReadTime(Long loginUserId, ImConversationUpdateLastReadTimeReqVO updateReqVO); |
| 38 | 39 | ||
| 40 | + ImConversationDO createConversation(Long loginUserId, ImConversationCreateReqVO createReqVO); | ||
| 41 | + | ||
| 39 | } | 42 | } |
| 40 | \ No newline at end of file | 43 | \ No newline at end of file |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java
| 1 | package cn.iocoder.yudao.module.im.service.conversation; | 1 | package cn.iocoder.yudao.module.im.service.conversation; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; | ||
| 5 | +import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationCreateReqVO; | ||
| 3 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdateLastReadTimeReqVO; |
| 4 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; | 7 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationUpdatePinnedReqVO; |
| 5 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; | 8 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| @@ -13,6 +16,8 @@ import org.springframework.validation.annotation.Validated; | @@ -13,6 +16,8 @@ import org.springframework.validation.annotation.Validated; | ||
| 13 | 16 | ||
| 14 | import java.util.List; | 17 | import java.util.List; |
| 15 | 18 | ||
| 19 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 20 | + | ||
| 16 | /** | 21 | /** |
| 17 | * IM 会话 Service 实现类 | 22 | * IM 会话 Service 实现类 |
| 18 | * | 23 | * |
| @@ -21,17 +26,24 @@ import java.util.List; | @@ -21,17 +26,24 @@ import java.util.List; | ||
| 21 | @Service | 26 | @Service |
| 22 | @Validated | 27 | @Validated |
| 23 | public class ImConversationServiceImpl implements ImConversationService { | 28 | public class ImConversationServiceImpl implements ImConversationService { |
| 29 | + private final String IM_CONVERSATION_ADD = "im-conversation-add"; | ||
| 24 | 30 | ||
| 25 | @Resource | 31 | @Resource |
| 26 | private ImConversationMapper imConversationMapper; | 32 | private ImConversationMapper imConversationMapper; |
| 27 | 33 | ||
| 34 | + @Resource | ||
| 35 | + WebSocketMessageSender webSocketMessageSender; | ||
| 36 | + | ||
| 28 | @Override | 37 | @Override |
| 29 | public List<ImConversationDO> getConversationList(Long loginUserId) { | 38 | public List<ImConversationDO> getConversationList(Long loginUserId) { |
| 30 | // 根据loginUserId判断targetId, 自己不能做targetId | 39 | // 根据loginUserId判断targetId, 自己不能做targetId |
| 31 | - // 如何loginUserId和targetId相同,则需要调换userId和targetId | 40 | + // 如果loginUserId和targetId相同,则需要调换userId和targetId |
| 32 | List<ImConversationDO> conversationList = imConversationMapper.selectList(); | 41 | List<ImConversationDO> conversationList = imConversationMapper.selectList(); |
| 42 | + | ||
| 43 | + // 过滤和自己无关的会话 | ||
| 44 | + List<ImConversationDO> conversationFilteredList = conversationList.stream().filter(item -> loginUserId.equals(item.getUserId()) || loginUserId.equals(item.getTargetId())).toList(); | ||
| 33 | // 遍历判断loginUserId和targetId相同,相同则将userId设置为targetId, targetId设置为userId | 45 | // 遍历判断loginUserId和targetId相同,相同则将userId设置为targetId, targetId设置为userId |
| 34 | - conversationList.forEach(item -> { | 46 | + conversationFilteredList.forEach(item -> { |
| 35 | if (item.getTargetId().equals(loginUserId)) { | 47 | if (item.getTargetId().equals(loginUserId)) { |
| 36 | Long targetId = item.getTargetId(); | 48 | Long targetId = item.getTargetId(); |
| 37 | Long userId = item.getUserId(); | 49 | Long userId = item.getUserId(); |
| @@ -39,7 +51,7 @@ public class ImConversationServiceImpl implements ImConversationService { | @@ -39,7 +51,7 @@ public class ImConversationServiceImpl implements ImConversationService { | ||
| 39 | item.setUserId(targetId); | 51 | item.setUserId(targetId); |
| 40 | } | 52 | } |
| 41 | }); | 53 | }); |
| 42 | - return conversationList; | 54 | + return conversationFilteredList; |
| 43 | } | 55 | } |
| 44 | 56 | ||
| 45 | @Override | 57 | @Override |
| @@ -84,4 +96,29 @@ public class ImConversationServiceImpl implements ImConversationService { | @@ -84,4 +96,29 @@ public class ImConversationServiceImpl implements ImConversationService { | ||
| 84 | // 4. 做对应更新的 notify 推送 | 96 | // 4. 做对应更新的 notify 推送 |
| 85 | } | 97 | } |
| 86 | 98 | ||
| 99 | + @Override | ||
| 100 | + public ImConversationDO createConversation(Long loginUserId, ImConversationCreateReqVO createReqVO) { | ||
| 101 | + // 1. 获得会话编号 | ||
| 102 | + String no = ImConversationTypeEnum.generateConversationNo(loginUserId, createReqVO.getTargetId(), createReqVO.getType()); | ||
| 103 | + // 2. 查询会话 | ||
| 104 | + ImConversationDO conversation = imConversationMapper.selectByNo(no); | ||
| 105 | + | ||
| 106 | + if (conversation == null) { | ||
| 107 | + // 2.1. 不存在,则插入 | ||
| 108 | + conversation = insertConversation(no, loginUserId, createReqVO.getTargetId(), createReqVO.getType()); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + // 发送打开会话的通知,并推送会话实体 | ||
| 112 | + // 给自己发送创建会话成功的通知 | ||
| 113 | + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), getLoginUserId(), | ||
| 114 | + IM_CONVERSATION_ADD, conversation); | ||
| 115 | + | ||
| 116 | + // 给接受者发送创建会话的通知 | ||
| 117 | + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), createReqVO.getTargetId(), | ||
| 118 | + IM_CONVERSATION_ADD, conversation); | ||
| 119 | + | ||
| 120 | + return conversation; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + | ||
| 87 | } | 124 | } |
| 88 | \ No newline at end of file | 125 | \ 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
| @@ -53,19 +53,24 @@ public class ImMessageServiceImpl implements ImMessageService { | @@ -53,19 +53,24 @@ public class ImMessageServiceImpl implements ImMessageService { | ||
| 53 | public List<ImMessageDO> getMessageList(ImMessageListReqVO listReqVO) { | 53 | public List<ImMessageDO> getMessageList(ImMessageListReqVO listReqVO) { |
| 54 | 54 | ||
| 55 | // 1. 获得会话编号 | 55 | // 1. 获得会话编号 |
| 56 | - String no = ""; | ||
| 57 | Long loginUserId = getLoginUserId(); | 56 | Long loginUserId = getLoginUserId(); |
| 58 | - if (Objects.equals(loginUserId, listReqVO.getUserId())) { | ||
| 59 | - no = generateConversationNo(loginUserId, listReqVO.getReceiverId(), listReqVO.getConversationType()); | ||
| 60 | - } else { | ||
| 61 | - no = generateConversationNo(listReqVO.getReceiverId(),loginUserId , listReqVO.getConversationType()); | ||
| 62 | - } | 57 | + String no1 = generateConversationNo(loginUserId, listReqVO.getReceiverId(), listReqVO.getConversationType()); |
| 58 | + String no2 = generateConversationNo(listReqVO.getReceiverId(),loginUserId, listReqVO.getConversationType()); | ||
| 63 | 59 | ||
| 64 | // 2. 查询历史消息 | 60 | // 2. 查询历史消息 |
| 65 | ImMessageDO message = new ImMessageDO() | 61 | ImMessageDO message = new ImMessageDO() |
| 66 | .setSendTime(listReqVO.getSendTime()) | 62 | .setSendTime(listReqVO.getSendTime()) |
| 67 | - .setConversationNo(no); | ||
| 68 | - return imMessageMapper.selectMessageList(message); | 63 | + .setConversationNo(no1); |
| 64 | + List<ImMessageDO> list = imMessageMapper.selectMessageList(message); | ||
| 65 | + | ||
| 66 | + if (!list.isEmpty()) { | ||
| 67 | + return list; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + message.setConversationNo(no2); | ||
| 71 | + list = imMessageMapper.selectMessageList(message); | ||
| 72 | + | ||
| 73 | + return list; | ||
| 69 | } | 74 | } |
| 70 | 75 | ||
| 71 | @Override | 76 | @Override |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java
| @@ -27,9 +27,7 @@ import org.springframework.web.bind.annotation.*; | @@ -27,9 +27,7 @@ import org.springframework.web.bind.annotation.*; | ||
| 27 | import org.springframework.web.multipart.MultipartFile; | 27 | import org.springframework.web.multipart.MultipartFile; |
| 28 | 28 | ||
| 29 | import java.io.IOException; | 29 | import java.io.IOException; |
| 30 | -import java.util.Arrays; | ||
| 31 | -import java.util.List; | ||
| 32 | -import java.util.Map; | 30 | +import java.util.*; |
| 33 | 31 | ||
| 34 | import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; | 32 | import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; |
| 35 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 33 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -103,6 +101,37 @@ public class UserController { | @@ -103,6 +101,37 @@ public class UserController { | ||
| 103 | pageResult.getTotal())); | 101 | pageResult.getTotal())); |
| 104 | } | 102 | } |
| 105 | 103 | ||
| 104 | + @GetMapping("/all") | ||
| 105 | + @Operation(summary = "获得所有用户列表") | ||
| 106 | + @PreAuthorize("@ss.hasPermission('system:user:list')") | ||
| 107 | + public CommonResult<List<UserRespVO>> getUserAll() { | ||
| 108 | + List<AdminUserDO> result = userService.getUserListAll(); | ||
| 109 | + if (CollUtil.isEmpty(result)) { | ||
| 110 | + return success(null); | ||
| 111 | + } | ||
| 112 | + // 拼接数据 | ||
| 113 | + Map<Long, DeptDO> deptMap = deptService.getDeptMap( | ||
| 114 | + convertList(result, AdminUserDO::getDeptId)); | ||
| 115 | + return success(UserConvert.INSTANCE.convertList(result, deptMap)); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + @GetMapping("/listByDept") | ||
| 119 | + @Operation(summary = "获得部门用户列表") | ||
| 120 | + @PreAuthorize("@ss.hasPermission('system:user:list')") | ||
| 121 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||
| 122 | + public CommonResult<List<UserRespVO>> getDeptUsers(@RequestParam("id") Long id) { | ||
| 123 | + List<Long> ids = new ArrayList<>(); | ||
| 124 | + ids.add(id); | ||
| 125 | + List<AdminUserDO> result = userService.getDeptUsers(ids); | ||
| 126 | + if (CollUtil.isEmpty(result)) { | ||
| 127 | + return success(null); | ||
| 128 | + } | ||
| 129 | + // 拼接数据 | ||
| 130 | + Map<Long, DeptDO> deptMap = deptService.getDeptMap( | ||
| 131 | + convertList(result, AdminUserDO::getDeptId)); | ||
| 132 | + return success(UserConvert.INSTANCE.convertList(result, deptMap)); | ||
| 133 | + } | ||
| 134 | + | ||
| 106 | @GetMapping({"/list-all-simple", "/simple-list"}) | 135 | @GetMapping({"/list-all-simple", "/simple-list"}) |
| 107 | @Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项") | 136 | @Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项") |
| 108 | public CommonResult<List<UserSimpleRespVO>> getSimpleUserList() { | 137 | public CommonResult<List<UserSimpleRespVO>> getSimpleUserList() { |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
| @@ -160,6 +160,14 @@ public interface AdminUserService { | @@ -160,6 +160,14 @@ public interface AdminUserService { | ||
| 160 | */ | 160 | */ |
| 161 | List<AdminUserDO> getUserList(Collection<Long> ids); | 161 | List<AdminUserDO> getUserList(Collection<Long> ids); |
| 162 | 162 | ||
| 163 | + | ||
| 164 | + /** | ||
| 165 | + * 获得全部用户列表 | ||
| 166 | + * | ||
| 167 | + * @return 用户列表 | ||
| 168 | + */ | ||
| 169 | + List<AdminUserDO> getUserListAll(); | ||
| 170 | + | ||
| 163 | /** | 171 | /** |
| 164 | * 校验用户们是否有效。如下情况,视为无效: | 172 | * 校验用户们是否有效。如下情况,视为无效: |
| 165 | * 1. 用户编号不存在 | 173 | * 1. 用户编号不存在 |
| @@ -208,6 +216,13 @@ public interface AdminUserService { | @@ -208,6 +216,13 @@ public interface AdminUserService { | ||
| 208 | List<AdminUserDO> getUserListByStatus(Integer status); | 216 | List<AdminUserDO> getUserListByStatus(Integer status); |
| 209 | 217 | ||
| 210 | /** | 218 | /** |
| 219 | + * 获得指定部门的用户 | ||
| 220 | + * @param deptIds | ||
| 221 | + * @return | ||
| 222 | + */ | ||
| 223 | + List<AdminUserDO> getDeptUsers(Collection<Long> deptIds); | ||
| 224 | + | ||
| 225 | + /** | ||
| 211 | * 判断密码是否匹配 | 226 | * 判断密码是否匹配 |
| 212 | * | 227 | * |
| 213 | * @param rawPassword 未加密的密码 | 228 | * @param rawPassword 未加密的密码 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
| @@ -308,6 +308,11 @@ public class AdminUserServiceImpl implements AdminUserService { | @@ -308,6 +308,11 @@ public class AdminUserServiceImpl implements AdminUserService { | ||
| 308 | return userMapper.selectBatchIds(ids); | 308 | return userMapper.selectBatchIds(ids); |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | + public List<AdminUserDO> getUserListAll() { | ||
| 312 | + return userMapper.selectList(); | ||
| 313 | + } | ||
| 314 | + | ||
| 315 | + | ||
| 311 | @Override | 316 | @Override |
| 312 | public void validateUserList(Collection<Long> ids) { | 317 | public void validateUserList(Collection<Long> ids) { |
| 313 | if (CollUtil.isEmpty(ids)) { | 318 | if (CollUtil.isEmpty(ids)) { |
| @@ -510,6 +515,11 @@ public class AdminUserServiceImpl implements AdminUserService { | @@ -510,6 +515,11 @@ public class AdminUserServiceImpl implements AdminUserService { | ||
| 510 | } | 515 | } |
| 511 | 516 | ||
| 512 | @Override | 517 | @Override |
| 518 | + public List<AdminUserDO> getDeptUsers(Collection<Long> deptIds) { | ||
| 519 | + return userMapper.selectListByDeptIds(deptIds); | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + @Override | ||
| 513 | public boolean isPasswordMatch(String rawPassword, String encodedPassword) { | 523 | public boolean isPasswordMatch(String rawPassword, String encodedPassword) { |
| 514 | return passwordEncoder.matches(rawPassword, encodedPassword); | 524 | return passwordEncoder.matches(rawPassword, encodedPassword); |
| 515 | } | 525 | } |