feat(im):fetchFriends 加 pending 去重 + FRIEND_APPLICATION 重命名 RECEIVED + inflight 命名调整为 pending

im
YunaiV 2026-05-04 19:14:51 +08:00
parent cfd152addf
commit b242b017c0
3 changed files with 38 additions and 26 deletions

View File

@ -25,14 +25,16 @@ import { getCurrentUserId, imStorage, setQuietly, StorageKeys } from '../../util
import { getFriendDisplayName } from '../../utils/user'
import type { Friend, FriendRequest } from '../types'
/** 当前正在进行的好友列表拉取;多 dispatcher 同时触发时复用同一 Promise避免雪崩重拉 */
let pendingFetchFriends: Promise<void> | null = null
/** 当前正在进行的好友申请列表拉取;多端连续多条申请到达时复用同一 Promise避免雪崩重拉 */
let inflightFetchRequests: Promise<void> | null = null
let pendingFetchRequests: Promise<void> | null = null
/** 好友通知 payload对齐后端 BaseFriendNotification + 子类裁减后的字段) */
export interface FriendNotificationPayload {
operatorUserId: number
friendUserId: number
// FRIEND_APPLICATION 系列:申请记录的核心字段(避免 payload 携带完整 DO
// FRIEND_REQUEST_* 系列:申请记录的核心字段(避免 payload 携带完整 DO
requestId?: number
applyContent?: string
handleContent?: string
@ -128,24 +130,34 @@ export const useFriendStore = defineStore('imFriendStore', {
// ==================== 远端拉取 ====================
/** 从后端拉取并覆盖本地列表;同步刷新对应私聊会话的展示名 / 头像 + 落 IDB */
/** 从后端拉取并覆盖本地列表;同步刷新对应私聊会话的展示名 / 头像 + 落 IDBpending 期间复用同一 Promise */
async fetchFriends(force = false) {
if (this.loaded && !force) {
return
}
const list = await apiGetMyFriendList()
this.friends = (list || []).map(convertFriend)
this.loaded = true
// 同步 conversationStore 私聊会话的展示名 / 头像 / 免打扰
const conversationStore = useConversationStore()
for (const friend of this.friends) {
conversationStore.updateConversation(ImConversationType.PRIVATE, friend.friendUserId, {
name: getFriendDisplayName(friend),
avatar: friend.avatar,
muted: friend.muted
})
if (pendingFetchFriends) {
return pendingFetchFriends
}
this.saveFriends()
pendingFetchFriends = apiGetMyFriendList()
.then((list) => {
this.friends = (list || []).map(convertFriend)
this.loaded = true
// 同步 conversationStore 私聊会话的展示名 / 头像 / 免打扰
const conversationStore = useConversationStore()
for (const friend of this.friends) {
conversationStore.updateConversation(ImConversationType.PRIVATE, friend.friendUserId, {
name: getFriendDisplayName(friend),
avatar: friend.avatar,
muted: friend.muted
})
}
// 落本地缓存
this.saveFriends()
})
.finally(() => {
pendingFetchFriends = null
})
return pendingFetchFriends
},
/** 按 friendUserId 获取详情并合并到本地(保证 nickname / avatar 最新) */
@ -195,19 +207,19 @@ export const useFriendStore = defineStore('imFriendStore', {
}
},
/** 拉取「我相关」的好友申请列表(页面打开时 / 收到 FRIEND_APPLICATION 时刷新in-flight 期间复用同一 Promise */
/** 拉取「我相关」的好友申请列表(页面打开时 / 收到 FRIEND_REQUEST_RECEIVED 时刷新pending 期间复用同一 Promise */
async fetchFriendRequests() {
if (inflightFetchRequests) {
return inflightFetchRequests
if (pendingFetchRequests) {
return pendingFetchRequests
}
inflightFetchRequests = apiGetMyFriendRequestList()
pendingFetchRequests = apiGetMyFriendRequestList()
.then((list) => {
this.friendRequests = (list || []).map(convertFriendRequest)
})
.finally(() => {
inflightFetchRequests = null
pendingFetchRequests = null
})
return inflightFetchRequests
return pendingFetchRequests
},
/** 按 id 查申请记录;列表是按 id 倒序的小列表O(n) find 即可,不再维护 Map 索引 */
@ -320,8 +332,8 @@ export const useFriendStore = defineStore('imFriendStore', {
// ==================== WebSocket 事件 dispatcher1201-1210 段) ====================
/** FRIEND_APPLICATION(1203)收到新申请payload 已裁减为核心字段,本地拉一次列表补齐 fromUser 等聚合字段 */
applyFriendRequestNotification(_payload: FriendNotificationPayload) {
/** FRIEND_REQUEST_RECEIVED(1203)收到新申请payload 已裁减为核心字段,本地拉一次列表补齐 fromUser 等聚合字段 */
applyFriendRequestReceivedNotification(_payload: FriendNotificationPayload) {
this.fetchFriendRequests().catch(() => undefined)
},

View File

@ -486,8 +486,8 @@ export const useImWebSocketStore = defineStore('imWebSocketStore', {
const payload = JSON.parse(websocketMessage.content || '{}') as FriendNotificationPayload
const friendStore = useFriendStore()
switch (websocketMessage.type) {
case ImMessageType.FRIEND_APPLICATION:
friendStore.applyFriendRequestNotification(payload)
case ImMessageType.FRIEND_REQUEST_RECEIVED:
friendStore.applyFriendRequestReceivedNotification(payload)
break
case ImMessageType.FRIEND_REQUEST_APPROVED:
friendStore.applyFriendRequestApprovedNotification(payload)

View File

@ -12,7 +12,7 @@ export const ImMessageType = {
// ========== 好友通知1201-1210 直接复用 OpenIM 段位编号) ==========
FRIEND_REQUEST_APPROVED: 1201, // 好友申请被同意
FRIEND_REQUEST_REJECTED: 1202, // 好友申请被拒绝
FRIEND_APPLICATION: 1203, // 收到新的好友申请
FRIEND_REQUEST_RECEIVED: 1203, // 收到新的好友申请
FRIEND_ADD: 1204, // 新增好友(双方建立关系)
FRIEND_DELETE: 1205, // 好友被删除
// 1206 对应 OpenIM FriendRemarkSetNotification本系统并入 FRIEND_UPDATE(1210) 统一推送,单一字段变更不再独立通道