Commit 04123e5987b9f873301e48c1a9e649a3fb445b2e
1 parent
354fe6fc
新增:获取会话列表,获取消息列表
Showing
7 changed files
with
158 additions
and
127 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.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 5 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||
| 8 | -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||
| 9 | -import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO; | ||
| 10 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationRespVO; | 5 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationRespVO; |
| 11 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO; |
| 12 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; | 7 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| 13 | import cn.iocoder.yudao.module.im.service.conversation.ImConversationService; | 8 | import cn.iocoder.yudao.module.im.service.conversation.ImConversationService; |
| 14 | import io.swagger.v3.oas.annotations.Operation; | 9 | import io.swagger.v3.oas.annotations.Operation; |
| 15 | -import io.swagger.v3.oas.annotations.Parameter; | ||
| 16 | import io.swagger.v3.oas.annotations.tags.Tag; | 10 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 17 | import jakarta.annotation.Resource; | 11 | import jakarta.annotation.Resource; |
| 18 | -import jakarta.servlet.http.HttpServletResponse; | ||
| 19 | import jakarta.validation.Valid; | 12 | import jakarta.validation.Valid; |
| 20 | import org.springframework.security.access.prepost.PreAuthorize; | 13 | import org.springframework.security.access.prepost.PreAuthorize; |
| 21 | import org.springframework.validation.annotation.Validated; | 14 | import org.springframework.validation.annotation.Validated; |
| 22 | import org.springframework.web.bind.annotation.*; | 15 | import org.springframework.web.bind.annotation.*; |
| 23 | 16 | ||
| 24 | -import java.io.IOException; | ||
| 25 | import java.util.List; | 17 | import java.util.List; |
| 26 | 18 | ||
| 27 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 19 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 28 | -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | ||
| 29 | 20 | ||
| 30 | @Tag(name = "管理后台 - 会话") | 21 | @Tag(name = "管理后台 - 会话") |
| 31 | @RestController | 22 | @RestController |
| @@ -36,58 +27,30 @@ public class ImConversationController { | @@ -36,58 +27,30 @@ public class ImConversationController { | ||
| 36 | @Resource | 27 | @Resource |
| 37 | private ImConversationService imConversationService; | 28 | private ImConversationService imConversationService; |
| 38 | 29 | ||
| 39 | - @PostMapping("/create") | ||
| 40 | - @Operation(summary = "创建会话") | ||
| 41 | - @PreAuthorize("@ss.hasPermission('im:conversation:create')") | ||
| 42 | - public CommonResult<Long> createConversation(@Valid @RequestBody ImConversationSaveReqVO createReqVO) { | ||
| 43 | - return success(imConversationService.createConversation(createReqVO)); | 30 | + @GetMapping("/get-conversation") |
| 31 | + @Operation(summary = "获得用户的会话列表") | ||
| 32 | + @PreAuthorize("hasAuthority('im:conversation:query')") | ||
| 33 | + public CommonResult<List<ImConversationRespVO>> getConversationList() { | ||
| 34 | + List<ImConversationDO> conversationList = imConversationService.getConversationList(); | ||
| 35 | + return success(BeanUtils.toBean(conversationList, ImConversationRespVO.class)); | ||
| 44 | } | 36 | } |
| 45 | 37 | ||
| 46 | - @PutMapping("/update") | ||
| 47 | - @Operation(summary = "更新会话") | ||
| 48 | - @PreAuthorize("@ss.hasPermission('im:conversation:update')") | ||
| 49 | - public CommonResult<Boolean> updateConversation(@Valid @RequestBody ImConversationSaveReqVO updateReqVO) { | ||
| 50 | - imConversationService.updateConversation(updateReqVO); | ||
| 51 | - return success(true); | ||
| 52 | - } | ||
| 53 | 38 | ||
| 54 | - @DeleteMapping("/delete") | ||
| 55 | - @Operation(summary = "删除会话") | ||
| 56 | - @Parameter(name = "id", description = "编号", required = true) | ||
| 57 | - @PreAuthorize("@ss.hasPermission('im:conversation:delete')") | ||
| 58 | - public CommonResult<Boolean> deleteConversation(@RequestParam("id") Long id) { | ||
| 59 | - imConversationService.deleteConversation(id); | 39 | + @PostMapping("/update-top") |
| 40 | + @Operation(summary = "置顶会话") | ||
| 41 | + @PreAuthorize("hasAuthority('im:conversation:update')") | ||
| 42 | + public CommonResult<Boolean> updateTop(@Valid @RequestBody ImConversationSaveReqVO updateReqVO) { | ||
| 43 | + imConversationService.updateTop(updateReqVO); | ||
| 60 | return success(true); | 44 | return success(true); |
| 61 | } | 45 | } |
| 62 | 46 | ||
| 63 | - @GetMapping("/get") | ||
| 64 | - @Operation(summary = "获得会话") | ||
| 65 | - @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||
| 66 | - @PreAuthorize("@ss.hasPermission('im:conversation:query')") | ||
| 67 | - public CommonResult<ImConversationRespVO> getConversation(@RequestParam("id") Long id) { | ||
| 68 | - ImConversationDO conversation = imConversationService.getConversation(id); | ||
| 69 | - return success(BeanUtils.toBean(conversation, ImConversationRespVO.class)); | ||
| 70 | - } | ||
| 71 | - | ||
| 72 | - @GetMapping("/page") | ||
| 73 | - @Operation(summary = "获得会话分页") | ||
| 74 | - @PreAuthorize("@ss.hasPermission('im:conversation:query')") | ||
| 75 | - public CommonResult<PageResult<ImConversationRespVO>> getConversationPage(@Valid ImConversationPageReqVO pageReqVO) { | ||
| 76 | - PageResult<ImConversationDO> pageResult = imConversationService.getConversationPage(pageReqVO); | ||
| 77 | - return success(BeanUtils.toBean(pageResult, ImConversationRespVO.class)); | ||
| 78 | - } | ||
| 79 | 47 | ||
| 80 | - @GetMapping("/export-excel") | ||
| 81 | - @Operation(summary = "导出会话 Excel") | ||
| 82 | - @PreAuthorize("@ss.hasPermission('im:conversation:export')") | ||
| 83 | - @OperateLog(type = EXPORT) | ||
| 84 | - public void exportConversationExcel(@Valid ImConversationPageReqVO pageReqVO, | ||
| 85 | - HttpServletResponse response) throws IOException { | ||
| 86 | - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | ||
| 87 | - List<ImConversationDO> list = imConversationService.getConversationPage(pageReqVO).getList(); | ||
| 88 | - // 导出 Excel | ||
| 89 | - ExcelUtils.write(response, "会话.xls", "数据", ImConversationRespVO.class, | ||
| 90 | - BeanUtils.toBean(list, ImConversationRespVO.class)); | 48 | + @PostMapping("/update-last-read-time") |
| 49 | + @Operation(summary = "更新最后已读时间") | ||
| 50 | + @PreAuthorize("hasAuthority('im:conversation:update')") | ||
| 51 | + public CommonResult<Boolean> updateLastReadTime(@Valid @RequestBody ImConversationSaveReqVO updateReqVO) { | ||
| 52 | + imConversationService.updateLastReadTime(updateReqVO); | ||
| 53 | + return success(true); | ||
| 91 | } | 54 | } |
| 92 | 55 | ||
| 93 | } | 56 | } |
| 94 | \ No newline at end of file | 57 | \ 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
| 1 | package cn.iocoder.yudao.module.im.controller.admin.message; | 1 | package cn.iocoder.yudao.module.im.controller.admin.message; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||
| 8 | -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||
| 9 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO; |
| 10 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageRespVO; | 7 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageRespVO; |
| 11 | -import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSaveReqVO; | ||
| 12 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; | 8 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; |
| 13 | import cn.iocoder.yudao.module.im.service.message.ImMessageService; | 9 | import cn.iocoder.yudao.module.im.service.message.ImMessageService; |
| 14 | import io.swagger.v3.oas.annotations.Operation; | 10 | import io.swagger.v3.oas.annotations.Operation; |
| 15 | import io.swagger.v3.oas.annotations.Parameter; | 11 | import io.swagger.v3.oas.annotations.Parameter; |
| 16 | import io.swagger.v3.oas.annotations.tags.Tag; | 12 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 17 | import jakarta.annotation.Resource; | 13 | import jakarta.annotation.Resource; |
| 18 | -import jakarta.servlet.http.HttpServletResponse; | ||
| 19 | import jakarta.validation.Valid; | 14 | import jakarta.validation.Valid; |
| 20 | import org.springframework.security.access.prepost.PreAuthorize; | 15 | import org.springframework.security.access.prepost.PreAuthorize; |
| 21 | import org.springframework.validation.annotation.Validated; | 16 | import org.springframework.validation.annotation.Validated; |
| 22 | -import org.springframework.web.bind.annotation.*; | 17 | +import org.springframework.web.bind.annotation.GetMapping; |
| 18 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 20 | +import org.springframework.web.bind.annotation.RestController; | ||
| 23 | 21 | ||
| 24 | -import java.io.IOException; | ||
| 25 | import java.util.List; | 22 | import java.util.List; |
| 26 | 23 | ||
| 27 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 24 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 28 | -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 25 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 29 | 26 | ||
| 30 | @Tag(name = "管理后台 - 消息") | 27 | @Tag(name = "管理后台 - 消息") |
| 31 | @RestController | 28 | @RestController |
| @@ -36,58 +33,36 @@ public class ImMessageController { | @@ -36,58 +33,36 @@ public class ImMessageController { | ||
| 36 | @Resource | 33 | @Resource |
| 37 | private ImMessageService imMessageService; | 34 | private ImMessageService imMessageService; |
| 38 | 35 | ||
| 39 | - @PostMapping("/create") | ||
| 40 | - @Operation(summary = "创建消息") | ||
| 41 | - @PreAuthorize("@ss.hasPermission('im:message:create')") | ||
| 42 | - public CommonResult<Long> createMessage(@Valid @RequestBody ImMessageSaveReqVO createReqVO) { | ||
| 43 | - return success(imMessageService.createMessage(createReqVO)); | 36 | + @GetMapping("/get-message-by-sequence") |
| 37 | + @Operation(summary = "拉取消息-增量拉取大于 seq 的消息") | ||
| 38 | + @Parameter(name = "sequence", description = "序号", required = true, example = "1") | ||
| 39 | + @Parameter(name = "size", description = "条数", required = true, example = "10") | ||
| 40 | + @PreAuthorize("@ss.hasPermission('im:message:query')") | ||
| 41 | + public CommonResult<List<ImMessageRespVO>> loadMessage( | ||
| 42 | + @RequestParam("sequence") Long sequence, | ||
| 43 | + @RequestParam("size") Integer size) { | ||
| 44 | + List<ImMessageDO> message = imMessageService.loadMessage(getLoginUserId(), sequence, size); | ||
| 45 | + return success(BeanUtils.toBean(message, ImMessageRespVO.class)); | ||
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | - @PutMapping("/update") | ||
| 47 | - @Operation(summary = "更新消息") | ||
| 48 | - @PreAuthorize("@ss.hasPermission('im:message:update')") | ||
| 49 | - public CommonResult<Boolean> updateMessage(@Valid @RequestBody ImMessageSaveReqVO updateReqVO) { | ||
| 50 | - imMessageService.updateMessage(updateReqVO); | ||
| 51 | - return success(true); | ||
| 52 | - } | ||
| 53 | 48 | ||
| 54 | - @DeleteMapping("/delete") | ||
| 55 | - @Operation(summary = "删除消息") | ||
| 56 | - @Parameter(name = "id", description = "编号", required = true) | ||
| 57 | - @PreAuthorize("@ss.hasPermission('im:message:delete')") | ||
| 58 | - public CommonResult<Boolean> deleteMessage(@RequestParam("id") Long id) { | ||
| 59 | - imMessageService.deleteMessage(id); | ||
| 60 | - return success(true); | ||
| 61 | - } | ||
| 62 | - | ||
| 63 | - @GetMapping("/get") | ||
| 64 | - @Operation(summary = "获得消息") | ||
| 65 | - @Parameter(name = "id", description = "编号", required = true, example = "1024") | 49 | + @GetMapping("/get-all-message") |
| 50 | + @Operation(summary = "拉取全部消息") | ||
| 51 | + @Parameter(name = "size", description = "条数", required = true, example = "10") | ||
| 66 | @PreAuthorize("@ss.hasPermission('im:message:query')") | 52 | @PreAuthorize("@ss.hasPermission('im:message:query')") |
| 67 | - public CommonResult<ImMessageRespVO> getMessage(@RequestParam("id") Long id) { | ||
| 68 | - ImMessageDO message = imMessageService.getMessage(id); | 53 | + public CommonResult<List<ImMessageRespVO>> loadAllMessage(@RequestParam("size") Integer size) { |
| 54 | + List<ImMessageDO> message = imMessageService.loadAllMessage(getLoginUserId(), size); | ||
| 69 | return success(BeanUtils.toBean(message, ImMessageRespVO.class)); | 55 | return success(BeanUtils.toBean(message, ImMessageRespVO.class)); |
| 70 | } | 56 | } |
| 71 | 57 | ||
| 58 | + | ||
| 72 | @GetMapping("/page") | 59 | @GetMapping("/page") |
| 73 | - @Operation(summary = "获得消息分页") | 60 | + @Operation(summary = "查询聊天记录-分页") |
| 74 | @PreAuthorize("@ss.hasPermission('im:message:query')") | 61 | @PreAuthorize("@ss.hasPermission('im:message:query')") |
| 75 | public CommonResult<PageResult<ImMessageRespVO>> getMessagePage(@Valid ImMessagePageReqVO pageReqVO) { | 62 | public CommonResult<PageResult<ImMessageRespVO>> getMessagePage(@Valid ImMessagePageReqVO pageReqVO) { |
| 76 | - PageResult<ImMessageDO> pageResult = imMessageService.getMessagePage(pageReqVO); | ||
| 77 | - return success(BeanUtils.toBean(pageResult, ImMessageRespVO.class)); | 63 | + PageResult<ImMessageDO> messagePage = imMessageService.getMessagePage(pageReqVO); |
| 64 | + return success(BeanUtils.toBean(messagePage, ImMessageRespVO.class)); | ||
| 78 | } | 65 | } |
| 79 | 66 | ||
| 80 | - @GetMapping("/export-excel") | ||
| 81 | - @Operation(summary = "导出消息 Excel") | ||
| 82 | - @PreAuthorize("@ss.hasPermission('im:message:export')") | ||
| 83 | - @OperateLog(type = EXPORT) | ||
| 84 | - public void exportMessageExcel(@Valid ImMessagePageReqVO pageReqVO, | ||
| 85 | - HttpServletResponse response) throws IOException { | ||
| 86 | - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | ||
| 87 | - List<ImMessageDO> list = imMessageService.getMessagePage(pageReqVO).getList(); | ||
| 88 | - // 导出 Excel | ||
| 89 | - ExcelUtils.write(response, "消息.xls", "数据", ImMessageRespVO.class, | ||
| 90 | - BeanUtils.toBean(list, ImMessageRespVO.class)); | ||
| 91 | - } | ||
| 92 | 67 | ||
| 93 | } | 68 | } |
| 94 | \ No newline at end of file | 69 | \ No newline at end of file |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImMessageMapper.java
| @@ -4,9 +4,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -4,9 +4,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO; |
| 7 | +import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO; | ||
| 7 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; | 8 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; |
| 9 | +import com.github.yulichang.wrapper.MPJLambdaWrapper; | ||
| 8 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 11 | ||
| 12 | +import java.util.List; | ||
| 13 | + | ||
| 10 | /** | 14 | /** |
| 11 | * 消息 Mapper | 15 | * 消息 Mapper |
| 12 | * | 16 | * |
| @@ -32,4 +36,24 @@ public interface ImMessageMapper extends BaseMapperX<ImMessageDO> { | @@ -32,4 +36,24 @@ public interface ImMessageMapper extends BaseMapperX<ImMessageDO> { | ||
| 32 | .orderByDesc(ImMessageDO::getId)); | 36 | .orderByDesc(ImMessageDO::getId)); |
| 33 | } | 37 | } |
| 34 | 38 | ||
| 39 | + default List<ImMessageDO> getGreaterThanSequenceMessage(Long userId, Long sequence, Integer size) { | ||
| 40 | + //查询 inbox 表中,大于 sequence 的消息,关联 message 表,按照 inbox 表 sequence 升序 | ||
| 41 | + return selectJoinList(ImMessageDO.class, new MPJLambdaWrapper<ImMessageDO>() | ||
| 42 | + .selectAll(ImMessageDO.class) | ||
| 43 | + .innerJoin(ImInboxDO.class, ImInboxDO::getMessageId, ImMessageDO::getId) | ||
| 44 | + .eq(ImInboxDO::getUserId, userId) | ||
| 45 | + .gt(ImInboxDO::getSequence, sequence) | ||
| 46 | + .orderByAsc(ImInboxDO::getSequence) | ||
| 47 | + .last("limit 0," + size)); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + default List<ImMessageDO> getAllMessage(Long userId, Integer size) { | ||
| 51 | + //查询 inbox 表中,100条消息,关联 message 表,按照 inbox 表 sequence 降序 | ||
| 52 | + return selectJoinList(ImMessageDO.class, new MPJLambdaWrapper<ImMessageDO>() | ||
| 53 | + .selectAll(ImMessageDO.class) | ||
| 54 | + .innerJoin(ImInboxDO.class, ImInboxDO::getMessageId, ImMessageDO::getId) | ||
| 55 | + .eq(ImInboxDO::getUserId, userId) | ||
| 56 | + .orderByDesc(ImInboxDO::getSequence) | ||
| 57 | + .last("limit 0," + size)); | ||
| 58 | + } | ||
| 35 | } | 59 | } |
| 36 | \ No newline at end of file | 60 | \ 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
| @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversatio | @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversatio | ||
| 6 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; | 6 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| 7 | import jakarta.validation.Valid; | 7 | import jakarta.validation.Valid; |
| 8 | 8 | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 9 | /** | 11 | /** |
| 10 | * 会话 Service 接口 | 12 | * 会话 Service 接口 |
| 11 | * | 13 | * |
| @@ -53,10 +55,23 @@ public interface ImConversationService { | @@ -53,10 +55,23 @@ public interface ImConversationService { | ||
| 53 | 55 | ||
| 54 | 56 | ||
| 55 | /** | 57 | /** |
| 56 | - * 保存私聊会话 | 58 | + * 获得用户的会话列表 |
| 59 | + * | ||
| 60 | + * @return 会话列表 | ||
| 61 | + */ | ||
| 62 | + List<ImConversationDO> getConversationList(); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 置顶会话 | ||
| 57 | * | 66 | * |
| 58 | - * @param fromUserId 发送者 | ||
| 59 | - * @param receiverId 接收者 | 67 | + * @param updateReqVO 更新信息 |
| 68 | + */ | ||
| 69 | + void updateTop(ImConversationSaveReqVO updateReqVO); | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 更新最后已读时间 | ||
| 73 | + * | ||
| 74 | + * @param updateReqVO 更新信息 | ||
| 60 | */ | 75 | */ |
| 61 | - void savePrivateConversation(Long fromUserId, Long receiverId); | 76 | + void updateLastReadTime(ImConversationSaveReqVO updateReqVO); |
| 62 | } | 77 | } |
| 63 | \ No newline at end of file | 78 | \ 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.hutool.core.date.DateUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO; |
| 6 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO; | 7 | import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO; |
| 7 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; | 8 | import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; |
| 8 | import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper; | 9 | import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper; |
| 9 | -import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum; | ||
| 10 | import jakarta.annotation.Resource; | 10 | import jakarta.annotation.Resource; |
| 11 | import org.springframework.stereotype.Service; | 11 | import org.springframework.stereotype.Service; |
| 12 | import org.springframework.validation.annotation.Validated; | 12 | import org.springframework.validation.annotation.Validated; |
| 13 | 13 | ||
| 14 | +import java.util.Date; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 14 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 17 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 15 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_NOT_EXISTS; | 18 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_NOT_EXISTS; |
| 16 | 19 | ||
| @@ -69,25 +72,36 @@ public class ImConversationServiceImpl implements ImConversationService { | @@ -69,25 +72,36 @@ public class ImConversationServiceImpl implements ImConversationService { | ||
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | @Override | 74 | @Override |
| 72 | - public void savePrivateConversation(Long fromUserId, Long receiverId) { | ||
| 73 | - // 创建并保存会话 | ||
| 74 | - createAndSaveConversation(fromUserId, receiverId); | ||
| 75 | - createAndSaveConversation(receiverId, fromUserId); | 75 | + public List<ImConversationDO> getConversationList() { |
| 76 | + return imConversationMapper.selectList(); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + @Override | ||
| 80 | + public void updateTop(ImConversationSaveReqVO updateReqVO) { | ||
| 81 | + createOrUpdateConversation(updateReqVO); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @Override | ||
| 85 | + public void updateLastReadTime(ImConversationSaveReqVO updateReqVO) { | ||
| 86 | + createOrUpdateConversation(updateReqVO); | ||
| 76 | } | 87 | } |
| 77 | 88 | ||
| 78 | - private void createAndSaveConversation(Long userId, Long targetId) { | ||
| 79 | - // 创建会话 | ||
| 80 | - ImConversationDO conversation = new ImConversationDO(); | ||
| 81 | - conversation.setUserId(userId); | ||
| 82 | - conversation.setConversationType(ImConversationTypeEnum.PRIVATE.getType()); | ||
| 83 | - conversation.setTargetId(targetId); | ||
| 84 | - conversation.setNo("s_" + userId + "_" + targetId); | ||
| 85 | - conversation.setPinned(false); | ||
| 86 | - | ||
| 87 | - // 根据 no 查询是否存在,不存在则新增 | ||
| 88 | - ImConversationDO imConversationDO = imConversationMapper.selectByNo(conversation.getNo()); | ||
| 89 | - if (imConversationDO == null) { | ||
| 90 | - imConversationMapper.insert(conversation); | 89 | + private void createOrUpdateConversation(ImConversationSaveReqVO updateReqVO) { |
| 90 | + // 操作会话(已读、置顶)时,才会延迟创建,要先判断是否存在,根据 no 查询是否存在,不存在则新增 | ||
| 91 | + ImConversationDO conversation = imConversationMapper.selectByNo(updateReqVO.getNo()); | ||
| 92 | + if (conversation == null) { | ||
| 93 | + ImConversationDO conversationDO = new ImConversationDO(); | ||
| 94 | + conversationDO.setNo(updateReqVO.getNo()); | ||
| 95 | + conversationDO.setUserId(updateReqVO.getUserId()); | ||
| 96 | + conversationDO.setTargetId(updateReqVO.getTargetId()); | ||
| 97 | + conversationDO.setConversationType(updateReqVO.getConversationType()); | ||
| 98 | + conversationDO.setPinned(updateReqVO.getPinned()); | ||
| 99 | + conversationDO.setLastReadTime(DateUtil.toLocalDateTime(new Date())); | ||
| 100 | + imConversationMapper.insert(conversationDO); | ||
| 101 | + } else { | ||
| 102 | + // 更新 | ||
| 103 | + ImConversationDO updateObj = BeanUtils.toBean(updateReqVO, ImConversationDO.class); | ||
| 104 | + imConversationMapper.updateById(updateObj); | ||
| 91 | } | 105 | } |
| 92 | } | 106 | } |
| 93 | 107 |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java
| @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; | @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; | ||
| 7 | import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage; | 7 | import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage; |
| 8 | import jakarta.validation.Valid; | 8 | import jakarta.validation.Valid; |
| 9 | 9 | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 10 | /** | 12 | /** |
| 11 | * 消息 Service 接口 | 13 | * 消息 Service 接口 |
| 12 | * | 14 | * |
| @@ -72,9 +74,29 @@ public interface ImMessageService { | @@ -72,9 +74,29 @@ public interface ImMessageService { | ||
| 72 | 74 | ||
| 73 | /** | 75 | /** |
| 74 | * 保存群聊消息 | 76 | * 保存群聊消息 |
| 75 | - * @param message 消息 | 77 | + * |
| 78 | + * @param message 消息 | ||
| 76 | * @param fromUserId 发送者用户ID | 79 | * @param fromUserId 发送者用户ID |
| 77 | * @return id | 80 | * @return id |
| 78 | */ | 81 | */ |
| 79 | ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId); | 82 | ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId); |
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 拉取消息-大于 seq 的消息 | ||
| 86 | + * | ||
| 87 | + * @param userId 用户id | ||
| 88 | + * @param sequence 序列号 | ||
| 89 | + * @param size 数量 | ||
| 90 | + * @return 消息列表 | ||
| 91 | + */ | ||
| 92 | + List<ImMessageDO> loadMessage(Long userId, Long sequence, Integer size); | ||
| 93 | + | ||
| 94 | + /** | ||
| 95 | + * 拉取全部消息 | ||
| 96 | + * | ||
| 97 | + * @param userId 登录用户编号 | ||
| 98 | + * @param size 数量 | ||
| 99 | + * @return 消息列表 | ||
| 100 | + */ | ||
| 101 | + List<ImMessageDO> loadAllMessage(Long userId, Integer size); | ||
| 80 | } | 102 | } |
| 81 | \ No newline at end of file | 103 | \ 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,6 +6,7 @@ import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO | @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessagePageReqVO | ||
| 6 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSaveReqVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.message.vo.ImMessageSaveReqVO; |
| 7 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; | 7 | import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; |
| 8 | import cn.iocoder.yudao.module.im.dal.mysql.message.ImMessageMapper; | 8 | import cn.iocoder.yudao.module.im.dal.mysql.message.ImMessageMapper; |
| 9 | +import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum; | ||
| 9 | import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; | 10 | import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; |
| 10 | import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage; | 11 | import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage; |
| 11 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 12 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -15,6 +16,8 @@ import org.dromara.hutool.core.date.TimeUtil; | @@ -15,6 +16,8 @@ import org.dromara.hutool.core.date.TimeUtil; | ||
| 15 | import org.springframework.stereotype.Service; | 16 | import org.springframework.stereotype.Service; |
| 16 | import org.springframework.validation.annotation.Validated; | 17 | import org.springframework.validation.annotation.Validated; |
| 17 | 18 | ||
| 19 | +import java.util.List; | ||
| 20 | + | ||
| 18 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 19 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.MESSAGE_NOT_EXISTS; | 22 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.MESSAGE_NOT_EXISTS; |
| 20 | 23 | ||
| @@ -91,7 +94,12 @@ public class ImMessageServiceImpl implements ImMessageService { | @@ -91,7 +94,12 @@ public class ImMessageServiceImpl implements ImMessageService { | ||
| 91 | imMessageDO.setSenderAvatar(user.getAvatar()); | 94 | imMessageDO.setSenderAvatar(user.getAvatar()); |
| 92 | imMessageDO.setConversationType(message.getConversationType()); | 95 | imMessageDO.setConversationType(message.getConversationType()); |
| 93 | imMessageDO.setContentType(message.getContentType()); | 96 | imMessageDO.setContentType(message.getContentType()); |
| 94 | - imMessageDO.setConversationNo(fromUserId + "_" + message.getReceiverId()); | 97 | + //单聊:s_{userId}_{targetId} 群聊:群聊:g_{groupId} |
| 98 | + if (message.getConversationType().equals(ImConversationTypeEnum.PRIVATE.getType())) { | ||
| 99 | + imMessageDO.setConversationNo("s_" + fromUserId + "_" + message.getReceiverId()); | ||
| 100 | + } else if (message.getConversationType().equals(ImConversationTypeEnum.GROUP.getType())) { | ||
| 101 | + imMessageDO.setConversationNo("g_" + message.getReceiverId()); | ||
| 102 | + } | ||
| 95 | imMessageDO.setContent(message.getContent()); | 103 | imMessageDO.setContent(message.getContent()); |
| 96 | //消息来源 100-用户发送;200-系统发送(一般是通知);不能为空 | 104 | //消息来源 100-用户发送;200-系统发送(一般是通知);不能为空 |
| 97 | imMessageDO.setSendFrom(100); | 105 | imMessageDO.setSendFrom(100); |
| @@ -117,4 +125,14 @@ public class ImMessageServiceImpl implements ImMessageService { | @@ -117,4 +125,14 @@ public class ImMessageServiceImpl implements ImMessageService { | ||
| 117 | return saveImMessageDO(message, fromUserId); | 125 | return saveImMessageDO(message, fromUserId); |
| 118 | } | 126 | } |
| 119 | 127 | ||
| 128 | + @Override | ||
| 129 | + public List<ImMessageDO> loadMessage(Long userId, Long sequence, Integer size) { | ||
| 130 | + return imMessageMapper.getGreaterThanSequenceMessage(userId, sequence, size); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + @Override | ||
| 134 | + public List<ImMessageDO> loadAllMessage(Long userId, Integer size) { | ||
| 135 | + return imMessageMapper.getAllMessage(userId, size); | ||
| 136 | + } | ||
| 137 | + | ||
| 120 | } | 138 | } |
| 121 | \ No newline at end of file | 139 | \ No newline at end of file |