✨ feat(im): 优化 ConversationItem.vue 逻辑
parent
68d3ad10d4
commit
d6f96a56a2
|
|
@ -0,0 +1,606 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { store } from '@/store'
|
||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||
|
||||
import {
|
||||
ImConversationType,
|
||||
ImMessageType,
|
||||
ImMessageStatus,
|
||||
TIME_TIP_GAP_MS
|
||||
} from '../../utils/constants'
|
||||
import { StorageKeys } from '../../utils/storage'
|
||||
import { parseMessage, buildRecallTip, type TextMessage } from '../../utils/message'
|
||||
import type { Conversation, Message, ConversationsData } from '../types'
|
||||
|
||||
const AT_ALL_FLAG = -1 // @全体成员 的特殊 userId 标识:atUserIds 中包含 -1 表示 @all
|
||||
|
||||
/** 获取当前登录用户编号 */
|
||||
function getCurrentUserId(): number {
|
||||
const { wsCache } = useCache()
|
||||
const user = wsCache.get(CACHE_KEY.USER)?.user
|
||||
return Number(user?.id) || 0
|
||||
}
|
||||
|
||||
/** 当前登录用户的会话列表 localStorage key */
|
||||
function currentConversationsKey(): string {
|
||||
return StorageKeys.conversations(getCurrentUserId())
|
||||
}
|
||||
|
||||
export const useConversationStore = defineStore('imConversationStore', {
|
||||
state: () => ({
|
||||
conversations: [] as Conversation[], // 全量会话列表(私聊 + 群聊)
|
||||
activeConversation: null as Conversation | null, // 当前激活的会话
|
||||
privateMessageMaxId: 0, // 私聊最大消息 id,作为 pull 的游标
|
||||
groupMessageMaxId: 0, // 群聊最大消息 id,作为 pull 的游标
|
||||
loading: false // 是否正在批量加载(例如离线消息拉取期间),避免频繁写 localStorage
|
||||
}),
|
||||
|
||||
getters: {
|
||||
/**
|
||||
* 会话列表排序规则:
|
||||
* 1. 置顶优先(top=true 的在前)
|
||||
* 2. 同级别按 lastSendTime 降序
|
||||
*/
|
||||
sortedConversations(state): Conversation[] {
|
||||
return [...state.conversations]
|
||||
.filter((c) => !c.deleted)
|
||||
.sort((a, b) => {
|
||||
const aTop = a.top ? 1 : 0
|
||||
const bTop = b.top ? 1 : 0
|
||||
if (aTop !== bTop) {
|
||||
return bTop - aTop
|
||||
}
|
||||
return b.lastSendTime - a.lastSendTime
|
||||
})
|
||||
},
|
||||
/** 当前会话的消息列表 */
|
||||
activeMessages(state): Message[] {
|
||||
return state.activeConversation?.messages || []
|
||||
},
|
||||
/** 未读总数(免打扰会话不计入)—— 用于 ToolBar 红点 */
|
||||
totalUnread(state): number {
|
||||
return state.conversations
|
||||
.filter((c) => !c.deleted && !c.muted)
|
||||
.reduce((sum, c) => sum + (c.unreadCount || 0), 0)
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
// ==================== 本地存储 ====================
|
||||
|
||||
/** 从 localStorage 恢复会话数据 */
|
||||
loadConversations() {
|
||||
const item = localStorage.getItem(currentConversationsKey())
|
||||
if (!item) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 反序列化缓存数据,恢复消息游标(privateMessageMaxId / groupMessageMaxId)
|
||||
const storageData = JSON.parse(item) as ConversationsData
|
||||
this.privateMessageMaxId = Number(storageData.privateMessageMaxId) || 0
|
||||
this.groupMessageMaxId = Number(storageData.groupMessageMaxId) || 0
|
||||
|
||||
// 回放会话列表,同时修正重启前遗留的"发送中"状态
|
||||
if (storageData.conversations && storageData.conversations.length > 0) {
|
||||
for (const conversation of storageData.conversations) {
|
||||
if (conversation.messages) {
|
||||
conversation.messages.forEach((message) => {
|
||||
// 发送中状态的消息标记为失败:重启后不可能仍处在发送中
|
||||
if (message.status === ImMessageStatus.SENDING) {
|
||||
message.status = ImMessageStatus.FAILED
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
this.conversations = storageData.conversations
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[IM] 本地消息缓存读取失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
/** 持久化到 localStorage */
|
||||
saveToStorage() {
|
||||
// loading 期间跳过,避免大量写入阻塞主线程
|
||||
if (this.loading) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO @AI:这个方案,可能存不下太多数据,需要调整!
|
||||
const storageData: ConversationsData = {
|
||||
privateMessageMaxId: this.privateMessageMaxId,
|
||||
groupMessageMaxId: this.groupMessageMaxId,
|
||||
conversations: this.conversations.filter((c) => !c.deleted)
|
||||
}
|
||||
try {
|
||||
localStorage.setItem(currentConversationsKey(), JSON.stringify(storageData))
|
||||
} catch (e) {
|
||||
console.error('[IM] 本地消息缓存存储失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 会话查找 / 打开 ====================
|
||||
|
||||
/** 查找会话:按 (type, targetId) 组合主键 */
|
||||
findConversation(type: number, targetId: number): Conversation | undefined {
|
||||
return this.conversations.find((c) => c.type === type && c.targetId === targetId)
|
||||
},
|
||||
|
||||
/**
|
||||
* 打开或创建一个会话,并设为激活
|
||||
*
|
||||
* 调用方应该把从 friendStore / groupStore 拿到的最新元数据(muted 等)
|
||||
* 通过 options 传进来,避免新建/复用的会话显示陈旧状态。
|
||||
* 此处不在 conversationStore 里反向 import friendStore/groupStore,是为了避免循环依赖。
|
||||
*/
|
||||
openConversation(
|
||||
targetId: number,
|
||||
type: number,
|
||||
showName: string,
|
||||
showImage: string,
|
||||
options?: { muted?: boolean }
|
||||
): Conversation {
|
||||
// 按 (type, targetId) 查找已有会话,不存在则新建并插到列表头部
|
||||
let conversation = this.findConversation(type, targetId)
|
||||
if (!conversation) {
|
||||
conversation = this.createEmptyConversation(type, targetId, showName, showImage)
|
||||
if (options?.muted !== undefined) {
|
||||
conversation.muted = options.muted
|
||||
}
|
||||
this.conversations.unshift(conversation)
|
||||
} else {
|
||||
// 已存在会话:用最新元数据刷新 showName / showImage / muted
|
||||
if (showName) {
|
||||
conversation.showName = showName
|
||||
}
|
||||
if (showImage) {
|
||||
conversation.showImage = showImage
|
||||
}
|
||||
if (options?.muted !== undefined) {
|
||||
conversation.muted = options.muted
|
||||
}
|
||||
}
|
||||
this.setActiveConversation(conversation)
|
||||
return conversation
|
||||
},
|
||||
|
||||
/** 设置当前会话,同时清零未读数 + 清除 @ 标记 */
|
||||
setActiveConversation(conversation: Conversation | null) {
|
||||
this.activeConversation = conversation
|
||||
if (conversation) {
|
||||
conversation.unreadCount = 0
|
||||
conversation.atMe = false
|
||||
conversation.atAll = false
|
||||
this.saveToStorage()
|
||||
}
|
||||
},
|
||||
|
||||
/** 创建空会话(抽取公共逻辑,供 insertMessage / openConversation 复用) */
|
||||
createEmptyConversation(type: number, targetId: number, showName: string, showImage: string): Conversation {
|
||||
return {
|
||||
targetId,
|
||||
type,
|
||||
showName,
|
||||
showImage,
|
||||
lastContent: '',
|
||||
lastSendTime: 0,
|
||||
unreadCount: 0,
|
||||
messages: [],
|
||||
deleted: false,
|
||||
top: false,
|
||||
muted: false,
|
||||
atMe: false,
|
||||
atAll: false,
|
||||
senderNickName: '',
|
||||
lastTimeTip: 0
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 置顶 / 免打扰 / 删除会话 ====================
|
||||
|
||||
/** 将某个会话置顶态切换 */
|
||||
setTop(type: number, targetId: number, top: boolean) {
|
||||
const conversation = this.findConversation(type, targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
conversation.top = top
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/** 设置会话免打扰(本地状态;后端同步由 friendStore / groupStore + /muted API 负责) */
|
||||
setMuted(type: number, targetId: number, muted: boolean) {
|
||||
const conversation = this.findConversation(type, targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
conversation.muted = muted
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/** 删除会话(软删:标记 deleted=true,持久化时过滤)*/
|
||||
removeConversation(type: number, targetId: number) {
|
||||
const conversation = this.findConversation(type, targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
if (this.activeConversation === conversation) {
|
||||
this.activeConversation = null
|
||||
}
|
||||
conversation.deleted = true
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
removePrivateConversation(friendId: number) {
|
||||
this.removeConversation(ImConversationType.PRIVATE, friendId)
|
||||
},
|
||||
|
||||
removeGroupConversation(groupId: number) {
|
||||
this.removeConversation(ImConversationType.GROUP, groupId)
|
||||
},
|
||||
|
||||
// ==================== 消息插入 / 更新 ====================
|
||||
|
||||
/**
|
||||
* 插入消息到会话
|
||||
*
|
||||
* 主要行为(子步骤见函数内 // x.y 注释):
|
||||
* 1. 会话定位:查找或创建 + 去重合并
|
||||
* 2. 更新会话元数据:摘要、@ 标记、未读数
|
||||
* 3. 插入消息:时间分隔线 + 按 id 有序插入
|
||||
* 4. 收尾:更新游标 + 持久化
|
||||
*/
|
||||
insertMessage(
|
||||
conversationInfo: { type: number; targetId: number; showName: string; showImage: string },
|
||||
messageInfo: Message
|
||||
) {
|
||||
// 1.1 查找或自动创建会话
|
||||
let conversation = this.findConversation(conversationInfo.type, conversationInfo.targetId)
|
||||
if (!conversation) {
|
||||
conversation = this.createEmptyConversation(
|
||||
conversationInfo.type,
|
||||
conversationInfo.targetId,
|
||||
conversationInfo.showName,
|
||||
conversationInfo.showImage
|
||||
)
|
||||
this.conversations.unshift(conversation)
|
||||
}
|
||||
|
||||
// 1.2 去重合并:优先按 id,其次按 clientMessageId。命中则覆盖更新并返回
|
||||
const existingIndex = conversation.messages.findIndex((message) => {
|
||||
if (messageInfo.id && message.id && message.id === messageInfo.id) {
|
||||
return true
|
||||
}
|
||||
return !!(messageInfo.clientMessageId && message.clientMessageId && message.clientMessageId === messageInfo.clientMessageId)
|
||||
})
|
||||
if (existingIndex >= 0) {
|
||||
// 覆盖更新,保留本地已有但服务端未带的字段(如 senderNickName)
|
||||
conversation.messages[existingIndex] = { ...conversation.messages[existingIndex], ...messageInfo }
|
||||
conversation.lastSendTime = messageInfo.sendTime || conversation.lastSendTime
|
||||
this.updateMaxId(conversationInfo.type, messageInfo.id)
|
||||
this.saveToStorage()
|
||||
return
|
||||
}
|
||||
|
||||
// 2.1 更新会话摘要(lastContent / lastSendTime / senderNickName)
|
||||
conversation.lastContent = this.resolveLastContent(messageInfo)
|
||||
conversation.lastSendTime = messageInfo.sendTime || Date.now()
|
||||
conversation.senderNickName = messageInfo.senderNickName || ''
|
||||
|
||||
// 2.2 群聊 @ 标记(仅对方消息 + 未读态有效)
|
||||
if (
|
||||
!messageInfo.selfSend &&
|
||||
conversation.type === ImConversationType.GROUP &&
|
||||
messageInfo.atUserIds &&
|
||||
messageInfo.atUserIds.length > 0 &&
|
||||
messageInfo.status !== ImMessageStatus.READ
|
||||
) {
|
||||
const currentUserId = getCurrentUserId()
|
||||
if (currentUserId && messageInfo.atUserIds.includes(currentUserId)) {
|
||||
conversation.atMe = true
|
||||
}
|
||||
if (messageInfo.atUserIds.includes(AT_ALL_FLAG)) {
|
||||
conversation.atAll = true
|
||||
}
|
||||
}
|
||||
|
||||
// 2.3 未读数:非当前会话 + 非自己发送 + 非系统 tip + 非已读 => +1
|
||||
const isActive =
|
||||
this.activeConversation?.type === conversationInfo.type &&
|
||||
this.activeConversation?.targetId === conversationInfo.targetId
|
||||
const isTipMessage =
|
||||
messageInfo.type === ImMessageType.TIP_TEXT || messageInfo.type === ImMessageType.TIP_TIME
|
||||
if (
|
||||
!messageInfo.selfSend &&
|
||||
!isActive &&
|
||||
!isTipMessage &&
|
||||
messageInfo.status !== ImMessageStatus.READ &&
|
||||
messageInfo.status !== ImMessageStatus.RECALL
|
||||
) {
|
||||
conversation.unreadCount++
|
||||
}
|
||||
|
||||
// 3.1 时间分隔线:距上条 TIP_TIME 超过 10 分钟则插入一条
|
||||
const sendTime = messageInfo.sendTime || Date.now()
|
||||
if (!conversation.lastTimeTip || conversation.lastTimeTip < sendTime - TIME_TIP_GAP_MS) {
|
||||
conversation.messages.push({
|
||||
id: 0,
|
||||
clientMessageId: `tip-${sendTime}`,
|
||||
type: ImMessageType.TIP_TIME,
|
||||
content: '',
|
||||
status: ImMessageStatus.UNREAD,
|
||||
sendTime,
|
||||
senderId: 0,
|
||||
senderNickName: '',
|
||||
targetId: conversationInfo.targetId,
|
||||
selfSend: false
|
||||
})
|
||||
conversation.lastTimeTip = sendTime
|
||||
}
|
||||
|
||||
// 3.2 根据 id 插入到正确位置(防止乱序);tip 消息 / 本地临时消息直接追加末尾
|
||||
let insertIndex = conversation.messages.length
|
||||
if (messageInfo.id) {
|
||||
for (let index = 0; index < conversation.messages.length; index++) {
|
||||
const existing = conversation.messages[index]
|
||||
// TIP_TIME 没有 id,不参与排序
|
||||
if (existing.type === ImMessageType.TIP_TIME) {
|
||||
continue
|
||||
}
|
||||
if (existing.id && messageInfo.id < existing.id) {
|
||||
insertIndex = index
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
conversation.messages.splice(insertIndex, 0, messageInfo)
|
||||
|
||||
// 4.1 更新游标
|
||||
this.updateMaxId(conversationInfo.type, messageInfo.id)
|
||||
|
||||
// 4.2 持久化到 localStorage
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/** 根据消息类型计算会话列表最后一条摘要 */
|
||||
resolveLastContent(messageInfo: Message): string {
|
||||
switch (messageInfo.type) {
|
||||
case ImMessageType.IMAGE:
|
||||
return '[图片]'
|
||||
case ImMessageType.FILE:
|
||||
return '[文件]'
|
||||
case ImMessageType.VOICE:
|
||||
return '[语音]'
|
||||
case ImMessageType.VIDEO:
|
||||
return '[视频]'
|
||||
case ImMessageType.RECALL:
|
||||
return buildRecallTip(messageInfo.senderNickName, messageInfo.selfSend)
|
||||
case ImMessageType.TEXT:
|
||||
case ImMessageType.TIP_TEXT:
|
||||
return parseMessage<TextMessage>(messageInfo.content)?.content ?? ''
|
||||
default:
|
||||
return parseMessage<TextMessage>(messageInfo.content)?.content ?? ''
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据 clientMessageId 更新消息状态
|
||||
*
|
||||
* 乐观更新回填:本地先以 SENDING 状态插入临时消息(id=0 + clientMessageId),
|
||||
* 待服务端返回后再用此方法回填真实 id、sendTime、status 等字段。
|
||||
*/
|
||||
updateMessageState(
|
||||
conversationType: number,
|
||||
targetId: number,
|
||||
clientMessageId: string,
|
||||
updates: Partial<Message>
|
||||
) {
|
||||
const conversation = this.findConversation(conversationType, targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
const message = conversation.messages.find((item) => item.clientMessageId === clientMessageId)
|
||||
if (!message) {
|
||||
return
|
||||
}
|
||||
Object.assign(message, updates)
|
||||
if (updates.id) {
|
||||
this.updateMaxId(conversationType, updates.id)
|
||||
}
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/**
|
||||
* 撤回消息:将原消息 type 改为 RECALL,并刷新会话摘要
|
||||
* 对应后端 RECALL 事件:按原 messageId 更新
|
||||
*/
|
||||
applyRecall(
|
||||
conversationType: number,
|
||||
targetId: number,
|
||||
messageId: number,
|
||||
senderNickName: string,
|
||||
selfSend: boolean
|
||||
) {
|
||||
const conversation = this.findConversation(conversationType, targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
const message = conversation.messages.find((item) => item.id === messageId)
|
||||
if (!message) {
|
||||
return
|
||||
}
|
||||
message.type = ImMessageType.RECALL
|
||||
message.status = ImMessageStatus.RECALL
|
||||
message.content = JSON.stringify({
|
||||
content: buildRecallTip(senderNickName, selfSend)
|
||||
})
|
||||
// 最后一条消息是刚撤回的,才更新会话摘要
|
||||
if (conversation.messages[conversation.messages.length - 1]?.id === messageId) {
|
||||
conversation.lastContent = buildRecallTip(senderNickName, selfSend)
|
||||
}
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/** 处理对方已读 / 群回执:更新发送方自己消息的 status / readCount / receiptStatus */
|
||||
applyReadReceipt(options: {
|
||||
conversationType: number
|
||||
targetId: number
|
||||
// 私聊:把和该好友的「自己发送的」消息标为已读
|
||||
markPrivateRead?: boolean
|
||||
// 群聊:针对单条消息的回执刷新
|
||||
groupMessageId?: number
|
||||
readCount?: number
|
||||
receiptStatus?: number
|
||||
}) {
|
||||
const conversation = this.findConversation(options.conversationType, options.targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
if (options.conversationType === ImConversationType.PRIVATE && options.markPrivateRead) {
|
||||
conversation.messages.forEach((message) => {
|
||||
if (message.selfSend && message.status !== ImMessageStatus.RECALL) {
|
||||
message.status = ImMessageStatus.READ
|
||||
}
|
||||
})
|
||||
} else if (options.conversationType === ImConversationType.GROUP && options.groupMessageId) {
|
||||
const message = conversation.messages.find((item) => item.id === options.groupMessageId)
|
||||
if (message) {
|
||||
if (options.readCount !== undefined) {
|
||||
message.readCount = options.readCount
|
||||
}
|
||||
if (options.receiptStatus !== undefined) {
|
||||
message.receiptStatus = options.receiptStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/**
|
||||
* 从本地消息列表移除一条消息(右键"删除";不同步后端)
|
||||
* 按 id 优先匹配;若 id 为 0(本地发送中),则按 clientMessageId 匹配
|
||||
*/
|
||||
removeLocalMessage(
|
||||
conversationType: number,
|
||||
targetId: number,
|
||||
key: { id?: number; clientMessageId?: string }
|
||||
) {
|
||||
const conversation = this.findConversation(conversationType, targetId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
const index = conversation.messages.findIndex((message) => {
|
||||
if (key.id && message.id && message.id === key.id) {
|
||||
return true
|
||||
}
|
||||
return !!(key.clientMessageId && message.clientMessageId && message.clientMessageId === key.clientMessageId)
|
||||
})
|
||||
if (index < 0) {
|
||||
return
|
||||
}
|
||||
conversation.messages.splice(index, 1)
|
||||
// 如果删的是最后一条,刷新摘要
|
||||
if (index === conversation.messages.length) {
|
||||
const last = conversation.messages[conversation.messages.length - 1]
|
||||
conversation.lastContent = last ? this.resolveLastContent(last) : ''
|
||||
conversation.lastSendTime = last?.sendTime || conversation.lastSendTime
|
||||
conversation.senderNickName = last?.senderNickName || ''
|
||||
}
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/**
|
||||
* 当前会话全部标记为已读(切换会话 / 手动触发)
|
||||
* 只处理「对方发来的、尚未读」的消息
|
||||
*/
|
||||
markActiveAsRead() {
|
||||
if (!this.activeConversation) {
|
||||
return
|
||||
}
|
||||
this.activeConversation.unreadCount = 0
|
||||
this.activeConversation.atMe = false
|
||||
this.activeConversation.atAll = false
|
||||
this.activeConversation.messages.forEach((message) => {
|
||||
if (!message.selfSend && message.status === ImMessageStatus.UNREAD) {
|
||||
message.status = ImMessageStatus.READ
|
||||
}
|
||||
})
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/** 更新 privateMessageMaxId / groupMessageMaxId 游标 */
|
||||
updateMaxId(conversationType: number, messageId?: number) {
|
||||
if (!messageId) {
|
||||
return
|
||||
}
|
||||
if (conversationType === ImConversationType.PRIVATE) {
|
||||
if (messageId > this.privateMessageMaxId) {
|
||||
this.privateMessageMaxId = messageId
|
||||
}
|
||||
} else if (conversationType === ImConversationType.GROUP) {
|
||||
if (messageId > this.groupMessageMaxId) {
|
||||
this.groupMessageMaxId = messageId
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** 离线消息加载完后重排:按 lastSendTime 倒序并持久化 */
|
||||
refreshConversations() {
|
||||
this.conversations.sort((a, b) => b.lastSendTime - a.lastSendTime)
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
/** 根据 friendStore 最新的好友信息同步对应私聊会话的展示名 / 头像 / 免打扰 */
|
||||
updateConversationFromFriend(friendId: number, info: { nickName?: string; showImage?: string; muted?: boolean }) {
|
||||
const conversation = this.findConversation(ImConversationType.PRIVATE, friendId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
let changed = false
|
||||
if (info.nickName && conversation.showName !== info.nickName) {
|
||||
conversation.showName = info.nickName
|
||||
changed = true
|
||||
}
|
||||
if (info.showImage !== undefined && conversation.showImage !== info.showImage) {
|
||||
conversation.showImage = info.showImage || ''
|
||||
changed = true
|
||||
}
|
||||
if (info.muted !== undefined && conversation.muted !== info.muted) {
|
||||
conversation.muted = info.muted
|
||||
changed = true
|
||||
}
|
||||
if (changed) {
|
||||
this.saveToStorage()
|
||||
}
|
||||
},
|
||||
|
||||
/** 根据 groupStore 最新的群信息同步对应群聊会话的展示名 / 头像 / 免打扰 */
|
||||
updateConversationFromGroup(groupId: number, info: { name?: string; showImage?: string; muted?: boolean }) {
|
||||
const conversation = this.findConversation(ImConversationType.GROUP, groupId)
|
||||
if (!conversation) {
|
||||
return
|
||||
}
|
||||
let changed = false
|
||||
if (info.name && conversation.showName !== info.name) {
|
||||
conversation.showName = info.name
|
||||
changed = true
|
||||
}
|
||||
if (info.showImage !== undefined && conversation.showImage !== info.showImage) {
|
||||
conversation.showImage = info.showImage || ''
|
||||
changed = true
|
||||
}
|
||||
if (info.muted !== undefined && conversation.muted !== info.muted) {
|
||||
conversation.muted = info.muted
|
||||
changed = true
|
||||
}
|
||||
if (changed) {
|
||||
this.saveToStorage()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const useConversationStoreWithOut = () => {
|
||||
return useConversationStore(store)
|
||||
}
|
||||
Loading…
Reference in New Issue