| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /**
- * 聊天全局状态:会话列表、各会话消息列表,供 composables 与页面共享
- */
- import { reactive } from 'vue'
- export const chatStore = reactive({
- // 会话列表(来自 getContacts)
- contacts: [],
- loadingContacts: false,
- /** 最近一次拉取会话列表是否因网络/接口失败(用于空列表时区分「请下拉刷新」与「暂无消息」) */
- contactsFetchFailed: false,
- // 按 contactId 存消息列表
- messages: {},
- // 已加载过历史的 contactId 集合,避免重复拉取
- loadedContactIds: {},
- // 当前正在查看的会话,用于前台/后台消息通知判断
- activeContactId: '',
- // 某会话是否正在加载更多
- loadingMore: {},
- /** 登出 / 清空 token 时重置,避免换账号仍显示上一用户会话与消息 */
- reset() {
- this.contacts = []
- this.loadingContacts = false
- this.contactsFetchFailed = false
- this.messages = {}
- this.loadedContactIds = {}
- this.activeContactId = ''
- this.loadingMore = {}
- this.setTabBarUnreadFromServer(0)
- },
- setContacts(list) {
- this.contacts = list || []
- },
- /** 仅更新某会话在列表中的最后一条预览与时间(WS 收到新消息时本地更新,不整表刷新) */
- updateContactPreview(contactId, { lastMessage, time }) {
- const id = String(contactId)
- const list = this.contacts || []
- const idx = list.findIndex((c) => String(c.user_id || c.id) === id)
- if (idx === -1) return
- const next = list.slice()
- next[idx] = { ...next[idx], lastMessage: lastMessage ?? next[idx].lastMessage, time: time ?? next[idx].time }
- this.contacts = next
- },
- setMessagesForContact(contactId, list, append = false) {
- const id = String(contactId)
- if (!this.messages[id]) this.messages[id] = []
- if (append) {
- this.messages[id].push(...list)
- } else {
- const current = this.messages[id] || []
- const tempMessages = current.filter((m) => m.tempId != null)
- // 合并接口历史与 store 里已有消息(含 WS 推送),避免点进会话时把实时收到的消息冲掉
- const existingStable = current.filter((m) => !m.tempId)
- const apiList = list || []
- const seen = new Set()
- const merged = []
- for (const m of [...apiList, ...existingStable]) {
- const k = String(m.id || m.tempId || '')
- if (seen.has(k)) continue
- seen.add(k)
- merged.push(m)
- }
- merged.sort((a, b) => {
- const ta = (a.createdAt && new Date(a.createdAt).getTime()) || 0
- const tb = (b.createdAt && new Date(b.createdAt).getTime()) || 0
- return ta - tb
- })
- this.messages[id] = [...merged, ...tempMessages]
- }
- },
- prependMessages(contactId, list) {
- const id = String(contactId)
- if (!this.messages[id]) this.messages[id] = []
- const merged = (list || []).concat(this.messages[id])
- // 按 id 去重,保留首次出现(历史在前,避免重复)
- const seen = new Set()
- this.messages[id] = merged.filter((m) => {
- const k = m.id || m.tempId
- if (seen.has(k)) return false
- seen.add(k)
- return true
- })
- },
- appendMessage(contactId, message) {
- const id = String(contactId)
- const prev = this.messages[id] || []
- this.messages[id] = [...prev, message]
- },
- replaceTempMessage(contactId, tempId, serverMessage) {
- const id = String(contactId)
- const list = this.messages[id]
- if (!list || !list.length) return
- const idx = list.findIndex((m) => m.id === tempId || m.tempId === tempId)
- if (idx !== -1) {
- this.messages[id] = [...list.slice(0, idx), serverMessage, ...list.slice(idx + 1)]
- }
- },
- /** 按 id / tempId 移除一条(如再次提醒发送失败时撤回临时消息) */
- removeMessage(contactId, messageId) {
- const id = String(contactId)
- const list = this.messages[id]
- if (!list || !list.length) return
- this.messages[id] = list.filter((m) => m.id !== messageId && m.tempId !== messageId)
- },
- /** 更新某条消息(如 status: 'sending' / 'failed') */
- updateMessage(contactId, tempIdOrId, updates) {
- const id = String(contactId)
- const list = this.messages[id]
- if (!list || !list.length) return
- const idx = list.findIndex((m) => m.id === tempIdOrId || m.tempId === tempIdOrId)
- if (idx !== -1) {
- const next = list.slice()
- next[idx] = { ...next[idx], ...updates }
- this.messages[id] = next
- }
- },
- markContactLoaded(contactId) {
- this.loadedContactIds[String(contactId)] = true
- },
- hasContactLoaded(contactId) {
- return !!this.loadedContactIds[String(contactId)]
- },
- setActiveContact(contactId) {
- this.activeContactId = contactId ? String(contactId) : ''
- },
- /**
- * 底部「消息」Tab 角标(index 0),数值来自 GET /messages/unread-count
- * @param {number|string} n - 未读总数
- */
- setTabBarUnreadFromServer(n) {
- const total = Math.max(0, Number(n) || 0)
- try {
- if (total <= 0) {
- uni.removeTabBarBadge({ index: 0 })
- } else {
- uni.setTabBarBadge({ index: 0, text: total > 99 ? '99+' : String(total) })
- }
- } catch (e) {
- // 非 Tab 页或未就绪时可能报错,忽略
- }
- }
- })
|