From cccec0674e701eda45092e7c4431b58d96af5cbd Mon Sep 17 00:00:00 2001 From: no99 <17663930442@163.com> Date: Wed, 13 Aug 2025 10:25:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=BA=E5=AE=9D=E5=A5=87=E5=85=B5=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=AE=B0=E5=BD=95=E7=82=B9=E5=87=BB=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/chat.js | 2 + src/views/AIchat.vue | 634 ++++++++++++++++++++------------- src/views/components/HistoryRecord.vue | 6 +- src/views/homePage.vue | 36 +- 4 files changed, 426 insertions(+), 252 deletions(-) diff --git a/src/store/chat.js b/src/store/chat.js index f8f9f0b..e4fe20a 100644 --- a/src/store/chat.js +++ b/src/store/chat.js @@ -7,6 +7,8 @@ export const useChatStore = defineStore("chat", { UserCount: 0, chartData: [], kLineData: [], + dbqbClickRecord:{}, + }), actions: { async getUserCount() { diff --git a/src/views/AIchat.vue b/src/views/AIchat.vue index c10c88f..3ed6e7b 100644 --- a/src/views/AIchat.vue +++ b/src/views/AIchat.vue @@ -684,102 +684,102 @@ const addTypingTask = (message, content, speed) => { async function showThinkingProcess(stockName = null) { // 第一步:正在思考 const thinkingMessage1 = reactive({ - sender: 'ai', - class: 'ing', - type: 'ing', + sender: "ai", + class: "ing", + type: "ing", flag: true, - content: '正在思考......', - gif: '/src/assets/img/gif/思考.gif' + content: "正在思考......", + gif: "/src/assets/img/gif/思考.gif", }); chatStore.messages.push(thinkingMessage1); - await new Promise(resolve => setTimeout(resolve, 1500)); + await new Promise((resolve) => setTimeout(resolve, 1500)); chatStore.messages.pop(); - + // 第二步:正在解析关键数据(持续显示直到获取到股票名称) const thinkingMessage2 = reactive({ - sender: 'ai', - class: 'ing', - type: 'ing', + sender: "ai", + class: "ing", + type: "ing", flag: true, - content: '正在解析关键数据......', - gif: '/src/assets/img/gif/解析.gif' + content: "正在解析关键数据......", + gif: "/src/assets/img/gif/解析.gif", }); chatStore.messages.push(thinkingMessage2); - + // 如果没有股票名称,保持第二步显示 if (!stockName) { return thinkingMessage2; // 返回消息引用,以便后续更新 } - + // 有股票名称后,继续后续步骤 - await new Promise(resolve => setTimeout(resolve, 1500)); + await new Promise((resolve) => setTimeout(resolve, 1500)); chatStore.messages.pop(); - + // 第三步:生成具体股票的全景作战报告 const thinkingMessage3 = reactive({ - sender: 'ai', - class: 'ing', - type: 'ing', + sender: "ai", + class: "ing", + type: "ing", flag: true, content: `正在生成${stockName}全景作战报告......`, - gif: '/src/assets/img/gif/生成.gif' + gif: "/src/assets/img/gif/生成.gif", }); chatStore.messages.push(thinkingMessage3); - await new Promise(resolve => setTimeout(resolve, 1500)); + await new Promise((resolve) => setTimeout(resolve, 1500)); chatStore.messages.pop(); - + // 第四步:报告已生成 const thinkingMessage4 = reactive({ - sender: 'ai', - class: 'ing', - type: 'ing', + sender: "ai", + class: "ing", + type: "ing", flag: true, - content: '报告已生成!', - gif: '/src/assets/img/gif/生成.gif' + content: "报告已生成!", + gif: "/src/assets/img/gif/生成.gif", }); chatStore.messages.push(thinkingMessage4); - await new Promise(resolve => setTimeout(resolve, 1500)); + await new Promise((resolve) => setTimeout(resolve, 1500)); chatStore.messages.pop(); - + return null; } // 继续思考过程(当获取到股票名称后调用) async function continueThinkingProcess(thinkingMessageRef, stockName) { if (!thinkingMessageRef || !stockName) return; - + // 等待一段时间后继续 - await new Promise(resolve => setTimeout(resolve, 1500)); - + await new Promise((resolve) => setTimeout(resolve, 1500)); + // 移除第二步消息 const index = chatStore.messages.indexOf(thinkingMessageRef); if (index > -1) { chatStore.messages.splice(index, 1); } - + // 第三步:生成具体股票的全景作战报告 const thinkingMessage3 = reactive({ - sender: 'ai', - class: 'ing', - type: 'ing', + sender: "ai", + class: "ing", + type: "ing", flag: true, content: `正在生成${stockName}全景作战报告......`, - gif: '/src/assets/img/gif/生成.gif' + gif: "/src/assets/img/gif/生成.gif", }); chatStore.messages.push(thinkingMessage3); - await new Promise(resolve => setTimeout(resolve, 1500)); + await new Promise((resolve) => setTimeout(resolve, 1500)); chatStore.messages.pop(); - + // 第四步:报告已生成 const thinkingMessage4 = reactive({ - sender: 'ai', - class: 'ing', - type: 'ing', + sender: "ai", + class: "ing", + type: "ing", flag: true, - content: '报告已生成!' + content: "报告已生成!", }); chatStore.messages.push(thinkingMessage4); - await new Promise(resolve => setTimeout(resolve, 1500)); + await new Promise((resolve) => setTimeout(resolve, 1500)); chatStore.messages.pop(); } @@ -829,7 +829,7 @@ watch( const codeData = ref(); // 开始思考过程(不带股票名称) const thinkingMessageRef = await showThinkingProcess(); - + // 第一阶段,意图识别 try { // 调用工作流获取回复 @@ -840,9 +840,12 @@ watch( if (result.code == 200) { // 获取到股票名称后,继续思考过程 if (thinkingMessageRef && codeData.value.name) { - await continueThinkingProcess(thinkingMessageRef, codeData.value.name); + await continueThinkingProcess( + thinkingMessageRef, + codeData.value.name + ); } - + chatStore.messages.push({ class: "ing", type: "ing", @@ -857,7 +860,7 @@ watch( chatStore.messages.splice(index, 1); } } - + flag = false; console.log("执行回绝话术"); const AIcontent = ref(result.msg); @@ -896,7 +899,7 @@ watch( chatStore.messages.splice(index, 1); } } - + console.log(e, "意图识别失败"); chatStore.messages.push({ class: "ing", @@ -2347,140 +2350,6 @@ watch( chatStore.isLoading = false; emit("enableInput"); } - - // 同时发起所有API调用 - // const promises = [ - // dbqbSecondOneAPI(params2), - // dbqbSecondTwoAPI(params2), - // dbqbSecondThreeAPI(params2), - // dbqbSecondFourAPI(params2), - // ]; - // const results = await Promise.allSettled(promises); - // let result21; - // let result22; - // let result23; - // let result24; - // // 检查每个API的结果并执行相应代码 - // console - // if (results[0].status === "fulfilled") { - // result21 = results[0].value; - // // oneAPI成功返回时执行的代码 - // console.log("oneAPI成功:", result21); - // // 在这里添加你的业务逻辑 - // } - - // if (results[1].status === "fulfilled") { - // result22 = results[1].value; - // // twoAPI成功返回时执行的代码 - // console.log("twoAPI成功:", result22); - // // 在这里添加你的业务逻辑 - // } - - // if (results[2].status === "fulfilled") { - // result23 = results[2].value; - // // threeAPI成功返回时执行的代码 - // console.log("threeAPI成功:", result23); - // } - - // if (results[3].status === "fulfilled") { - // result24 = results[3].value; - // // fourAPI成功返回时执行的代码 - // console.log("fourAPI成功:", result24); - // } - - // const result21 = await dbqbSecondOneAPI(params2); - // const result22 = await dbqbSecondTwoAPI(params2); - // const result23 = await dbqbSecondThreeAPI(params2); - // const result24 = await dbqbSecondFourAPI(params2); - - // 音频收集逻辑已移至checkAndExecuteInOrder函数内部 - - // // 修改后的消息处理逻辑 - // const processedContent = marked(AIcontent.value); - // const katexRegex = /\$\$(.*?)\$\$/g; - // const plainTextContent = htmlToText(processedContent); - - // // 获取音频数据 - // const TTSResult = ( - // await TTSAPI({ - // language: "cn", - // content: plainTextContent, - // }) - // ).json(); - - // const tts = ref(); - // await TTSResult.then((res) => { - // tts.value = JSON.parse(res.data); - // }); - - // const ttsUrl = ref(); - // if (tts.value.tts_cn !== null) { - // audioStore.ttsUrl = tts.value.tts_cn.url; - // ttsUrl.value = tts.value.tts_cn.url; - // audioStore.isNewInstance = true; - // } else if (tts.value.tts_en !== null) { - // audioStore.ttsUrl = tts.value.tts_en.url; - // ttsUrl.value = tts.value.tts_en.url; - // audioStore.isNewInstance = true; - // } - - // if (ttsUrl.value) { - // nextTick(() => { - // if (audioStore.isVoiceEnabled) { - // console.log("ttsUrl.value", ttsUrl.value); - // // 播放音频 - // playAudio(ttsUrl.value); - // } - // }); - // } - - // // chatStore.messages.pop(); - // // 先推送初始消息 - // const aiMessage = reactive({ - // sender: "ai", - // content: "", - // isTyping: true, - // }); - // chatStore.messages.push(aiMessage); - - // let index = 0; - // const typingInterval = setInterval(() => { - // if (index < processedContent.length) { - // aiMessage.content += processedContent.charAt(index); - // index++; - // } else { - // clearInterval(typingInterval); - // aiMessage.isTyping = false; - - // // 延迟处理KaTeX确保DOM已更新 - // nextTick(() => { - // aiMessage.content = aiMessage.content.replace( - // katexRegex, - // (match, formula) => { - // try { - // return katex.renderToString(formula, { - // throwOnError: false, - // }); - // } catch (error) { - // console.error("KaTeX 渲染错误:", error); - // return match; - // } - // } - // ); - // chatStore.setLoading(false); - // }); - // } - // }, 50); // 调整速度为50ms/字符 - // // } else { - // // chatStore.messages.pop(); - // // chatStore.messages.push({ - // // sender: "ai", - // // content: status.msg - // // }); - - // // chatStore.setLoading(false); - // // } - // } } catch (e) { console.error("请求失败:", e); hasValidData.value = false; // 请求失败时设置数据无效 @@ -2500,6 +2369,274 @@ watch( { deep: true } ); +// 点击历史记录 +watch( + () => chatStore.dbqbClickRecord, + (newValue, oldValue) => { + console.log("new", newValue); + if (!newValue || Object.keys(newValue).length === 0) { + return; + } + + const clickRecord = ref(newValue); + console.log("dbqbClickRecord 发生变化:", clickRecord.value); + + // 在下一个事件循环中清空 dbqbClickRecord + setTimeout(() => { + chatStore.dbqbClickRecord = {}; + console.log("dbqbClickRecord 已清空"); + }, 0); + + // 清空聊天框内容 + chatStore.messages = []; + + chatStore.messages.push({ + sender: "user", + timestamp: clickRecord.value.createdTime, + content: clickRecord.value.keyword, + }); + + chatStore.messages.push({ + sender: "ai", + class: "title1", + type: "title1", + content: clickRecord.value.stockName + "全景作战报告", + date: clickRecord.value.wokeFlowData.One.date, + }); + + const pc1 = marked( + clickRecord.value.wokeFlowData.One.name + + "\n" + + clickRecord.value.wokeFlowData.One.price + + "\n" + + clickRecord.value.wokeFlowData.One.date + ); + + chatStore.messages.push({ + sender: "ai", + class: "content1", + type: "content1", + content: pc1, + }); + + const HomePage = clickRecord.value.stockData.HomePage; + if (HomePage) { + const LiuSeData = JSON.parse(JSON.stringify(toRaw(HomePage))); + const sz = fnGetData(LiuSeData); + if (sz) { + hasValidData.value = true; + console.log("hasValidData设置为:", hasValidData.value); + } + // 先推送K线图消息 + const klineMessageId1 = `kline-${Date.now()}`; + console.log("生成K线消息ID:", klineMessageId1); + + chatStore.messages.push({ + sender: "ai", + class: "content1", + type: "content1", + kline: true, + chartData: sz, + messageId: klineMessageId1, + hasValidData: true, + klineType: 1, + }); + + // 在渲染完成后初始化图表 + nextTick(() => { + console.log("nextTick开始 - 准备渲染图表"); + console.log("消息列表:", chatStore.messages); + + // 寻找最新添加的K线消息索引 + let klineIndex = -1; + for (let i = 0; i < chatStore.messages.length; i++) { + if (chatStore.messages[i].messageId === klineMessageId1) { + klineIndex = i; + break; + } + } + + console.log("找到的K线消息索引:", klineIndex); + + if (klineIndex !== -1) { + const containerId = `kline-container-${klineIndex}`; + console.log("图表容器ID:", containerId); + + // 确保DOM已经渲染完成 + setTimeout(() => { + console.log("延时执行,确保DOM已渲染"); + KlineCanvsEcharts(containerId); + }, 100); // 短暂延时确保DOM已渲染 + } else { + console.warn("未找到K线消息"); + } + }); + } + const AIGoldBull = clickRecord.value.stockData.AIGoldBull; + // 度牛尺K线图 + if ( + AIGoldBull && + AIGoldBull.DNC && + AIGoldBull.FCX && + AIGoldBull.JN && + AIGoldBull.KLine20 && + AIGoldBull.QSXH + ) { + const AIGoldBullData = JSON.parse(JSON.stringify(toRaw(AIGoldBull))); + const HomePageData = JSON.parse(JSON.stringify(toRaw(HomePage))); + console.log("处理 K 线数据 - 开始"); + console.log("AIGoldBullData", AIGoldBullData); + console.log("HomePageData", HomePageData); + + const Kline20 = { + name: HomePageData.StockInformation.Name, + Kline: AIGoldBullData, + }; + + // 打印K线数据结构 + console.log("K线数据结构:", Kline20); + console.log("K线数据名称:", Kline20.name); + console.log("K线数据:", Kline20.Kline ? Kline20.Kline : null); + + // 设置数据有效标志 + hasValidData.value = true; + console.log("hasValidData设置为:", hasValidData.value); + + // chatStore.messages.pop(); + + // 先推送K线图消息 + const klineMessageId2 = `kline-${Date.now() + 1}`; + console.log("生成K线消息ID:", klineMessageId2); + + chatStore.messages.push({ + sender: "ai", + class: "content2", + type: "content2", + kline: true, + chartData: Kline20, + messageId: klineMessageId2, + hasValidData: true, // 添加hasValidData标志 + klineType: 2, + }); + + // 在渲染完成后初始化图表 + nextTick(() => { + console.log("nextTick开始 - 准备渲染图表"); + console.log("消息列表:", chatStore.messages); + + // 寻找最新添加的K线消息索引 + let klineIndex = -1; + for (let i = 0; i < chatStore.messages.length; i++) { + if (chatStore.messages[i].messageId === klineMessageId2) { + klineIndex = i; + break; + } + } + + console.log("找到的K线消息索引:", klineIndex); + + if (klineIndex !== -1) { + const containerId = `kline-container-${klineIndex}`; + console.log("图表容器ID:", containerId); + + // 确保DOM已经渲染完成 + setTimeout(() => { + console.log("延时执行,确保DOM已渲染"); + KlineCanvsEcharts(containerId); + }, 100); // 短暂延时确保DOM已渲染 + } else { + console.warn("未找到K线消息"); + } + }); + } + chatStore.messages.push({ + sender: "ai", + class: "title2", + type: "title2", + content: "", + }); + + const pc2 = marked(clickRecord.value.wokeFlowData.Two.hxjzpg); + // 先推送初始消息 + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: pc2, + }); + + chatStore.messages.push({ + sender: "ai", + class: "title3", + type: "title3", + content: title2, + }); + + const ac3 = `
【主力行为】
${clickRecord.value.wokeFlowData.Three.zhuli1}
${clickRecord.value.wokeFlowData.Three.zhuli2}
${clickRecord.value.wokeFlowData.Three.zhuli3}
`; + + // 先推送初始消息 + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac3, + isTyping: true, + }); + + chatStore.messages.push({ + sender: "ai", + class: "title3", + type: "title3", + content: title3, + }); + + const arr = clickRecord.value.wokeFlowData.Three.kongjian.split(","); + const kongjian = `【空间维度】
${arr[0]},${arr[1]}
${arr[2]},${arr[3]}
`; + const shijian = `【时间维度】
${clickRecord.value.wokeFlowData.Three.shijian}
`; + const nengliang = `【能量维度】
${clickRecord.value.wokeFlowData.Three.nengliang}
`; + const ac4 = kongjian + shijian + nengliang; + + // 先推送初始消息 + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac4, + }); + + chatStore.messages.push({ + sender: "ai", + class: "title3", + type: "title3", + content: title4, + }); + + const cftj = `【触发条件】
${clickRecord.value.wokeFlowData.Four.cftl}
`; + const gfzl = `【攻防指令】
${clickRecord.value.wokeFlowData.Four.gfzl}
`; + const ac5 = cftj + gfzl; + + // 先推送初始消息 + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac5, + }); + + chatStore.messages.push({ + sender: "ai", + class: "mianze", + type: "mianze", + content: "该内容由AI生成,请注意甄别", + end: true, + }); + }, + { + deep: true, // 深度监听对象内部属性的变化 + immediate: true, // 立即执行一次回调 + } +); + function KlineCanvsEcharts(containerId) { function vwToPx(vw) { console.log((window.innerWidth * vw) / 100, "vwToPx"); @@ -4199,14 +4336,14 @@ onUnmounted(() => {