Commit 716738ac5d521ba6013f28bf6a9264fbc00c3b95

Authored by YunaiV
1 parent 92a993b2

fix(im):群昵称修改改为静默同步

- 后端将 GROUP_MEMBER_NICKNAME_UPDATE 改为非持久化事件,避免写入群聊历史消息
- 保留群昵称变更的 WebSocket 在线同步,继续更新成员 displayUserName
- Vue3 聊天侧栏从当前群成员的 displayUserName 回填「我在本群的昵称」
- Vue3 WebSocket 收到 GROUP_MEMBER_NICKNAME_UPDATE 时只同步 groupStore,不再插入消息列表
- 补充后端单测,覆盖群昵称变更事件不入库但仍推送
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImContentTypeEnum.java
... ... @@ -281,9 +281,9 @@ public enum ImContentTypeEnum implements ArrayValuable<Integer> {
281 281 /**
282 282 * 对应 OpenIM:sdkws.GroupMemberInfoSetTips(GroupMemberInfoSetNotification 1516,窄化到 displayUserName)
283 283 * 对应自己的类:GroupMemberNicknameUpdateNotification
284   - * 场景:成员修改自己在群里的昵称,全员广播;前端按 displayUserName 局部更新对应 member
  284 + * 场景:成员修改自己在群里的昵称,在线成员同步对应 member
285 285 */
286   - GROUP_MEMBER_NICKNAME_UPDATE(1516, "成员昵称变更", true, false),
  286 + GROUP_MEMBER_NICKNAME_UPDATE(1516, "成员昵称变更", false, false),
287 287 /**
288 288 * 对应 OpenIM:GroupMemberSetToAdminNotification 1517
289 289 * 对应自己的类:GroupAdminAddNotification
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java
... ... @@ -258,7 +258,7 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService {
258 258 .setId(member.getId());
259 259 groupMemberMapper.updateById(updateObj);
260 260  
261   - // 3.1 displayUserName 是公开字段,单独走 GROUP_MEMBER_NICKNAME_UPDATE 广播给全员;空串视为「清空昵称」也要广播;与旧值相同跳过
  261 + // 3.1 displayUserName 是公开字段,单独走 GROUP_MEMBER_NICKNAME_UPDATE 在线同步给全员;空串视为「清空昵称」也要同步;与旧值相同跳过
262 262 if (updateReqVO.getDisplayUserName() != null
263 263 && ObjUtil.notEqual(updateReqVO.getDisplayUserName(), member.getDisplayUserName())) {
264 264 groupMessageService.sendGroupMessage(userId, ImGroupMessageSendDTO.ofGroupMemberNicknameUpdate(
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImplTest.java
... ... @@ -242,7 +242,7 @@ public class ImGroupMemberServiceImplTest extends BaseMockitoUnitTest {
242 242 verify(groupMemberMapper).updateById(captor.capture());
243 243 assertEquals(50L, captor.getValue().getId());
244 244 assertTrue(captor.getValue().getSilent());
245   - // 公开字段昵称变化 → 全员广播 GROUP_MEMBER_NICKNAME_UPDATE
  245 + // 公开字段昵称变化 → 全员在线同步 GROUP_MEMBER_NICKNAME_UPDATE
246 246 verify(groupMessageService).sendGroupMessage(eq(1L), any(cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO.class));
247 247 // 个人字段 silent 变化 → 仅自己多端同步 GROUP_MEMBER_SETTING_UPDATE
248 248 verify(groupMessageService).sendGroupMessage(eq(1L), eq(ListUtil.of(1L)),
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImplTest.java
... ... @@ -961,6 +961,20 @@ public class ImGroupMessageServiceImplTest extends BaseMockitoUnitTest {
961 961 }
962 962  
963 963 @Test
  964 + public void testSendGroupMessage_dto_groupMemberNicknameUpdateNotInserted() {
  965 + // 准备:成员昵称变更只做在线同步,不入库
  966 + ImGroupMessageSendDTO dto = ImGroupMessageSendDTO.ofGroupMemberNicknameUpdate(10L, 1L, "群昵称");
  967 + when(groupMemberService.getActiveGroupMemberUserIdsByGroupId(10L)).thenReturn(List.of(1L, 2L));
  968 +
  969 + groupMessageService.sendGroupMessage(1L, dto);
  970 +
  971 + verify(groupMessageMapper, never()).insert(any(ImGroupMessageDO.class));
  972 + verify(imWebSocketService).sendNotificationAsync(argThat((Collection<Long> ids) ->
  973 + ids.size() == 2 && ids.contains(1L) && ids.contains(2L)),
  974 + anyInt(), eq(ImContentTypeEnum.GROUP_MEMBER_NICKNAME_UPDATE.getType()), any());
  975 + }
  976 +
  977 + @Test
964 978 public void testSendGroupMessage_threeArg_explicitTargetsBypassActiveMembers() {
965 979 // 准备:调用方传入显式 targets(解散场景成员已被批量 DISABLE,必须按移除前快照推送)
966 980 Set<Long> targets = Set.of(1L, 2L, 3L);
... ...