From b0221c21cdc6c54205033ce85aae48896f8104ca Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 4 May 2026 19:52:37 +0800 Subject: [PATCH] ♻️ refactor(im):好友模块清理——删 ImFriendServiceImpl 无效的 getSelf 自代理 + Controller 回调参数命名展开 + Consumer 补日志 + silent re-add 注释补充 --- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java | 6 +++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java | 12 +++++++----- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java | 4 ++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java | 14 +++++--------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java index 5c1b6b3..d62d1bb 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java @@ -100,9 +100,9 @@ public class ImFriendController { // 批量聚合 AdminUser 信息(昵称 / 头像),避免 N+1 Map userMap = adminUserApi.getUserMap( convertList(friends, ImFriendDO::getFriendUserId)); - return convertList(friends, f -> { - ImFriendRespVO vo = BeanUtils.toBean(f, ImFriendRespVO.class); - MapUtils.findAndThen(userMap, f.getFriendUserId(), user -> + return convertList(friends, friend -> { + ImFriendRespVO vo = BeanUtils.toBean(friend, ImFriendRespVO.class); + MapUtils.findAndThen(userMap, friend.getFriendUserId(), user -> vo.setNickname(user.getNickname()).setAvatar(user.getAvatar())); // 备注 / 昵称的拼音,给前端做字母分桶 + 拼音搜索 vo.setDisplayNamePinyin(StrUtils.toPinyin(vo.getDisplayName())) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java index 9c74946..879577d 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java @@ -87,13 +87,15 @@ public class ImFriendRequestController { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } - Set userIds = convertSetByFlatMap(list, r -> Stream.of(r.getFromUserId(), r.getToUserId())); + // 双向 OR 列表,userIds 取 from + to 两组并集 + Set userIds = convertSetByFlatMap(list, + request -> Stream.of(request.getFromUserId(), request.getToUserId())); Map userMap = adminUserApi.getUserMap(userIds); - return convertList(list, r -> { - ImFriendRequestRespVO vo = BeanUtils.toBean(r, ImFriendRequestRespVO.class); - MapUtils.findAndThen(userMap, r.getFromUserId(), user -> + return convertList(list, request -> { + ImFriendRequestRespVO vo = BeanUtils.toBean(request, ImFriendRequestRespVO.class); + MapUtils.findAndThen(userMap, request.getFromUserId(), user -> vo.setFromNickname(user.getNickname()).setFromAvatar(user.getAvatar())); - MapUtils.findAndThen(userMap, r.getToUserId(), user -> + MapUtils.findAndThen(userMap, request.getToUserId(), user -> vo.setToNickname(user.getNickname()).setToAvatar(user.getAvatar())); return vo; }); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java index 40ddcab..528b99b 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java @@ -33,6 +33,7 @@ public class AdminUserProfileUpdateConsumer { @EventListener @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步 public void onMessage(AdminUserProfileUpdateMessage message) { + log.info("[onMessage][消息内容({})]", message); Long userId = message.getUserId(); // 1. 找当前用户的所有有效好友(DISABLE 已删的不推) List friends = friendService.getFriendList(userId); @@ -41,6 +42,7 @@ public class AdminUserProfileUpdateConsumer { } // 2. 给每个好友的多端推 FRIEND_INFO_UPDATED;payload 里 operatorUserId / friendUserId 都是「资料被改的人」 + int notifyCount = 0; for (ImFriendDO friend : friends) { if (CommonStatusEnum.isDisable(friend.getStatus())) { continue; @@ -49,7 +51,9 @@ public class AdminUserProfileUpdateConsumer { .setOperatorUserId(userId).setFriendUserId(userId); websocketService.sendPrivateMessageAsync(friend.getFriendUserId(), ImPrivateMessageDTO.ofFriendNotification( ImMessageTypeEnum.FRIEND_INFO_UPDATED.getType(), userId, friend.getFriendUserId(), payload)); + notifyCount++; } + log.info("[onMessage][userId({}) 推送 FRIEND_INFO_UPDATED 给 {} 位好友]", userId, notifyCount); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java index f7e8b78..8a4852c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.im.service.friend; import cn.hutool.core.util.BooleanUtil; -import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.im.controller.admin.friend.vo.ImFriendUpdateReqVO; @@ -124,8 +123,8 @@ public class ImFriendServiceImpl implements ImFriendService { Long toUserId = request.getToUserId(); // 1. 双向建立关系:A 侧带申请的 displayName / addSource;B 侧 displayName 为空、addSource 同来源 // FRIEND_STATE 双向失效由方法上的 @Caching 注解处理;framework 已开 transactionAware 自动延迟到 afterCommit - getSelf().addFriend0(fromUserId, toUserId, request.getDisplayName(), request.getAddSource()); - getSelf().addFriend0(toUserId, fromUserId, null, request.getAddSource()); + addFriend0(fromUserId, toUserId, request.getDisplayName(), request.getAddSource()); + addFriend0(toUserId, fromUserId, null, request.getAddSource()); // 2.1 推 TIP 系统消息(双方私聊会话里看到「你们已成为好友」);TIP 走会话入库,FRIEND_ADD 走事件通知 privateMessageService.sendTipPrivateMessage(fromUserId, toUserId, FRIEND_ADD_TIP_MESSAGE); @@ -150,7 +149,8 @@ public class ImFriendServiceImpl implements ImFriendService { @Transactional(rollbackFor = Exception.class) public void silentReAddFriend(Long userId, Long friendUserId, String displayName, Integer addSource) { // 1. 单边重新启用我侧好友关系 - getSelf().addFriend0(userId, friendUserId, displayName, addSource); + // 不推 TIP 系统消息:sendPrivateMessage 是 (sender, receiver) 单条入库 + 双向可见,无法仅 userId 单边可见;对方不应感知 silent 重启,TIP 整体省略 + addFriend0(userId, friendUserId, displayName, addSource); // 2. 仅推 FRIEND_ADD 给 userId 多端(不通知对方,保持「对方一直把我当好友」的错觉) // operatorUserId 填 friendUserId(对方):让 userId 多端 UI 呈现「对方加了我」的视觉效果,与 silent 语义对齐 @@ -169,7 +169,7 @@ public class ImFriendServiceImpl implements ImFriendService { public void deleteFriend(Long userId, Long friendUserId) { // 1. 单边软删:仅 userId 视角的关系置 DISABLE;friendUserId 视角不动 // 不推 TIP 系统消息:单边删除语义下对方不应感知;userId 端反馈由前端 toast 承担,多端同步靠下面的 FRIEND_DELETE - getSelf().deleteFriend0(userId, friendUserId); + deleteFriend0(userId, friendUserId); // 2. 推 FRIEND_DELETE 给 userId 多端做同步(friendUserId 不感知) FriendDeleteNotification payload = (FriendDeleteNotification) new FriendDeleteNotification() @@ -287,8 +287,4 @@ public class ImFriendServiceImpl implements ImFriendService { return friendMapper.selectPage(reqVO); } - private ImFriendServiceImpl getSelf() { - return SpringUtil.getBean(getClass()); - } - } -- libgit2 0.21.4