2025-03-28 15:19:42 +08:00
|
|
|
|
import {
|
|
|
|
|
defineStore
|
|
|
|
|
} from 'pinia';
|
|
|
|
|
import {
|
|
|
|
|
reactive,
|
2025-04-10 10:59:25 +08:00
|
|
|
|
ref,
|
|
|
|
|
toRaw
|
2025-03-28 15:19:42 +08:00
|
|
|
|
} 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 {
|
2025-04-16 14:24:06 +08:00
|
|
|
|
if (config.OnlyUseCachedDB) return;
|
|
|
|
|
console.warn('本地数据库不存在数据')
|
2025-04-10 10:59:25 +08:00
|
|
|
|
getHistory('refresh')
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
}, 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) {
|
2025-04-10 10:59:25 +08:00
|
|
|
|
|
2025-03-28 15:19:42 +08:00
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
try {
|
|
|
|
|
toggleTyping(true);
|
2025-04-10 10:59:25 +08:00
|
|
|
|
const customDataID = 'message_' + UUID.generate()
|
2025-03-28 15:19:42 +08:00
|
|
|
|
const params = {
|
|
|
|
|
data: text,
|
|
|
|
|
sessionId: chatSessionID.value,
|
2025-04-10 10:59:25 +08:00
|
|
|
|
dataId: customDataID
|
2025-03-28 15:19:42 +08:00
|
|
|
|
};
|
|
|
|
|
if (fileUrls && fileUrls.length) {
|
2025-03-29 20:46:23 +08:00
|
|
|
|
params['fileUrl'] = fileUrls.map((item) => item.url);
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
2025-04-10 10:59:25 +08:00
|
|
|
|
// ------>
|
|
|
|
|
const MsgData = {
|
|
|
|
|
text: text,
|
|
|
|
|
self: true,
|
|
|
|
|
displayText: text,
|
|
|
|
|
files: fileUrls
|
|
|
|
|
};
|
|
|
|
|
addMessage(MsgData); // 添加message数据
|
|
|
|
|
// <------
|
2025-03-28 15:19:42 +08:00
|
|
|
|
const newMsg = {
|
2025-04-10 10:59:25 +08:00
|
|
|
|
text: '', // 存储原始结构化内容
|
2025-03-28 15:19:42 +08:00
|
|
|
|
self: false,
|
2025-04-10 10:59:25 +08:00
|
|
|
|
displayText: '', // 用于流式渲染展示
|
|
|
|
|
dataId: customDataID
|
2025-03-28 15:19:42 +08:00
|
|
|
|
};
|
2025-04-16 14:24:06 +08:00
|
|
|
|
console.log(messages.value)
|
2025-03-28 15:19:42 +08:00
|
|
|
|
const index = messages.value.length;
|
2025-03-29 20:46:23 +08:00
|
|
|
|
messages.value.push(newMsg);
|
|
|
|
|
|
|
|
|
|
const rawParts = Array.isArray(text) ? text : [text]; // 统一处理
|
2025-03-28 15:19:42 +08:00
|
|
|
|
|
2025-03-29 20:46:23 +08:00
|
|
|
|
// 用于追加每个部分的流式数据
|
|
|
|
|
let partIndex = 0;
|
2025-03-28 15:19:42 +08:00
|
|
|
|
|
|
|
|
|
function handleUnload() {
|
2025-03-29 20:46:23 +08:00
|
|
|
|
newMsg.parentGroupId = chatSessionID.value;
|
2025-04-16 14:24:06 +08:00
|
|
|
|
baseDB.db.add(massageName.value, newMsg).then((id) => {
|
|
|
|
|
messages.value[index] = {
|
|
|
|
|
...newMsg,
|
|
|
|
|
id
|
|
|
|
|
};
|
|
|
|
|
});
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
window.addEventListener("unload", handleUnload);
|
|
|
|
|
|
|
|
|
|
function onDataReceived(data) {
|
2025-03-29 20:46:23 +08:00
|
|
|
|
// 支持追加多个部分
|
2025-04-10 10:59:25 +08:00
|
|
|
|
newMsg.text += data;
|
|
|
|
|
newMsg.displayText += data;
|
2025-03-28 15:19:42 +08:00
|
|
|
|
messages.value[index] = {
|
|
|
|
|
...newMsg
|
2025-03-29 20:46:23 +08:00
|
|
|
|
};
|
|
|
|
|
progress && progress();
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onError(error) {
|
2025-03-29 20:46:23 +08:00
|
|
|
|
msg('服务响应异常');
|
2025-03-28 15:19:42 +08:00
|
|
|
|
reject(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onComplete() {
|
|
|
|
|
messages.value[index] = {
|
|
|
|
|
...newMsg
|
|
|
|
|
};
|
|
|
|
|
toggleTyping(false);
|
|
|
|
|
window.removeEventListener("unload", handleUnload);
|
2025-03-29 20:46:23 +08:00
|
|
|
|
handleUnload();
|
|
|
|
|
resolve();
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-03-29 20:46:23 +08:00
|
|
|
|
$api.streamRequest('/chat', params, onDataReceived, onError, onComplete);
|
2025-03-28 15:19:42 +08:00
|
|
|
|
} catch (err) {
|
|
|
|
|
console.log(err);
|
|
|
|
|
reject(err);
|
|
|
|
|
}
|
2025-03-29 20:46:23 +08:00
|
|
|
|
});
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 状态控制
|
|
|
|
|
function addNewDialogue() {
|
|
|
|
|
chatSessionID.value = ''
|
|
|
|
|
messages.value = []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function changeDialogue(item) {
|
|
|
|
|
chatSessionID.value = item.sessionId
|
|
|
|
|
initMessage(item.sessionId)
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-10 10:59:25 +08:00
|
|
|
|
// 云端数据
|
2025-04-16 14:24:06 +08:00
|
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
2025-04-10 10:59:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-03-28 15:19:42 +08:00
|
|
|
|
// 云端数据
|
|
|
|
|
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) {
|
2025-04-16 14:24:06 +08:00
|
|
|
|
baseDB.db.add(massageName.value, list).then((ids) => {
|
|
|
|
|
messages.value = listAddId(list, ids)
|
|
|
|
|
});
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
}
|
2025-04-07 09:10:55 +08:00
|
|
|
|
if (obj.type === 'tool') {
|
|
|
|
|
console.log(obj)
|
|
|
|
|
}
|
2025-03-28 15:19:42 +08:00
|
|
|
|
}
|
|
|
|
|
arr.push({
|
|
|
|
|
parentGroupId: sessionId,
|
|
|
|
|
displayText: text,
|
|
|
|
|
self: self,
|
|
|
|
|
text: text,
|
2025-04-16 14:24:06 +08:00
|
|
|
|
userBadFeedback: element.userBadFeedback || '',
|
2025-03-28 15:19:42 +08:00
|
|
|
|
dataId: element.dataId,
|
|
|
|
|
files,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
return arr
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-16 14:24:06 +08:00
|
|
|
|
|
|
|
|
|
function listAddId(list, ids) {
|
|
|
|
|
return list.map((item, index) => ({
|
|
|
|
|
...item,
|
|
|
|
|
id: ids[index] || ids
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-28 15:19:42 +08:00
|
|
|
|
return {
|
|
|
|
|
messages,
|
|
|
|
|
isTyping,
|
|
|
|
|
textInput,
|
|
|
|
|
chatSessionID,
|
|
|
|
|
tabeList,
|
|
|
|
|
init,
|
|
|
|
|
toggleTyping,
|
|
|
|
|
addTabel,
|
|
|
|
|
addNewDialogue,
|
|
|
|
|
changeDialogue,
|
|
|
|
|
getStearm,
|
|
|
|
|
getHistory,
|
2025-04-10 10:59:25 +08:00
|
|
|
|
badFeedback
|
2025-03-28 15:19:42 +08:00
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function safeParseJSON(data) {
|
|
|
|
|
try {
|
|
|
|
|
return JSON.parse(data);
|
|
|
|
|
} catch {
|
|
|
|
|
return null; // 解析失败,返回 null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default useChatGroupDBStore
|