292 lines
7.6 KiB
JavaScript
292 lines
7.6 KiB
JavaScript
/**
|
|
* 聊天状态管理模块
|
|
* Requirements: 7.1, 7.2, 13.5
|
|
*/
|
|
|
|
import { defineStore } from 'pinia'
|
|
|
|
/**
|
|
* 消息类型枚举
|
|
* 与后端 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
|
|
}),
|
|
|
|
getters: {
|
|
/**
|
|
* 获取当前会话的消息列表
|
|
*/
|
|
currentMessages: (state) => {
|
|
if (!state.currentSessionId) return []
|
|
return state.messagesBySession[state.currentSessionId] || []
|
|
},
|
|
|
|
/**
|
|
* 是否有未读消息
|
|
* Property 22: Unread Badge Display - 未读消息数 > 0 时显示红点
|
|
*/
|
|
hasUnreadMessages: (state) => state.totalUnreadCount > 0,
|
|
|
|
/**
|
|
* 获取指定会话的未读数
|
|
*/
|
|
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
|
|
)
|
|
},
|
|
|
|
/**
|
|
* 设置当前会话
|
|
* @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
|
|
}
|
|
}
|
|
})
|