From 42566d1e869bb4db5c461d7f643fbdaea1eb3bf7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 4 May 2026 16:41:55 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(im):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=A5=BD=E5=8F=8B=E7=94=B3=E8=AF=B7=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E6=88=91=E6=B7=BB=E5=8A=A0=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E4=B8=8E=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新好友申请功能,使用 computed 包裹当前用户 ID,避免在 keep-alive 实例中持有旧 ID。增加自我添加好友的校验逻辑,防止用户添加自己为好友。同时,增强自动通过好友申请的异常处理,确保在事务提交后能正确处理失败情况。 --- .../im/home/components/friend/FriendAddDialog.vue | 15 ++++++++++++++- .../im/home/pages/contact/FriendRequestDetail.vue | 5 +++-- .../im/home/pages/contact/FriendRequestList.vue | 11 ++++++----- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/views/im/home/components/friend/FriendAddDialog.vue b/src/views/im/home/components/friend/FriendAddDialog.vue index 388387238..741c03838 100644 --- a/src/views/im/home/components/friend/FriendAddDialog.vue +++ b/src/views/im/home/components/friend/FriendAddDialog.vue @@ -172,7 +172,8 @@ const friendStore = useFriendStore() const userStore = useUserStore() const message = useMessage() -const currentUserId = getCurrentUserId() // 当前登录用户编号 +/** 当前登录用户编号;用 computed 包一层,切账号后随 wsCache 重取,避免顶层求值在 keep-alive 实例里持有旧 id */ +const currentUserId = computed(() => getCurrentUserId()) const keyword = ref('') const users = ref([]) const searched = ref(false) @@ -266,6 +267,11 @@ async function handleSubmitApply() { if (!targetUser.value) { return } + // 预校验:不能加自己(搜索列表已过滤,这里兜底 presetUser / 名片入口等场景) + if (targetUser.value.id === currentUserId.value) { + message.warning('不能添加自己为好友') + return + } submitting.value = true try { const requestId = await friendStore.applyFriend({ @@ -274,8 +280,15 @@ async function handleSubmitApply() { displayName: displayName.value.trim() || undefined, addSource: props.addSource }) + // silent 分支(已是单向好友被静默重启):主动 loadFriendInfo 入库,不依赖 WS FRIEND_ADD 推送,避免丢推时列表看不到 + if (requestId === null) { + await friendStore.loadFriendInfo(targetUser.value.id) + } message.success(requestId ? '申请已发送,等待对方验证' : '已添加为好友') visible.value = false + } catch { + // 业务错误(已是好友 / 被对方拉黑 / 用户被禁用 等):全局拦截器已弹错误提示,本地关弹窗避免脏状态停留 + visible.value = false } finally { submitting.value = false } diff --git a/src/views/im/home/pages/contact/FriendRequestDetail.vue b/src/views/im/home/pages/contact/FriendRequestDetail.vue index df1dffce4..b1a6f78d6 100644 --- a/src/views/im/home/pages/contact/FriendRequestDetail.vue +++ b/src/views/im/home/pages/contact/FriendRequestDetail.vue @@ -104,10 +104,11 @@ const emit = defineEmits<{ const friendStore = useFriendStore() const message = useMessage() -const currentUserId = Number(getCurrentUserId() || 0) +/** 当前登录用户编号;用 computed 包一层,切账号后随 wsCache 重取,避免顶层求值在 keep-alive 实例里持有旧 id */ +const currentUserId = computed(() => getCurrentUserId()) /** 是不是我发起的(fromUserId === me) */ -const iSentIt = computed(() => props.request.fromUserId === currentUserId) +const iSentIt = computed(() => props.request.fromUserId === currentUserId.value) /** 是否「已拒绝」态:模板里多处用到,computed 一次省得到处写枚举比对 */ const refused = computed( diff --git a/src/views/im/home/pages/contact/FriendRequestList.vue b/src/views/im/home/pages/contact/FriendRequestList.vue index 0917b02f0..a66b40087 100644 --- a/src/views/im/home/pages/contact/FriendRequestList.vue +++ b/src/views/im/home/pages/contact/FriendRequestList.vue @@ -82,30 +82,31 @@ const emit = defineEmits<{ }>() const expanded = ref(true) -const currentUserId = getCurrentUserId() +/** 当前登录用户编号;用 computed 包一层,切账号后随 wsCache 重取,避免顶层求值在 keep-alive 实例里持有旧 id */ +const currentUserId = computed(() => getCurrentUserId()) /** 未处理 + 别人加我的(接收方=我)才进红点;我发起的不进 */ const unhandledCount = computed( () => props.requests.filter( - (r) => r.handleResult === ImFriendRequestHandleResult.UNHANDLED && r.toUserId === currentUserId + (r) => r.handleResult === ImFriendRequestHandleResult.UNHANDLED && r.toUserId === currentUserId.value ).length ) /** 列表项展示对端:fromUserId == 我 → 对端 = toUser;否则对端 = fromUser */ function getPeerUserId(request: FriendRequest): number { - return request.fromUserId === currentUserId ? request.toUserId : request.fromUserId + return request.fromUserId === currentUserId.value ? request.toUserId : request.fromUserId } /** 列表项展示对端的昵称(fromUserId == 我 → toUser 昵称;否则 fromUser 昵称;缺则用 id 兜底) */ function getPeerNickname(request: FriendRequest): string { - return request.fromUserId === currentUserId + return request.fromUserId === currentUserId.value ? request.toNickname || String(request.toUserId) : request.fromNickname || String(request.fromUserId) } /** 列表项展示对端的头像(fromUserId == 我 → toUser 头像;否则 fromUser 头像) */ function getPeerAvatar(request: FriendRequest): string | undefined { - return request.fromUserId === currentUserId ? request.toAvatar : request.fromAvatar + return request.fromUserId === currentUserId.value ? request.toAvatar : request.fromAvatar }