xiangyixiangqin/miniapp/store/chat.js
2026-02-06 17:58:15 +08:00

349 lines
9.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 聊天状态管理模块
* Requirements: 7.1, 7.2, 13.5
*/
import { defineStore } from 'pinia'
import { getUnreadCount as getChatUnreadCount } from '../api/chat.js'
import { getUnreadCount as getSystemUnreadCount } from '../api/message.js'
/**
* 消息类型枚举
* 与后端 MessageType 枚举保持一致
*/
export const MessageType = {
TEXT: 1, // 文本消息
VOICE: 2, // 语音消息
IMAGE: 3, // 图片消息
EXCHANGE_WECHAT: 4, // 交换微信请求
EXCHANGE_WECHAT_RESULT: 5, // 交换微信结果
EXCHANGE_PHOTO: 6, // 交换照片请求
EXCHANGE_PHOTO_RESULT: 7 // 交换照片结果
}
/**
* 消息状态枚举
*/
export const MessageStatus = {
SENDING: 0, // 发送中
SENT: 1, // 已发送
DELIVERED: 2, // 已送达
READ: 3, // 已读
FAILED: 4 // 发送失败
}
/**
* 聊天会话定义
* @typedef {Object} ChatSession
* @property {number} sessionId - 会话ID
* @property {number} targetUserId - 对方用户ID
* @property {string} targetNickname - 对方昵称
* @property {string} targetAvatar - 对方头像
* @property {string} lastMessage - 最后一条消息
* @property {string} lastMessageTime - 最后消息时间
* @property {number} unreadCount - 未读消息数
*/
/**
* 聊天消息定义
* @typedef {Object} ChatMessage
* @property {number} id - 消息ID
* @property {number} sessionId - 会话ID
* @property {number} senderId - 发送者ID
* @property {number} receiverId - 接收者ID
* @property {number} messageType - 消息类型
* @property {string} content - 消息内容
* @property {number} status - 消息状态
* @property {string} createTime - 创建时间
* @property {boolean} isMine - 是否是自己发送的
*/
export const useChatStore = defineStore('chat', {
state: () => ({
// 会话列表
sessions: [],
// 当前会话的消息列表 (按sessionId分组)
messagesBySession: {},
// 当前活跃的会话ID
currentSessionId: null,
// 总未读消息数
totalUnreadCount: 0,
// 系统消息未读数
systemUnreadCount: 0
}),
getters: {
/**
* 获取当前会话的消息列表
*/
currentMessages: (state) => {
if (!state.currentSessionId) return []
return state.messagesBySession[state.currentSessionId] || []
},
/**
* 是否有未读消息
* Property 22: Unread Badge Display - 未读消息数 > 0 时显示红点
*/
hasUnreadMessages: (state) => state.totalUnreadCount > 0,
/**
* 消息tab总未读数聊天 + 系统消息)
*/
messageBadgeCount: (state) => state.totalUnreadCount + state.systemUnreadCount,
/**
* 获取指定会话的未读数
*/
getSessionUnreadCount: (state) => (sessionId) => {
const session = state.sessions.find(s => s.sessionId === sessionId)
return session ? session.unreadCount : 0
},
/**
* 判断是否应该显示未读徽章
* Property 22: Unread Badge Display
* @param {number} unreadCount - 未读消息数
* @returns {boolean}
*/
shouldShowUnreadBadge: () => (unreadCount) => {
return unreadCount > 0
}
},
actions: {
/**
* 设置会话列表
* @param {Array<ChatSession>} sessions - 会话列表
*/
setSessions(sessions) {
this.sessions = sessions
this.updateTotalUnreadCount()
},
/**
* 更新总未读消息数
*/
updateTotalUnreadCount() {
this.totalUnreadCount = this.sessions.reduce(
(total, session) => total + (session.unreadCount || 0),
0
)
this.updateTabBarBadge()
},
/**
* 设置系统消息未读数
*/
setSystemUnreadCount(count) {
this.systemUnreadCount = count
this.updateTabBarBadge()
},
/**
* 更新底部导航栏消息tab的badge
*/
updateTabBarBadge() {
const total = this.messageBadgeCount
if (total > 0) {
uni.setTabBarBadge({
index: 1,
text: total > 99 ? '99+' : String(total)
})
} else {
uni.removeTabBarBadge({ index: 1 })
}
},
/**
* 从服务器获取所有未读数并更新badge
*/
async fetchAllUnreadCounts() {
try {
const [chatRes, sysRes] = await Promise.all([
getChatUnreadCount(),
getSystemUnreadCount()
])
if (chatRes?.code === 0) {
this.totalUnreadCount = chatRes.data || 0
}
if (sysRes?.code === 0) {
this.systemUnreadCount = sysRes.data?.unreadCount || 0
}
this.updateTabBarBadge()
} catch (e) {
console.error('获取未读数失败:', e)
}
},
/**
* 设置当前会话
* @param {number} sessionId - 会话ID
*/
setCurrentSession(sessionId) {
this.currentSessionId = sessionId
},
/**
* 设置会话的消息列表
* @param {number} sessionId - 会话ID
* @param {Array<ChatMessage>} messages - 消息列表
*/
setMessages(sessionId, messages) {
this.messagesBySession[sessionId] = messages
},
/**
* 添加新消息到会话
* @param {number} sessionId - 会话ID
* @param {ChatMessage} message - 消息
*/
addMessage(sessionId, message) {
if (!this.messagesBySession[sessionId]) {
this.messagesBySession[sessionId] = []
}
this.messagesBySession[sessionId].push(message)
// 更新会话的最后消息
this.updateSessionLastMessage(sessionId, message)
},
/**
* 更新会话的最后消息
* @param {number} sessionId - 会话ID
* @param {ChatMessage} message - 消息
*/
updateSessionLastMessage(sessionId, message) {
const session = this.sessions.find(s => s.sessionId === sessionId)
if (session) {
session.lastMessage = this.getMessagePreview(message)
session.lastMessageTime = message.createTime
}
},
/**
* 获取消息预览文本
* @param {ChatMessage} message - 消息
* @returns {string}
*/
getMessagePreview(message) {
switch (message.messageType) {
case MessageType.TEXT:
return message.content
case MessageType.VOICE:
return '[语音]'
case MessageType.IMAGE:
return '[图片]'
case MessageType.EXCHANGE_WECHAT:
return '[交换微信请求]'
case MessageType.EXCHANGE_PHOTO:
return '[交换照片请求]'
default:
return message.content || ''
}
},
/**
* 接收新消息
* @param {ChatMessage} message - 消息
*/
receiveMessage(message) {
const { sessionId } = message
// 添加消息到列表
this.addMessage(sessionId, message)
// 如果不是当前会话,增加未读数
if (sessionId !== this.currentSessionId) {
this.incrementUnreadCount(sessionId)
}
},
/**
* 增加会话未读数
* @param {number} sessionId - 会话ID
*/
incrementUnreadCount(sessionId) {
const session = this.sessions.find(s => s.sessionId === sessionId)
if (session) {
session.unreadCount = (session.unreadCount || 0) + 1
this.updateTotalUnreadCount()
}
},
/**
* 标记会话已读
* @param {number} sessionId - 会话ID
*/
markSessionAsRead(sessionId) {
const session = this.sessions.find(s => s.sessionId === sessionId)
if (session && session.unreadCount > 0) {
session.unreadCount = 0
this.updateTotalUnreadCount()
}
},
/**
* 发送消息(本地状态更新)
* @param {number} sessionId - 会话ID
* @param {Object} messageData - 消息数据
* @returns {ChatMessage} 创建的消息对象
*/
sendMessage(sessionId, messageData) {
const message = {
id: Date.now(), // 临时ID
sessionId,
senderId: messageData.senderId,
receiverId: messageData.receiverId,
messageType: messageData.messageType || MessageType.TEXT,
content: messageData.content,
status: MessageStatus.SENDING,
createTime: new Date().toISOString(),
isMine: true
}
this.addMessage(sessionId, message)
return message
},
/**
* 更新消息状态
* @param {number} sessionId - 会话ID
* @param {number} messageId - 消息ID
* @param {number} status - 新状态
*/
updateMessageStatus(sessionId, messageId, status) {
const messages = this.messagesBySession[sessionId]
if (messages) {
const message = messages.find(m => m.id === messageId)
if (message) {
message.status = status
}
}
},
/**
* 清空当前会话
*/
clearCurrentSession() {
this.currentSessionId = null
},
/**
* 重置聊天状态
*/
reset() {
this.sessions = []
this.messagesBySession = {}
this.currentSessionId = null
this.totalUnreadCount = 0
this.systemUnreadCount = 0
uni.removeTabBarBadge({ index: 1 })
}
}
})