349 lines
9.1 KiB
JavaScript
349 lines
9.1 KiB
JavaScript
/**
|
||
* 聊天状态管理模块
|
||
* 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 })
|
||
}
|
||
}
|
||
})
|