From 1e08e9fbcae7a2208a39a543506d1ced94f19de1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 21 May 2026 10:06:52 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(im):=20=E4=BF=AE=20IM=20?= =?UTF-8?q?=E5=88=87=E8=B4=A6=E5=8F=B7=E4=B8=B2=E5=8F=B7=EF=BC=9AloadConve?= =?UTF-8?q?rsations=20=E5=BC=80=E5=A4=B4=E6=B8=85=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E3=80=81=E5=8A=A0=20loadedUserId=20=E5=AE=88=E9=97=A8=E8=B7=A8?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E5=90=8C=20key=20=E8=AF=AF=E6=BF=80=E6=B4=BB?= =?UTF-8?q?=E3=80=81=E6=96=B0=E5=A2=9E=20clear()=20=E5=AF=B9=E9=BD=90=20fr?= =?UTF-8?q?iend/group=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/im/home/store/conversationStore.ts | 42 +++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/views/im/home/store/conversationStore.ts b/src/views/im/home/store/conversationStore.ts index c1631e9fb..af8049479 100644 --- a/src/views/im/home/store/conversationStore.ts +++ b/src/views/im/home/store/conversationStore.ts @@ -14,7 +14,7 @@ import { import { CONVERSATION_RECENT_FORWARD_MAX } from '../../utils/config' import { getCurrentUserId, imStorage, removeQuietly, StorageKeys } from '../../utils/storage' import { parseRecallMessageId, revokeBlobUrlsInContent } from '../../utils/message' -import { resolveConversationLastContent } from '../../utils/conversation' +import { getConversationKey, resolveConversationLastContent } from '../../utils/conversation' import { tryGetSenderDisplayName } from '../../utils/user' import { useGroupStore } from './groupStore' import { useDraftStore } from './draftStore' @@ -148,6 +148,7 @@ export const useConversationStore = defineStore('imConversationStore', { state: () => ({ conversations: [] as Conversation[], // 全量会话列表(私聊 + 群聊) activeConversation: null as Conversation | null, // 当前激活的会话 + loadedUserId: null as number | null, // 当前内存里这份 conversations 属于哪个用户;切账号时同 key 的 active 不再被误恢复 privateMessageMaxId: 0, // 私聊最大消息 id,作为 pull 的游标 groupMessageMaxId: 0, // 群聊最大消息 id,作为 pull 的游标 channelMessageMaxId: 0, // 频道最大消息 id,作为 pull 的游标 @@ -204,18 +205,29 @@ export const useConversationStore = defineStore('imConversationStore', { async loadConversations() { const userId = getCurrentUserId() if (!userId) { + // 未登录场景也清一下,避免上次登录残留的 conversations / 游标继续在内存中生效 + this.clear() return } + // 加载前快照旧账号身份 + 旧 active 主键:仅同账号才恢复 active,跨账号即便新列表有同 key 也不误激活 + const previousLoadedUserId = this.loadedUserId + const previousActiveKey = this.activeConversation + ? getConversationKey(this.activeConversation) + : null + // 立刻清空内存:无 meta / 空会话列表 / 异常分支都会沿用清空后的干净状态,避免旧账号 conversations + 游标继续生效 + this.clear() try { // 顺手把最近转发列表也恢复出来;和 meta 并发读 const [meta, recent] = await Promise.all([ imStorage.getItem(StorageKeys.conversationMeta(userId)), imStorage.getItem(StorageKeys.recentForwardConversationKeys(userId)) ]) - // 缺数据时显式赋空,避免切账号后沿用上一个用户的内存列表 - this.recentForwardConversationKeys = Array.isArray(recent) - ? recent.slice(0, CONVERSATION_RECENT_FORWARD_MAX) - : [] + // recent 失效保持开头 reset 给的 [];有值才覆盖 + if (Array.isArray(recent)) { + this.recentForwardConversationKeys = recent.slice(0, CONVERSATION_RECENT_FORWARD_MAX) + } + // 标记本次加载到内存里的是哪个用户的数据;放在所有早返回路径之前,让 "无 meta / 空会话" 也能在同账号 re-enter 时识别 + this.loadedUserId = userId if (!meta) { return } @@ -265,11 +277,31 @@ export const useConversationStore = defineStore('imConversationStore', { } }) this.conversations = await Promise.all(tasks) + // 重绑 active:同账号 + 旧 key 仍存在才恢复;跨账号即便有同 key 也不误激活。显式 ?? null 避免依赖 clear() 的隐式链 + if (previousLoadedUserId === userId && previousActiveKey) { + this.activeConversation = + this.conversations.find( + (c) => !c.deleted && getConversationKey(c) === previousActiveKey + ) ?? null + } } catch (e) { console.error('[IM] 本地消息缓存读取失败', e) + // 加载中途异常:避免半成品(maxId 已写但 conversations 未填)让 pullOnce 用错游标漏拉 + this.clear() } }, + /** loadConversations 开头 + 中途失败统一兜底;切账号 / 异常时让旧会话 + 游标不残留。命名与 friendStore.clear / groupStore.clear 对齐 */ + clear() { + this.conversations = [] + this.activeConversation = null + this.loadedUserId = null + this.privateMessageMaxId = 0 + this.groupMessageMaxId = 0 + this.channelMessageMaxId = 0 + this.recentForwardConversationKeys = [] + }, + /** * 持久化到 IndexedDB(fire-and-forget;调用方无需 await) *