✨ feat(im): 修 IM 切账号串号:loadConversations 开头清状态、加 loadedUserId 守门跨账号同 key 误激活、新增 clear() 对齐 friend/group store
parent
69653163b0
commit
1e08e9fbca
|
|
@ -14,7 +14,7 @@ import {
|
||||||
import { CONVERSATION_RECENT_FORWARD_MAX } from '../../utils/config'
|
import { CONVERSATION_RECENT_FORWARD_MAX } from '../../utils/config'
|
||||||
import { getCurrentUserId, imStorage, removeQuietly, StorageKeys } from '../../utils/storage'
|
import { getCurrentUserId, imStorage, removeQuietly, StorageKeys } from '../../utils/storage'
|
||||||
import { parseRecallMessageId, revokeBlobUrlsInContent } from '../../utils/message'
|
import { parseRecallMessageId, revokeBlobUrlsInContent } from '../../utils/message'
|
||||||
import { resolveConversationLastContent } from '../../utils/conversation'
|
import { getConversationKey, resolveConversationLastContent } from '../../utils/conversation'
|
||||||
import { tryGetSenderDisplayName } from '../../utils/user'
|
import { tryGetSenderDisplayName } from '../../utils/user'
|
||||||
import { useGroupStore } from './groupStore'
|
import { useGroupStore } from './groupStore'
|
||||||
import { useDraftStore } from './draftStore'
|
import { useDraftStore } from './draftStore'
|
||||||
|
|
@ -148,6 +148,7 @@ export const useConversationStore = defineStore('imConversationStore', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
conversations: [] as Conversation[], // 全量会话列表(私聊 + 群聊)
|
conversations: [] as Conversation[], // 全量会话列表(私聊 + 群聊)
|
||||||
activeConversation: null as Conversation | null, // 当前激活的会话
|
activeConversation: null as Conversation | null, // 当前激活的会话
|
||||||
|
loadedUserId: null as number | null, // 当前内存里这份 conversations 属于哪个用户;切账号时同 key 的 active 不再被误恢复
|
||||||
privateMessageMaxId: 0, // 私聊最大消息 id,作为 pull 的游标
|
privateMessageMaxId: 0, // 私聊最大消息 id,作为 pull 的游标
|
||||||
groupMessageMaxId: 0, // 群聊最大消息 id,作为 pull 的游标
|
groupMessageMaxId: 0, // 群聊最大消息 id,作为 pull 的游标
|
||||||
channelMessageMaxId: 0, // 频道最大消息 id,作为 pull 的游标
|
channelMessageMaxId: 0, // 频道最大消息 id,作为 pull 的游标
|
||||||
|
|
@ -204,18 +205,29 @@ export const useConversationStore = defineStore('imConversationStore', {
|
||||||
async loadConversations() {
|
async loadConversations() {
|
||||||
const userId = getCurrentUserId()
|
const userId = getCurrentUserId()
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
|
// 未登录场景也清一下,避免上次登录残留的 conversations / 游标继续在内存中生效
|
||||||
|
this.clear()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 加载前快照旧账号身份 + 旧 active 主键:仅同账号才恢复 active,跨账号即便新列表有同 key 也不误激活
|
||||||
|
const previousLoadedUserId = this.loadedUserId
|
||||||
|
const previousActiveKey = this.activeConversation
|
||||||
|
? getConversationKey(this.activeConversation)
|
||||||
|
: null
|
||||||
|
// 立刻清空内存:无 meta / 空会话列表 / 异常分支都会沿用清空后的干净状态,避免旧账号 conversations + 游标继续生效
|
||||||
|
this.clear()
|
||||||
try {
|
try {
|
||||||
// 顺手把最近转发列表也恢复出来;和 meta 并发读
|
// 顺手把最近转发列表也恢复出来;和 meta 并发读
|
||||||
const [meta, recent] = await Promise.all([
|
const [meta, recent] = await Promise.all([
|
||||||
imStorage.getItem<ConversationStoreMeta>(StorageKeys.conversationMeta(userId)),
|
imStorage.getItem<ConversationStoreMeta>(StorageKeys.conversationMeta(userId)),
|
||||||
imStorage.getItem<string[]>(StorageKeys.recentForwardConversationKeys(userId))
|
imStorage.getItem<string[]>(StorageKeys.recentForwardConversationKeys(userId))
|
||||||
])
|
])
|
||||||
// 缺数据时显式赋空,避免切账号后沿用上一个用户的内存列表
|
// recent 失效保持开头 reset 给的 [];有值才覆盖
|
||||||
this.recentForwardConversationKeys = Array.isArray(recent)
|
if (Array.isArray(recent)) {
|
||||||
? recent.slice(0, CONVERSATION_RECENT_FORWARD_MAX)
|
this.recentForwardConversationKeys = recent.slice(0, CONVERSATION_RECENT_FORWARD_MAX)
|
||||||
: []
|
}
|
||||||
|
// 标记本次加载到内存里的是哪个用户的数据;放在所有早返回路径之前,让 "无 meta / 空会话" 也能在同账号 re-enter 时识别
|
||||||
|
this.loadedUserId = userId
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -265,11 +277,31 @@ export const useConversationStore = defineStore('imConversationStore', {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.conversations = await Promise.all(tasks)
|
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) {
|
} catch (e) {
|
||||||
console.error('[IM] 本地消息缓存读取失败', 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)
|
* 持久化到 IndexedDB(fire-and-forget;调用方无需 await)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue