From 96f2d1a12fb191fff8627923f94e4c9ef686b2d2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 28 Apr 2026 23:28:27 +0800 Subject: [PATCH] ✨ feat(friend): 添加好友展示备注功能 --- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendController.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendRespVO.java | 3 +++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendUpdateReqVO.java | 8 ++++++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/friend/ImFriendDO.java | 4 ++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java | 5 +++-- yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java | 40 ++++++++++++++++++++++++++++++++++++++++ yudao-module-im/src/test/resources/sql/create_tables.sql | 1 + 7 files changed, 58 insertions(+), 5 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 146cb54..b526ad6 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 @@ -75,7 +75,7 @@ public class ImFriendController { } @PutMapping("/update") - @Operation(summary = "更新好友信息(当前仅免打扰)") + @Operation(summary = "更新好友信息") public CommonResult updateFriend(@Valid @RequestBody ImFriendUpdateReqVO reqVO) { friendService.updateFriend(getLoginUserId(), reqVO); return success(true); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendRespVO.java index 8e00c39..ebefe1e 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendRespVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendRespVO.java @@ -23,6 +23,9 @@ public class ImFriendRespVO { @Schema(description = "是否免打扰", example = "false") private Boolean muted; + @Schema(description = "好友展示备注(仅自己可见)", example = "老张") + private String displayName; + @Schema(description = "好友状态(0=正常,1=已删除)", example = "0") private Integer status; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendUpdateReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendUpdateReqVO.java index a44ae83..3aecfa1 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendUpdateReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/vo/ImFriendUpdateReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.im.controller.admin.friend.vo; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; @Schema(description = "管理后台 - IM 好友更新 Request VO") @@ -12,8 +13,11 @@ public class ImFriendUpdateReqVO { @NotNull(message = "好友用户编号不能为空") private Long friendUserId; - @Schema(description = "是否免打扰", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "免打扰状态不能为空") + @Schema(description = "是否免打扰;不传表示不修改", example = "true") private Boolean muted; + @Schema(description = "好友展示备注(仅自己可见);不传表示不修改,传空串表示清空", example = "老张") + @Size(max = 16, message = "好友备注最多 16 个字符") + private String displayName; + } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/friend/ImFriendDO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/friend/ImFriendDO.java index c61f0e1..55dcc15 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/friend/ImFriendDO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/friend/ImFriendDO.java @@ -51,6 +51,10 @@ public class ImFriendDO extends BaseDO { */ private Boolean muted; /** + * 好友展示备注 + */ + private String displayName; + /** * 好友状态 *

* 枚举 {@link CommonStatusEnum} 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 86b6a89..f4fe4f4 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 @@ -84,8 +84,9 @@ public class ImFriendServiceImpl implements ImFriendService { throw exception(FRIEND_NOT_FRIEND); } - // 2. 更新好友属性(目前仅免打扰) - imFriendMapper.updateById(new ImFriendDO().setId(friend.getId()).setMuted(reqVO.getMuted())); + // 2. 更新好友属性 + imFriendMapper.updateById(new ImFriendDO().setId(friend.getId()) + .setMuted(reqVO.getMuted()).setDisplayName(reqVO.getDisplayName())); // 3. 推送好友更新通知(多端同步) imWebSocketService.sendPrivateMessageAsync(userId, diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java index c6b1856..da0a93e 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java +++ b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java @@ -112,6 +112,46 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest { assertEquals(FRIEND_NOT_FRIEND.getCode(), exception.getCode()); } + @Test + public void testUpdateFriend_displayNameOnly() { + // 准备:只传备注、不传 muted —— 走差量更新 + ImFriendUpdateReqVO reqVO = new ImFriendUpdateReqVO(); + reqVO.setFriendUserId(2L); + reqVO.setDisplayName("老张"); + ImFriendDO friend = ImFriendDO.builder().id(100L).userId(1L).friendUserId(2L) + .muted(false).status(CommonStatusEnum.ENABLE.getStatus()).build(); + when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(friend); + + // 调用 + friendService.updateFriend(1L, reqVO); + + // 断言:updateById 收到 displayName 但没有 muted(MyBatis-Plus 靠 NOT_NULL 跳过) + ArgumentCaptor captor = ArgumentCaptor.forClass(ImFriendDO.class); + verify(imFriendMapper).updateById(captor.capture()); + assertEquals(100L, captor.getValue().getId()); + assertEquals("老张", captor.getValue().getDisplayName()); + assertNull(captor.getValue().getMuted()); + // 断言:推送好友更新通知 + verify(imWebSocketService).sendPrivateMessageAsync(eq(1L), any(ImPrivateMessageDTO.class)); + } + + @Test + public void testUpdateFriend_emptyRequest() { + // 准备:muted 和 displayName 都不传 —— 短路返回,不打 SQL 也不发推送 + ImFriendUpdateReqVO reqVO = new ImFriendUpdateReqVO(); + reqVO.setFriendUserId(2L); + ImFriendDO friend = ImFriendDO.builder().id(100L).userId(1L).friendUserId(2L) + .muted(false).status(CommonStatusEnum.ENABLE.getStatus()).build(); + when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(friend); + + // 调用 + friendService.updateFriend(1L, reqVO); + + // 断言:没触发 SQL 更新 / 没发 WebSocket 推送 + verify(imFriendMapper, never()).updateById(any(ImFriendDO.class)); + verify(imWebSocketService, never()).sendPrivateMessageAsync(any(Long.class), any(ImPrivateMessageDTO.class)); + } + // ========== addFriend ========== @Test diff --git a/yudao-module-im/src/test/resources/sql/create_tables.sql b/yudao-module-im/src/test/resources/sql/create_tables.sql index 924c93c..95dc219 100644 --- a/yudao-module-im/src/test/resources/sql/create_tables.sql +++ b/yudao-module-im/src/test/resources/sql/create_tables.sql @@ -81,6 +81,7 @@ CREATE TABLE IF NOT EXISTS "im_friend" ( "user_id" bigint NOT NULL COMMENT '用户编号', "friend_user_id" bigint NOT NULL COMMENT '好友用户编号', "muted" bit DEFAULT FALSE COMMENT '是否免打扰', + "display_name" varchar(64) NOT NULL DEFAULT '' COMMENT '好友展示备注(仅自己可见)', "status" tinyint NOT NULL COMMENT '好友状态', "add_time" timestamp DEFAULT NULL COMMENT '添加好友时间', "delete_time" timestamp DEFAULT NULL COMMENT '删除好友时间', -- libgit2 0.21.4