Commit eb2d3c39e21ed1f607ef4afe76de2df43a1baf55

Authored by YunaiV
1 parent b5f5c408

♻️ refactor(im):用户申请列表,增加流式查询,避免一次性加载过多,或者历史无法被加载到。

yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java
1 package cn.iocoder.yudao.module.im.controller.admin.friend; 1 package cn.iocoder.yudao.module.im.controller.admin.friend;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -15,6 +16,7 @@ import io.swagger.v3.oas.annotations.Parameter; @@ -15,6 +16,7 @@ import io.swagger.v3.oas.annotations.Parameter;
15 import io.swagger.v3.oas.annotations.tags.Tag; 16 import io.swagger.v3.oas.annotations.tags.Tag;
16 import jakarta.annotation.Resource; 17 import jakarta.annotation.Resource;
17 import jakarta.validation.Valid; 18 import jakarta.validation.Valid;
  19 +import jakarta.validation.constraints.Min;
18 import jakarta.validation.constraints.NotNull; 20 import jakarta.validation.constraints.NotNull;
19 import jakarta.validation.constraints.Size; 21 import jakarta.validation.constraints.Size;
20 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
@@ -75,12 +77,29 @@ public class ImFriendRequestController { @@ -75,12 +77,29 @@ public class ImFriendRequestController {
75 } 77 }
76 78
77 @GetMapping("/list") 79 @GetMapping("/list")
78 - @Operation(summary = "查询「我相关」的好友申请列表(含我发起的、别人加我的)")  
79 - public CommonResult<List<ImFriendRequestRespVO>> getMyFriendRequestList() {  
80 - List<ImFriendRequestDO> list = friendRequestService.getMyFriendRequestList(getLoginUserId()); 80 + @Operation(summary = "查询「我相关」的好友申请列表(游标分页:传 lastRequestId 加载更多)")
  81 + public CommonResult<List<ImFriendRequestRespVO>> getMyFriendRequestList(
  82 + @Parameter(description = "当前列表最旧记录的 id;首页不传")
  83 + @RequestParam(value = "lastRequestId", required = false) Long lastRequestId,
  84 + @Parameter(description = "单次拉取条数", required = true) @RequestParam("limit") @Min(1) Integer limit) {
  85 + List<ImFriendRequestDO> list = friendRequestService.getMyFriendRequestList(getLoginUserId(), lastRequestId, limit);
81 return success(buildList(list)); 86 return success(buildList(list));
82 } 87 }
83 88
  89 + @GetMapping("/get")
  90 + @Operation(summary = "按 id 单查「我相关」的申请记录(带越权过滤;WebSocket 通知到达后用)")
  91 + @Parameter(name = "id", description = "申请记录编号", required = true)
  92 + public CommonResult<ImFriendRequestRespVO> getMyFriendRequest(@RequestParam("id") Long id) {
  93 + ImFriendRequestDO request = friendRequestService.getFriendRequest(id);
  94 + // 越权过滤:fromUser / toUser 必有一方是当前用户,否则当不存在返回 null
  95 + Long currentUserId = getLoginUserId();
  96 + if (request == null || (ObjUtil.notEqual(request.getFromUserId(), currentUserId)
  97 + && ObjUtil.notEqual(request.getToUserId(), currentUserId))) {
  98 + return success(null);
  99 + }
  100 + return success(CollUtil.getFirst(buildList(Collections.singletonList(request))));
  101 + }
  102 +
