import { defineStore } from 'pinia'; import { reactive, ref } from 'vue' import IndexedDBHelper from '@/common/IndexedDBHelper.js' import baseDB from './BaseDBStore'; import { msg, CloneDeep, $api, formatDate, insertSortData } from '../common/globalFunction'; import { UUID } from '../lib/uuid-min'; import config from '../config'; const useChatGroupDBStore = defineStore("messageGroup", () => { const tableName = ref('messageGroup') const massageName = ref('messages') const messages = ref([]) // 消息列表 const isTyping = ref(false) // 是否正在输入 const textInput = ref('') // tabel const tabeList = ref([]) const chatSessionID = ref('') const lastDateRef = ref('') // const groupPages = reactive({ // page: 0, // total: 0, // maxPage: 2, // pageSize: 50, // }) async function init() { // 获取所有数据 setTimeout(async () => { if (!baseDB.isDBReady) await baseDB.initDB(); const result = await baseDB.db.getAll(tableName.value); // 1、判断是否有数据,没数据请求服务器 if (result.length) { console.warn('本地数据库存在数据') const list = result.reverse() const [table, lastData] = insertSortData(list) tabeList.value = table const tabelRow = list[0] chatSessionID.value = tabelRow.sessionId initMessage(tabelRow.sessionId) } else { console.warn('本地数据库存在数据') getHistory('refresh') } }, 1000) } async function initMessage(sessionId) { if (!baseDB.isDBReady) await baseDB.initDB(); chatSessionID.value = sessionId const list = await baseDB.db.queryByField(massageName.value, 'parentGroupId', sessionId); if (list.length) { console.log('本地数据库存在该对话数据', list) messages.value = list } else { console.log('本地数据库不存在该对话数据') getHistoryRecord('refresh') } } async function addMessage(payload) { if (!chatSessionID.value) { return msg('请创建对话') } const params = { ...payload, parentGroupId: chatSessionID.value, files: payload.files || [], } messages.value.push(params); addMessageIndexdb(params) } function toggleTyping(status) { isTyping.value = status } async function addTabel(text) { if (!baseDB.isDBReady) await baseDB.initDB(); const uuid = UUID.generate() // 对话sessionId let payload = { title: text, createTime: formatDate(Date.now()), sessionId: uuid } const id = await baseDB.db.add(tableName.value, payload); const list = await baseDB.db.getAll(tableName.value); chatSessionID.value = uuid const [result, lastData] = insertSortData(list) tabeList.value = result return id } async function addMessageIndexdb(payload) { console.log(payload) return await baseDB.db.add(massageName.value, payload); } async function getStearm(text, fileUrls = [], progress) { return new Promise((resolve, reject) => { try { toggleTyping(true); const params = { data: text, sessionId: chatSessionID.value, }; if (fileUrls && fileUrls.length) { params['fileUrl'] = fileUrls.map((item) => item.url) } const newMsg = { text: '', // 存放完整的流式数据 self: false, displayText: '' // 用于前端逐步显示 }; const index = messages.value.length; messages.value.push(newMsg); // 先占位 let fullText = ''; // 存储完整的响应内容 function handleUnload() { newMsg.text = fullText newMsg.parentGroupId = chatSessionID.value baseDB.db.add(massageName.value, newMsg); } // 添加事件监听 window.addEventListener("unload", handleUnload); // 实时数据渲染 function onDataReceived(data) { // const parsedData = safeParseJSON(data); fullText += data; // 累积完整内容 newMsg.displayText += data; // 逐步更新 UI messages.value[index] = { ...newMsg }; // 触发视图更新 progress && progress() } // 异常处理 function onError(error) { console.error('请求异常:', error); msg('服务响应异常') reject(error); } // 完成处理 function onComplete() { newMsg.text = fullText; // 保存完整响应 messages.value[index] = { ...newMsg }; toggleTyping(false); window.removeEventListener("unload", handleUnload); handleUnload() resolve && resolve(); } $api.streamRequest('/chat', params, onDataReceived, onError, onComplete) } catch (err) { console.log(err); reject(err); } }) } // 状态控制 function addNewDialogue() { chatSessionID.value = '' messages.value = [] } function changeDialogue(item) { chatSessionID.value = item.sessionId initMessage(item.sessionId) } // 云端数据 function getHistory() { $api.chatRequest('/getHistory').then((res) => { if (!res.data.list.length) return let tabel = parseHistory(res.data.list) if (tabel && tabel.length) { const tabelRow = tabel[0] // 默认第一个 const [result, lastData] = insertSortData(tabel) // console.log('getHistory insertSortData', result, lastData) chatSessionID.value = tabelRow.sessionId tabeList.value = result getHistoryRecord(false) baseDB.db.add(tableName.value, tabel); lastDateRef.value = lastData } }) } function getHistoryRecord(loading = true) { const params = { sessionId: chatSessionID.value } $api.chatRequest('/detail', params, 'GET', loading).then((res) => { console.log('detail:', res.data) let list = parseHistoryDetail(res.data.list, chatSessionID.value) if (list.length) { messages.value = list baseDB.db.add(massageName.value, list); } console.log('解析后:', list) }).catch(() => { msg('请求出现异常,请联系工作人员') }) } // 解析器 function parseHistory(list) { return list.map((item) => ({ title: item.title, createTime: item.updateTime, sessionId: item.chatId })) } function parseHistoryDetail(list, sessionId) { const arr = [] for (let i = 0; i < list.length; i++) { const element = list[i]; const self = element.obj !== 'AI' let text = '' let files = [] for (let j = 0; j < element.value.length; j++) { const obj = element.value[j]; if (obj.type === 'text') { text += obj.text.content } if (obj.type === 'file') { files.push(obj.file) } } arr.push({ parentGroupId: sessionId, displayText: text, self: self, text: text, dataId: element.dataId, files, }) } return arr } return { messages, isTyping, textInput, chatSessionID, addMessage, tabeList, init, toggleTyping, addTabel, addNewDialogue, changeDialogue, getStearm, getHistory, }; }); function safeParseJSON(data) { try { return JSON.parse(data); } catch { return null; // 解析失败,返回 null } } export default useChatGroupDBStore