// 消息数组 import { ref, reactive, nextTick, inject } from 'vue' import { storeToRefs } from 'pinia' import avator from '@/public/icon/32.png' import moment from 'moment' import { getFormKey, buildObjPrompt, getFileSummaryPrompt, formatMessage, sendMessage } from '../utils/ai-service.js' import { ElMessage } from 'element-plus' import { getPageInfo } from '../utils/index.js' import { mockData, mockData2 } from '../mock' import { useMsgStore } from '@/store/modules/msg' import { FunctionList } from '../mock' export function useMsg(scrollbar?: any) { const { messages, msgUuid } = storeToRefs(useMsgStore()) const indexTemp = ref(0) const taklToHtml = ref(false) const sendLoading = ref(false) const pageInfo = ref({}) const type = ref(FunctionList.File_Operation) const formMap = ref([]) // 获取父组件提供的 Hook 实例 const { useStore } = inject('indexedDBHook') as any const getFileSummary = async (file: any) => { const obj = reactive({ id: moment(), username: '用户1', rawContent: '', content: '解析文件中', timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), isSelf: false, avatar: avator, addToHistory: !taklToHtml.value }) try { sendLoading.value = true messages.value.push(obj) nextTick(() => scrollbar.value?.setScrollTop(99999)) const res = await getFileValue(file) console.log(res.data, file) await streamRes() } catch (error) { obj.content = '解析出错' } finally { sendLoading.value = false } } const getFormKeyAndValue = async (file: any, form?: any) => { // const obj = reactive({ // id: moment(), // username: '用户1', // rawContent: '', // content: '解析文件中', // timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), // isSelf: false, // avatar: avator, // addToHistory: !taklToHtml.value // }) try { sendLoading.value = true // messages.value.push(obj) const response = await getFormKey({ body: form, input_data: file }) return response } catch (error) { // obj.content = '解析出错' } finally { sendLoading.value = false } } // 发送消息 // const handleSend = async (msg: any) => { // if ( msg?.startsWith('/')) { // if (!taklToHtml.value) // return messages.value.push({ // id: messages.value.length + 1, // username: '用户1', // content: '请打开与页面对话!', // rawContent: '请打开与页面对话!', // timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), // isSelf: false, // avatar: avator, // addToHistory: false // }) // indexTemp.value = 0 // fetchRes(msg) // } // } async function awaitFindForm(obj: any) { return await new Promise((res, rej) => { chrome.runtime.sendMessage( { type: 'FROM_SIDE_PANEL_TO_GET_PAGE_FORM' }, ({ status, data }) => { if (status === 'error') { obj.content = '当前页面未找到表单' res({ status }) } if (status === 'ok') { obj.content = '请上传数据' res({ status, data }) } if (status === 'select') { obj.content = '检测到左侧页面中有多个表单,请选择要填写的表单。' function handle(message, sender, sendResponse) { if (message.type === 'TO_SIDE_PANEL_FORM_INFO') { console.log('收到一次性消息:', message.data) res({ status: 'ok', data: message.data }) obj.content = '请上传数据' console.log(565656) // 销毁监听器(确保只触发一次) chrome.runtime.onMessage.removeListener(handle) } } chrome.runtime.onMessage.addListener(handle) } } ) }) } const fetchRes = async (msg: any) => { indexTemp.value = 0 sendLoading.value = true const obj: any = reactive({ id: messages.value.length + 1, username: '用户1', content: '', timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), isSelf: false, avatar: avator, addToHistory: !taklToHtml.value }) messages.value.push(obj) msg = msg.split('/智能填表')[1] nextTick(() => scrollbar.value?.setScrollTop(99999)) if (!msg) { sendLoading.value = false const res = await awaitFindForm(obj) return res } const res = await fetchDataAndProcess(msg, obj) sendLoading.value = false if (res.status === 'ok') { await new Promise((res: any) => setTimeout(() => { res() }, 2000) ) const res = await awaitFindForm(obj) return res } } let str = '' async function fetchDataAndProcess(input: any, obj: any) { str = input console.log(str) const pageInfo = await getPageInfo() await new Promise((res: any) => setTimeout(() => { res() }, 2000) ) // const res = await hepl({ // input_data: input, // body: pageInfo.content.mainContent // }) const res: any = await new Promise((resolve, reject) => { setTimeout(() => { resolve({ data: pageInfo.title === '智能招采' ? mockData[indexTemp.value] : mockData2[indexTemp.value] }) }, 1000) }) if (!res.data.tag || res.data.tag === 'undefined') { ElMessage({ message: '未找到标签,请重试', type: 'error', duration: 4 * 1000, grouping: true }) obj.content = '未找到标签,请重试' return { status: 'error' } } await new Promise((resolve) => setTimeout(resolve, 2000)) obj.content = `点击${res.data.tag}元素` const res2 = await new Promise((resolve, rej) => { chrome.runtime.sendMessage( { type: 'FROM_SIDE_PANEL_TO_ACTION', data: res.data }, async ({ data, status }) => { if (chrome.runtime.lastError) { console.error('消息发送错误:', chrome.runtime.lastError) } else { if (status === 'error') { obj.content = data resolve({ data, status }) } if (res.data.next === '是') { const arr = str.split(',') arr.shift() str = arr.join(',') indexTemp.value++ const res = await fetchDataAndProcess(str, obj) resolve(res) } else resolve({ status: 'ok' }) // else { // await new Promise((resolve, reject) => { // setTimeout(() => { // resolve(1) // }, 2000) // }) // obj.content = `请选择表单` // ElMessage({ // message: '请选择表单', // type: 'success', // duration: 4 * 1000, // grouping: true // }) // chrome.runtime.sendMessage({ // type: 'FROM_SIDE_PANEL_TO_GET_PAGE_FORM' // }) // } } } ) }) return res2 } /** * * @param addHtml 是否添加页面信息 */ const streamRes = async (addHtml: any = false) => { pageInfo.value = await getPageInfo() sendLoading.value = true const obj = reactive({ id: messages.value.length + 1, username: '用户1', content: '', rawContent: '', // 存储原始内容 timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), isSelf: false, avatar: avator, addToHistory: !taklToHtml.value }) let history = [] if (taklToHtml.value) { if (addHtml) { history.push({ role: 'user', content: `页面主要内容${pageInfo.value.content.mainContent}` }) } history.push({ role: 'user', content: messages.value[messages.value.length - 1].rawContent }) } else { history = messages.value .filter((item: any) => item.addToHistory) .slice(-20) .map((item: any) => ({ role: item.isSelf ? 'user' : 'system', content: item.rawContent })) } messages.value.push(obj) nextTick(() => { scrollbar.value?.setScrollTop(99999) }) const iterator = await sendMessage(history) for await (const chunk of iterator) { if (chunk) { const decodedChunk = chunk.choices[0].delta.content if (decodedChunk) { // 保存原始内容 obj.rawContent += decodedChunk // 实时格式化显示内容 obj.content = formatMessage(obj.rawContent) // if (type.value === '2') obj.content = obj.content.replace(/item/g, '表单项').replace(/excelColumn/g, '对应数据源') } } scrollbar.value?.setScrollTop(99999) } console.log(obj.rawContent) //添加到存储历史 useStore(msgUuid.value).add({ ...obj }) // 处理最终内容 sendLoading.value = false nextTick(() => { scrollbar.value?.setScrollTop(99999) }) if (type.value === '2') { const arr = JSON.parse(obj.rawContent.split('json')[1].split('```')[0]) const newArr = arr .map((obj) => { return `| ${[ `“findBy”: \` "label",`, `"findByValue" \` “${obj.findByValue}”,`, `"数据来源字段" \` “${obj.excelColumn}”,`, `"表单项" \` “${obj.item}"` ].join(' ')} |` }) .join('\n') obj.content = formatMessage('```json' + JSON.stringify(newArr) + '```') console.log(formatMessage('```json' + JSON.stringify(newArr) + '```')) } return obj.rawContent } async function requestFlowFn(data: any[]) { sendLoading.value = true const obj = reactive({ id: messages.value.length + 1, username: '用户1', content: '', rawContent: '', // 存储原始内容 timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), isSelf: false, avatar: avator, addToHistory: !taklToHtml.value }) messages.value.push(obj) scrollbar.value?.setScrollTop(99999) const iterator = await sendMessage(data) if (iterator.error) { // 实时格式化显示内容 obj.content = iterator.error } else { for await (const chunk of iterator) { if (chunk) { const decodedChunk = chunk.choices[0].delta.content if (decodedChunk) { // 保存原始内容 obj.rawContent += decodedChunk // 实时格式化显示内容 obj.content = formatMessage(obj.rawContent) } } scrollbar.value?.setScrollTop(99999) } } //添加到存储历史 useStore(msgUuid.value).add({ ...obj }) // 处理最终内容 sendLoading.value = false nextTick(() => { scrollbar.value?.setScrollTop(99999) }) } return { indexTemp, taklToHtml, sendLoading, formMap, type, fetchRes, streamRes, getFormKeyAndValue, getFileSummary, requestFlowFn } }