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 1 package cn.iocoder.yudao.module.im.controller.admin.friend;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
6 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
... ... @@ -15,6 +16,7 @@ import io.swagger.v3.oas.annotations.Parameter;
15 16 import io.swagger.v3.oas.annotations.tags.Tag;
16 17 import jakarta.annotation.Resource;
17 18 import jakarta.validation.Valid;
  19 +import jakarta.validation.constraints.Min;
18 20 import jakarta.validation.constraints.NotNull;
19 21 import jakarta.validation.constraints.Size;
20 22 import org.springframework.validation.annotation.Validated;
... ... @@ -75,12 +77,29 @@ public class ImFriendRequestController {
75 77 }
76 78  
77 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 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 103 // ========== 私有方法:VO 组装 ==========
85 104  
86 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 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 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 35 .or().eq(ImFriendRequestDO::getToUserId, userId))
32 36 .orderByDesc(ImFriendRequestDO::getId)
33 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 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 183 }
184 184  
185 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 /**
... ...