84 // ========== 私有方法:VO 组装 ========== 103 // ========== 私有方法:VO 组装 ==========
85 104
86 private List<ImFriendRequestRespVO> buildList(List<ImFriendRequestDO> list) { 105 private List<ImFriendRequestRespVO> buildList(List<ImFriendRequestDO> list) {
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/friend/ImFriendRequestMapper.java
@@ -24,10 +24,14 @@ public interface ImFriendRequestMapper extends BaseMapperX&lt;ImFriendRequestDO&gt; { @@ -24,10 +24,14 @@ public interface ImFriendRequestMapper extends BaseMapperX&lt;ImFriendRequestDO&gt; {
24 .last("LIMIT 1")); 24 .last("LIMIT 1"));
25 } 25 }
26 26
27 - default List<ImFriendRequestDO> selectMyList(Long userId, int limit) {  
28 - // 先放扩展过滤再放双向 OR;否则 .and() 返回 LambdaQueryWrapper 基类,丢失 eqIfPresent 等扩展方法 27 + /**
  28 + * 拉取「我相关」的好友申请列表;游标分页:lastRequestId 为 null 拉首页,非 null 拉 id 严格小于它的下一页
  29 + */
  30 + default List<ImFriendRequestDO> selectMyList(Long userId, Long lastRequestId, int limit) {
  31 + // 先放扩展过滤再放双向 OR;否则 .and() 返回 LambdaQueryWrapper 基类,丢失 ltIfPresent 等扩展方法
29 LambdaQueryWrapperX<ImFriendRequestDO> wrapper = new LambdaQueryWrapperX<>(); 32 LambdaQueryWrapperX<ImFriendRequestDO> wrapper = new LambdaQueryWrapperX<>();
30 - wrapper.and(w -> w.eq(ImFriendRequestDO::getFromUserId, userId) 33 + wrapper.ltIfPresent(ImFriendRequestDO::getId, lastRequestId)
  34 + .and(w -> w.eq(ImFriendRequestDO::getFromUserId, userId)
31 .or().eq(ImFriendRequestDO::getToUserId, userId)) 35 .or().eq(ImFriendRequestDO::getToUserId, userId))
32 .orderByDesc(ImFriendRequestDO::getId) 36 .orderByDesc(ImFriendRequestDO::getId)
33 .last("LIMIT " + limit); 37 .last("LIMIT " + limit);
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestService.java
@@ -39,11 +39,18 @@ public interface ImFriendRequestService { @@ -39,11 +39,18 @@ public interface ImFriendRequestService {
39 void refuseFriendRequest(Long userId, Long requestId, String handleContent); 39 void refuseFriendRequest(Long userId, Long requestId, String handleContent);
40 40
41 /** 41 /**
42 - * 查询「我相关」的申请列表(含我发起的、别人加我的) 42 + * 查询「我相关」的申请列表(含我发起的、别人加我的);游标分页:传 lastRequestId 拉它之前的下一页
43 * 43 *
44 - * @param userId 用户编号  
45 - * @return 申请记录列表 44 + * @param userId 用户编号
  45 + * @param lastRequestId 当前列表最旧记录的 id;首页传 null
  46 + * @param limit 单次拉取条数(page size,由前端常量控制)
  47 + * @return 申请记录列表,按 id 倒序
46 */ 48 */
47 - List<ImFriendRequestDO> getMyFriendRequestList(Long userId); 49 + List<ImFriendRequestDO> getMyFriendRequestList(Long userId, Long lastRequestId, Integer limit);
  50 +
  51 + /**
  52 + * 按 id 单查申请记录;通用读接口,调用方自行做越权过滤
  53 + */
  54 + ImFriendRequestDO getFriendRequest(Long id);
48 55
49 } 56 }
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java
@@ -183,8 +183,13 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService { @@ -183,8 +183,13 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService {
183 } 183 }
184 184
185 @Override 185 @Override
186 - public List<ImFriendRequestDO> getMyFriendRequestList(Long userId) {  
187 - return friendRequestMapper.selectMyList(userId, imProperties.getFriend().getRequestListMaxSize()); 186 + public List<ImFriendRequestDO> getMyFriendRequestList(Long userId, Long lastRequestId, Integer limit) {
  187 + return friendRequestMapper.selectMyList(userId, lastRequestId, limit);
  188 + }
  189 +
  190 + @Override
  191 + public ImFriendRequestDO getFriendRequest(Long id) {
  192 + return friendRequestMapper.selectById(id);
188 } 193 }
189 194
190 /** 195 /**