114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
import { defineStore } from 'pinia'
|
||
import { ref, computed } from 'vue'
|
||
import type { Conversation } from '@/types/conversation'
|
||
import type { ChatMessage } from '@/types/api'
|
||
import * as conversationApi from '@/api/modules/conversation'
|
||
|
||
export const useConversationStore = defineStore('conversation', () => {
|
||
const conversations = ref<Conversation[]>([])
|
||
const loading = ref(false)
|
||
|
||
// 计算总未读数
|
||
const totalUnread = computed(() =>
|
||
conversations.value.reduce((acc, c) => acc + (c.is_muted ? 0 : c.unread_count), 0)
|
||
)
|
||
|
||
/**
|
||
* 初始化加载会话列表
|
||
*/
|
||
async function loadConversations() {
|
||
loading.value = true
|
||
try {
|
||
const list = await conversationApi.getConversationList()
|
||
// 后端返回的数据需要简单处理一下
|
||
conversations.value = list.map(c => ({
|
||
...c,
|
||
name: c.target_user?.name || '未知用户',
|
||
avatar: c.target_user?.avatar || '',
|
||
}))
|
||
} catch (error) {
|
||
console.error('Fetch conversations failed:', error)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理新消息 (发送或接收)
|
||
* 实时更新前端列表:这里只做前端 UI 层的兜底,后端已更新会话表
|
||
* @param isCurrentChat 是否是当前选中的聊天,如果是则不增加未读数
|
||
*/
|
||
function handleMessageUpdate(message: ChatMessage, isSelf: boolean, isCurrentChat: boolean = false) {
|
||
const targetId = isSelf ? message.receiver_user_id : message.sender_user_id
|
||
if (!targetId) return
|
||
|
||
let conv = conversations.value.find(c => c.target_id === targetId)
|
||
const summary = getMsgSummary(message)
|
||
const now = new Date(message.created_at || Date.now()).getTime()
|
||
|
||
if (conv) {
|
||
conv.last_message = summary
|
||
conv.last_time = now
|
||
// 如果不是自己发送的,且不是当前选中的聊天,且未设置免打扰,则增加未读数
|
||
if (!isSelf && !isCurrentChat && !conv.is_muted) {
|
||
conv.unread_count = (conv.unread_count || 0) + 1
|
||
}
|
||
} else {
|
||
// 新会话直接重新拉取,保证与后端一致
|
||
loadConversations()
|
||
return
|
||
}
|
||
|
||
sortConversations()
|
||
}
|
||
|
||
/**
|
||
* 增加未读数 (仅前端UI,用于收到消息且不在当前窗口时)
|
||
*/
|
||
function incrementUnread(targetId: string) {
|
||
const conv = conversations.value.find(c => c.target_id === targetId)
|
||
if (conv) {
|
||
conv.unread_count = (conv.unread_count || 0) + 1
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 清除未读数 (同步后端)
|
||
*/
|
||
async function clearUnread(targetId: string) {
|
||
const conv = conversations.value.find(c => c.target_id === targetId)
|
||
if (conv && conv.unread_count > 0) {
|
||
conv.unread_count = 0
|
||
// 调用后端接口
|
||
try {
|
||
await conversationApi.resetUnread(targetId)
|
||
} catch (e) { console.error(e) }
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 排序
|
||
*/
|
||
function sortConversations() {
|
||
conversations.value.sort((a, b) => {
|
||
if (a.is_top !== b.is_top) return a.is_top ? -1 : 1
|
||
return b.last_time - a.last_time
|
||
})
|
||
}
|
||
|
||
function getMsgSummary(msg: ChatMessage): string {
|
||
const types: Record<number, string> = { 1: '[图片]', 2: '[语音]', 3: '[视频]', 8: '[文件]', 6: '[通话]' }
|
||
return types[msg.message_type] || msg.content
|
||
}
|
||
|
||
return {
|
||
conversations,
|
||
loading,
|
||
totalUnread,
|
||
loadConversations,
|
||
handleMessageUpdate,
|
||
incrementUnread,
|
||
clearUnread
|
||
}
|
||
})
|