import { defineStore } from 'pinia'; import { reactive, ref, toRaw } 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('') 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 { if (config.OnlyUseCachedDB) return; 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) { return await baseDB.db.add(massageName.value, payload); } async function getStearm(text, fileUrls = [], progress) { return new Promise((resolve, reject) => { try { toggleTyping(true); const customDataID = 'message_' + UUID.generate() const params = { data: text, sessionId: chatSessionID.value, dataId: customDataID }; if (fileUrls && fileUrls.length) { params['fileUrl'] = fileUrls.map((item) => item.url); } // ------> const MsgData = { text: text, self: true, displayText: text, files: fileUrls }; addMessage(MsgData); // 添加message数据 // <------ const newMsg = { text: '', // 存储原始结构化内容 self: false, displayText: '', // 用于流式渲染展示 dataId: customDataID }; console.log(messages.value) const index = messages.value.length; messages.value.push(newMsg); const rawParts = Array.isArray(text) ? text : [text]; // 统一处理 // 用于追加每个部分的流式数据 let partIndex = 0; function handleUnload() { newMsg.parentGroupId = chatSessionID.value; baseDB.db.add(massageName.value, newMsg).then((id) => { messages.value[index] = { ...newMsg, id }; }); } window.addEventListener("unload", handleUnload); function onDataReceived(data) { // 支持追加多个部分 newMsg.text += data; newMsg.displayText += data; messages.value[index] = { ...newMsg }; progress && progress(); } function onError(error) { msg('服务响应异常'); reject(error); } function onComplete() { messages.value[index] = { ...newMsg }; toggleTyping(false); window.removeEventListener("unload", handleUnload); handleUnload(); 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 badFeedback(msgs, content = '') { return new Promise((resolve, reject) => { if (!msgs.dataId) { return msg('旧数据,没有dataId') } let parmas = { dataId: msgs.dataId, sessionId: msgs.parentGroupId, userBadFeedback: content, } const dbData = { ...toRaw(msgs), userBadFeedback: content, } $api.chatRequest('/stepped', parmas, 'POST').then((res) => { baseDB.db.update(massageName.value, dbData) // 更新本地数据库 messages.value.forEach((item) => { if (item.id === dbData.id) { item.userBadFeedback = content resolve() } }) }) }) } // 云端数据 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) => { let list = parseHistoryDetail(res.data.list, chatSessionID.value) if (list.length) { baseDB.db.add(massageName.value, list).then((ids) => { messages.value = listAddId(list, ids) }); } 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) } if (obj.type === 'tool') { console.log(obj) } } arr.push({ parentGroupId: sessionId, displayText: text, self: self, text: text, userBadFeedback: element.userBadFeedback || '', dataId: element.dataId, files, }) } return arr } function listAddId(list, ids) { return list.map((item, index) => ({ ...item, id: ids[index] || ids })) } return { messages, isTyping, textInput, chatSessionID, tabeList, init, toggleTyping, addTabel, addNewDialogue, changeDialogue, getStearm, getHistory, badFeedback }; }); function safeParseJSON(data) { try { return JSON.parse(data); } catch { return null; // 解析失败,返回 null } } export default useChatGroupDBStore