chat-pc/src/store/modules/talk.ts
Phoenix c64a562913 refactor(db): 重构会话表主键结构并清理旧数据
- 将会话表主键从自增id改为index_name
- 添加数据库版本升级逻辑清理旧数据
- 更新所有相关操作方法使用新主键
- 添加详细的版本变更注释
2025-07-03 10:33:29 +08:00

267 lines
8.1 KiB
TypeScript

import { defineStore } from 'pinia'
import { ServeGetTalkList, ServeCreateTalkList } from '@/api/chat'
import { formatTalkItem, ttime, KEY_INDEX_NAME } from '@/utils/talk'
import { useEditorDraftStore } from './editor-draft'
import { ISession } from '@/types/chat'
import { getConversations, addOrUpdateConversation, deleteConversation, getConversation } from '@/utils/db'
interface TalkStoreState {
loadStatus: number
items: ISession[]
}
export const useTalkStore = defineStore('talk', {
state: (): TalkStoreState => {
return {
// 加载状态[1:未加载;2:加载中;3:加载完成;4:加载失败;]
loadStatus: 2,
// 会话列表
items: []
}
},
getters: {
// 过滤所有置顶对话列表
topItems: (state) => {
return state.items.filter((item: ISession) => item.is_top == 1)
},
// 对话列表
talkItems: (state) => {
return state.items.sort((a, b) => {
return ttime(b.updated_at) - ttime(a.updated_at)
})
},
// 消息未读数总计
talkUnreadNum: (state) => {
return state.items.reduce((total: number, item: ISession) => {
return total + item.unread_num
}, 0)
}
},
actions: {
findItem(index_name: string) {
return this.items.find((item: ISession) => item.index_name === index_name) as ISession
},
// 更新对话节点
async updateItem(params: any) {
const item = this.items.find((item) => item.index_name === params.index_name)
if (item) {
Object.assign(item, params)
// 同步更新本地数据库
try {
await addOrUpdateConversation(JSON.parse(JSON.stringify(item)))
} catch (error) {
console.error('更新本地会话失败:', error)
}
}
},
// 新增对话节点
async addItem(params: any) {
this.items = [params, ...this.items]
// 同步添加到本地数据库
try {
await addOrUpdateConversation(JSON.parse(JSON.stringify(params)))
} catch (error) {
console.error('添加本地会话失败:', error)
}
},
// 移除对话节点
async delItem(index_name: string) {
const i = this.items.findIndex((item) => item.index_name === index_name)
if (i >= 0) {
const item = this.items[i]
this.items.splice(i, 1)
// 同步从本地数据库删除
try {
// 从本地数据库中查找并删除会话
const [talkType, receiverId] = index_name.split('_')
const conversation = await getConversation(Number(talkType), Number(receiverId))
if (conversation && conversation.id) {
await deleteConversation(conversation.id, false) // 不删除相关消息
}
} catch (error) {
console.error('删除本地会话失败:', error)
}
}
this.items = [...this.items]
},
// 更新对话消息
async updateMessage(params: any) {
const item = this.items.find((item) => item.index_name === params.index_name)
if (item) {
item.unread_num++
item.msg_text = params.msg_text
item.updated_at = params.updated_at
// 同步更新本地数据库中的会话信息
try {
await addOrUpdateConversation(JSON.parse(JSON.stringify(item)))
} catch (error) {
console.error('更新本地会话消息失败:', error)
}
}
},
// 更新联系人备注
async setRemark(params: any) {
const item = this.items.find((item) => item.index_name === `1_${params.user_id}`)
if (item) {
item.remark = params.remark
// 同步更新本地数据库
try {
await addOrUpdateConversation(JSON.parse(JSON.stringify(item)))
} catch (error) {
console.error('更新本地联系人备注失败:', error)
}
}
},
// 加载会话列表
async loadTalkList() {
this.loadStatus = 2
try {
// 先从本地数据库加载会话列表
const localConversations = await getConversations()
if (localConversations && localConversations.length > 0) {
// 将本地会话列表转换为应用所需格式
this.items = localConversations.map((item: any) => {
// 确保本地存储的会话格式与应用一致
const value = formatTalkItem(item)
const draft = useEditorDraftStore().items[value.index_name]
if (draft) {
value.draft_text = JSON.parse(draft).text || ''
}
if (value.is_robot == 1) {
value.is_online = 1
}
return value
})
// 设置为加载完成状态,因为已从本地加载了数据,不需要等待服务器数据就可以显示
this.loadStatus = 3
}
// 从服务器获取最新会话列表
const resp = await ServeGetTalkList()
if (resp.code == 200) {
// 将服务器返回的会话列表转换为应用所需格式
const serverItems = resp.data.items.map((item: any) => {
const value = formatTalkItem(item)
const draft = useEditorDraftStore().items[value.index_name]
if (draft) {
value.draft_text = JSON.parse(draft).text || ''
}
if (value.is_robot == 1) {
value.is_online = 1
}
return value
})
// 更新状态和本地数据库
this.items = serverItems
console.log('serverItems',serverItems)
// 将最新的会话列表保存到本地数据库
for (const item of serverItems) {
await addOrUpdateConversation(item)
}
this.loadStatus = 3
} else {
// 如果服务器请求失败但本地有数据,保持使用本地数据
if (this.items.length === 0) {
this.loadStatus = 4
} else {
this.loadStatus = 3
}
}
} catch (error) {
console.error('加载会话列表失败:', error)
// 如果有本地数据,即使服务器请求失败也显示本地数据
if (this.items.length === 0) {
this.loadStatus = 4
} else {
this.loadStatus = 3
}
}
},
findTalkIndex(index_name: string) {
return this.items.findIndex((item: ISession) => item.index_name === index_name)
},
async toTalk(talk_type: number, receiver_id: number, router: any) {
const route = {
path: '/message',
query: {
v: new Date().getTime()
}
}
if (this.findTalkIndex(`${talk_type}_${receiver_id}`) >= 0) {
sessionStorage.setItem(KEY_INDEX_NAME, `${talk_type}_${receiver_id}`)
return router.push(route)
}
try {
// 先检查本地数据库中是否有该会话
const localConversation = await getConversation(talk_type, receiver_id)
if (localConversation) {
// 如果本地有该会话,直接添加到列表中
if (this.findTalkIndex(`${talk_type}_${receiver_id}`) === -1) {
this.addItem(formatTalkItem(localConversation))
}
sessionStorage.setItem(KEY_INDEX_NAME, `${talk_type}_${receiver_id}`)
return router.push(route)
}
// 如果本地没有,则从服务器创建
const { code, data, message } = await ServeCreateTalkList({
talk_type,
receiver_id
})
if (code == 200) {
const formattedItem = formatTalkItem(data)
if (this.findTalkIndex(`${talk_type}_${receiver_id}`) === -1) {
await this.addItem(formattedItem) // 使用 await 确保本地数据库同步更新
}
sessionStorage.setItem(KEY_INDEX_NAME, `${talk_type}_${receiver_id}`)
return router.push(route)
} else {
window['$message'].info(message)
}
} catch (error) {
console.error('创建会话失败:', error)
window['$message'].error('创建会话失败,请稍后再试')
}
}
}
})