Files
nl-um-vue-ts/src/stores/conversation.ts

114 lines
3.7 KiB
TypeScript
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.
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
}
})