diff --git a/.env.development b/.env.development index 007e426..32dcc78 100644 --- a/.env.development +++ b/.env.development @@ -5,8 +5,8 @@ VITE_OUTPUT_DIR = 'dev' VITE_PUBLIC_PATH = / #新数据接口 -# VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link" -VITE_APP_API_BASE_URL = "https://api.homilychart.com/link" +VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link" +# VITE_APP_API_BASE_URL = "https://api.homilychart.com/link" VITE_APP_IMG_API_BASE_URL = "http://39.101.133.168:8828/hljw/api/aws/upload" #MJ API diff --git a/package-lock.json b/package-lock.json index e04a679..7bf2b91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "html-to-text": "^9.0.5", "katex": "^0.16.21", "lodash": "^4.17.21", - "marked": "^15.0.7", + "marked": "^15.0.12", "mitt": "^3.0.1", "moment": "^2.30.1", "pinia": "^2.3.1", @@ -5117,9 +5117,9 @@ } }, "node_modules/marked": { - "version": "15.0.7", - "resolved": "https://mirrors.huaweicloud.com/repository/npm/marked/-/marked-15.0.7.tgz", - "integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==", + "version": "15.0.12", + "resolved": "https://mirrors.huaweicloud.com/repository/npm/marked/-/marked-15.0.12.tgz", + "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", "license": "MIT", "bin": { "marked": "bin/marked.js" diff --git a/package.json b/package.json index 70957f2..14651ed 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "html-to-text": "^9.0.5", "katex": "^0.16.21", "lodash": "^4.17.21", - "marked": "^15.0.7", + "marked": "^15.0.12", "mitt": "^3.0.1", "moment": "^2.30.1", "pinia": "^2.3.1", diff --git a/src/api/AIxiaocaishen.js b/src/api/AIxiaocaishen.js index b3394ad..0cbce31 100644 --- a/src/api/AIxiaocaishen.js +++ b/src/api/AIxiaocaishen.js @@ -213,12 +213,53 @@ export const getMarketAndCodeAPI = function (params) { }; // 登录获取次数接口 export const addUsageAPI = function (params) { - return request({ - url: `${APIurl}/api/ai_god/addUsage`, - method: "POST", - data: new URLSearchParams(params), - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - }); - }; \ No newline at end of file + return request({ + url: `${APIurl}/api/ai_god/addUsage`, + method: "POST", + data: new URLSearchParams(params), + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }); +}; + +// duobao11 +export const dbqbFirstAPI = function (params) { + return request({ + url: `${APIurl}/api/workflow/dbqbFirst`, + method: "POST", + data: params, + }); +}; +// duobao21 +export const dbqbSecondOneAPI = function (params) { + return request({ + url: `${APIurl}/api/workflow/dbqbSecondOne`, + method: "POST", + data: params, + }); +}; +// duobao22 +export const dbqbSecondTwoAPI = function (params) { + return request({ + url: `${APIurl}/api/workflow/dbqbSecondTwo`, + method: "POST", + data: params, + }); +}; +// duobao23 +export const dbqbSecondThreeAPI = function (params) { + return request({ + url: `${APIurl}/api/workflow/dbqbSecondThree`, + method: "POST", + data: params, + }); +}; +// duobao24 +export const dbqbSecondFourAPI = function (params) { + return request({ + url: `${APIurl}/api/workflow/dbqbSecondFour`, + method: "POST", + data: params, + }); +}; diff --git a/src/utils/request.js b/src/utils/request.js index 80b4877..e4f8432 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -115,6 +115,7 @@ service.interceptors.response.use( const errorMsg = res.msg || 'Unkonw error' // ElMessage.error(errorMsg) // return Promise.reject(new Error(res.msg || 'Error')) + return response.data } else { return response.data } diff --git a/src/views/AIchat.vue b/src/views/AIchat.vue index 03cc174..44a9343 100644 --- a/src/views/AIchat.vue +++ b/src/views/AIchat.vue @@ -5,8 +5,12 @@ import { getReplyStreamAPI, getReplyAPI, TTSAPI, - getQuestionAPI, qsArpAamClickAPI, + dbqbFirstAPI, + dbqbSecondOneAPI, + dbqbSecondTwoAPI, + dbqbSecondThreeAPI, + dbqbSecondFourAPI, } from "../api/AIxiaocaishen"; import { useUserStore } from "../store/userPessionCode"; import { useChatStore } from "../store/chat"; @@ -17,6 +21,7 @@ import katex from "katex"; // 引入 KaTeX 库 import { htmlToText } from "html-to-text"; import { Howl, Howler } from "howler"; import * as echarts from "echarts"; +import moment from "moment"; import AIgif1 from "@/assets/img/AIchat/AIgif1.gif"; import AIgif2 from "@/assets/img/AIchat/AIgif2.gif"; @@ -31,92 +36,15 @@ import title3 from "@/assets/img/AIchat/攻防三维.png"; import title4 from "@/assets/img/AIchat/综合作战.png"; const gifList = [AIgif1, AIgif2, AIgif3, AIgif4, AIgif5, AIgif6, AIgif7]; - const chatStore = useChatStore(); const audioStore = useAudioStore(); const dataStore = useDataStore(); // 随机GIF const currentGif = ref(""); -// 推荐问题飘屏数据 -const questionsList = ref([]); -const getQuestionsList = async () => { - const result = await getQuestionAPI(); - questionsList.value = result.data; -}; - // 定义自定义事件 const emit = defineEmits(["updateMessage", "sendMessage"]); -// 弹窗控制 -// const currentQuestions = ref(""); -// const showQuestions = async (questions) => { -// const click = await qsArpAamClickAPI({ -// token: localStorage.getItem("localToken"), -// id: questions.id, -// }); -// console.log(click); - -// currentQuestions.value = questions; -// // 触发自定义事件 -// emit("updateMessage", questions.title); -// // emit("sendMessage"); -// }; - -// 飘屏控制 -// const floatingTopMouseEnter = function () { -// const userAgent = navigator.userAgent.toLowerCase(); -// const mobileKeywords = ["mobile", "android", "iphone", "ipad", "ipod"]; -// const isMobile = mobileKeywords.some((keyword) => -// userAgent.includes(keyword) -// ); -// if (isMobile) { -// return; -// } -// console.log("鼠标指上去"); -// const floatTop = document.getElementById("top"); -// floatTop.style.animationPlayState = "paused"; -// }; -// const floatingTopMouseLeave = function () { -// const userAgent = navigator.userAgent.toLowerCase(); -// const mobileKeywords = ["mobile", "android", "iphone", "ipad", "ipod"]; -// const isMobile = mobileKeywords.some((keyword) => -// userAgent.includes(keyword) -// ); -// if (isMobile) { -// return; -// } -// console.log("鼠标指下去"); -// const floatTop = document.getElementById("top"); -// floatTop.style.animationPlayState = "running"; -// }; -// const floatingBottomMouseEnter = function () { -// const userAgent = navigator.userAgent.toLowerCase(); -// const mobileKeywords = ["mobile", "android", "iphone", "ipad", "ipod"]; -// const isMobile = mobileKeywords.some((keyword) => -// userAgent.includes(keyword) -// ); -// if (isMobile) { -// return; -// } -// console.log("鼠标指上去"); -// const floatBottom = document.getElementById("bottom"); -// floatBottom.style.animationPlayState = "paused"; -// }; -// const floatingBottomMouseLeave = function () { -// const userAgent = navigator.userAgent.toLowerCase(); -// const mobileKeywords = ["mobile", "android", "iphone", "ipad", "ipod"]; -// const isMobile = mobileKeywords.some((keyword) => -// userAgent.includes(keyword) -// ); -// if (isMobile) { -// return; -// } -// console.log("鼠标指下去"); -// const floatBottom = document.getElementById("bottom"); -// floatBottom.style.animationPlayState = "running"; -// }; - // 音频播放方法 const playAudio = (url) => { // 添加空值校验 @@ -276,123 +204,45 @@ watch( // 获取权限 const userStore = useUserStore(); - const params = { - content: newVal[newVal.length - 1].content, - userData: { - token: localStorage.getItem("localToken"), - // language: "cn", - // brainPrivilegeState: userStore.brainPerssion, - // swordPrivilegeState: userStore.swordPerssion, - // stockForecastPrivile: userStore.pricePerssion, - // spaceForecastPrivile: userStore.timePerssion, - // aibullPrivilegeState: userStore.aibullPerssion, - // aigoldBullPrivilegeS: userStore.aiGnbullPerssion, - // airadarPrivilegeStat: userStore.airadarPerssion, - // marketList: "hk,cn,usa,my,sg,vi,in,gb" - // token: "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w", - language: "cn", - brainPrivilegeState: "1", - swordPrivilegeState: "1", - stockForecastPrivile: "1", - spaceForecastPrivile: "1", - aibullPrivilegeState: "1", - aigoldBullPrivilegeS: "1", - airadarPrivilegeStat: "1", - marketList: "hk,cn,usa,my,sg,vi,in,gb", + const params1 = { + workflow_id: "7514939889071718438", + parameters: { + content: newVal[newVal.length - 1].content, + userData: { + language: "cn", + marketList: "hk,cn,usa,my,sg,vi,in,gb", + token: localStorage.getItem("localToken"), + // language: "cn", + // marketList: "hk,cn,usa,my,sg,vi,in,gb" + // token: "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w", + }, }, }; - + // 标志 + let flag = true; + const codeData = ref(); + // 第一阶段,意图识别 try { - chatStore.messages.push({ - class: "ing", - type: "ing", - content: "正在为您生成特斯拉全景作战报告", - }); - - chatStore.messages.push({ - sender: "ai", - class: "title1", - type: "title1", - content: "特斯拉全景作战报告", - date: "05/06/2025", - }); - - chatStore.messages.push({ - sender: "ai", - class: "title2", - type: "title2", - content: "", - }); - - chatStore.messages.push({ - sender: "ai", - class: "title3", - type: "title3", - content: title2, - }); - - chatStore.messages.push({ - sender: "ai", - class: "title3", - type: "title3", - content: title3, - }); - - chatStore.messages.push({ - sender: "ai", - class: "title3", - type: "title3", - content: title4, - }); - - chatStore.messages.push({ - sender: "ai", - class: "content1", - type: "content1", - content: "股票名称:tesla", - }); - - chatStore.messages.push({ - sender: "ai", - class: "content2", - type: "content2", - content: "K线图", - }); - - chatStore.messages.push({ - sender: "ai", - class: "content3", - type: "content3", - content: "(1)牛股评级:⭐⭐⭐⭐⭐", - }); - - chatStore.messages.push({ - sender: "ai", - class: "mianze", - type: "mianze", - content: "内容由AI生成,请注意甄别", - }); - // 调用工作流获取回复 - const result = (await getReplyAPI(params)).json(); - // 获取结果 - const ans = ref(); - await result.then((res) => { - // 解析 data 字段中的 JSON - ans.value = JSON.parse(res.data); - }); - const AIcontent = ref(""); - // 处理不同的 answer 字段 - - if (ans.value.resp !== "" && ans.value.resp !== null) { + const result = await dbqbFirstAPI(params1); + codeData.value = result.data; + console.log(codeData.value, "codeData"); + // 根据意图识别结果判断 + if (result.code == 200) { + chatStore.messages.push({ + class: "ing", + type: "ing", + flag: flag, + content: result.data.kaishi, + }); + } else { + flag = false; console.log("执行回绝话术"); - AIcontent.value = ans.value.resp; - + const AIcontent = ref(result.msg); // 修改后的消息处理逻辑 + const processedContent = marked(AIcontent.value); const katexRegex = /\$\$(.*?)\$\$/g; - // const plainTextContent = htmlToText(processedContent); - const aiContent = processedContent.replace( katexRegex, (match, formula) => { @@ -404,193 +254,416 @@ watch( } } ); - console.log(aiContent, "aiContent"); - // chatStore.messages.pop(); - chatStore.messages.push({ - sender: "ai", + class: "ing", + type: "ing", + flag: flag, content: aiContent, }); chatStore.setLoading(false); - } else { - // 判断是否是股票问题 - if (ans.value.answer !== "") { - AIcontent.value = ans.value.answer; - const type = ans.value.type; - const data = JSON.parse(ans.value.data); - - console.log("处理 K 线数据 - 开始"); - console.log(data, "data"); - - const Kline20 = { - name: data.data.HomePage.StockInformation.Name, - Kline: data.data, - type: type, - }; - - // 打印K线数据结构 - console.log("K线数据结构:", Kline20); - console.log("K线数据名称:", Kline20.name); - console.log("K线数据类型:", Kline20.type); - console.log("K线数据:", Kline20.Kline ? Kline20.Kline : null); - - // 设置数据有效标志 - hasValidData.value = true; - console.log("hasValidData设置为:", hasValidData.value); + } + } catch (e) { + console.log(e, "意图识别失败"); + } - // chatStore.messages.pop(); + if (flag) { + const params2 = { + content: newVal[newVal.length - 1].content, + userData: { + aibullPrivilegeState: 1, + aigoldBullPrivilegeS: 1, + airadarPrivilegeStat: 1, + brainPrivilegeState: 1, + spaceForecastPrivile: 1, + stockForecastPrivile: 1, + swordPrivilegeState: 1, + language: "cn", + marketList: "hk,cn,usa,my,sg,vi,in,gb", + token: localStorage.getItem("localToken"), + // aibullPrivilegeState: userStore.aibullPrivilegeState, + // aigoldBullPrivilegeState: userStore.aigoldBullPrivilegeState, + // airadarPrivilegeState: userStore.airadarPrivilegeState, + // brainPrivilegeState: userStore.brainPrivilegeState, + // spaceForecastPrivilegeState: userStore.spaceForecastPrivilegeState, + // stockForecastPrivilegeState: userStore.stockForecastPrivilegeState, + // swordPrivilegeState: userStore.swordPrivilegeState, + // language: "cn", + // marketList: "hk,cn,usa,my,sg,vi,in,gb" + // token: "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w", + }, + name: codeData.value.name, + code: codeData.value.code, + market: codeData.value.market, + }; + + try { + const result21 = await dbqbSecondOneAPI({ + workflow_id: "7514945685688025127", + parameters: params2, + }); + const result22 = await dbqbSecondTwoAPI({ + workflow_id: "7514945728733888575", + parameters: params2, + }); + const result23 = await dbqbSecondThreeAPI({ + workflow_id: "7514945758421811254", + parameters: params2, + }); + const result24 = await dbqbSecondFourAPI({ + workflow_id: "7514945791469223955", + parameters: params2, + }); - // 先推送K线图消息 - const klineMessageId = `kline-${Date.now()}`; - console.log("生成K线消息ID:", klineMessageId); + const katexRegex = /\$\$(.*?)\$\$/g; + // 删除正在为您生成信息 + chatStore.messages.pop(); + // 添加报告头和时间 + chatStore.messages.push({ + sender: "ai", + class: "title1", + type: "title1", + content: codeData.value.name + "全景作战报告", + date: moment().format("MM/DD/YYYY"), + }); + // 添加股票信息框 + + const pc1 = marked( + result21.data.name + + "\n" + + result21.data.price + + "\n" + + result21.data.data + ); + const ac1 = pc1.replace(katexRegex, (match, formula) => { + try { + return katex.renderToString(formula, { throwOnError: false }); + } catch (error) { + console.error("KaTeX 渲染错误:", error); + return match; + } + }); - chatStore.messages.push({ - sender: "ai", - type: "kline", - chartData: Kline20, - messageId: klineMessageId, - hasValidData: true, // 添加hasValidData标志 - }); + chatStore.messages.push({ + sender: "ai", + class: "content1", + type: "content1", + content: ac1, + }); + // 添加六色罗盘 + chatStore.messages.push({ + sender: "ai", + class: "content2", + type: "content2", + content: "K线图", + }); + // 度牛尺K线图 + // 添加标题2 + chatStore.messages.push({ + sender: "ai", + class: "title2", + type: "title2", + content: "", + }); + // 添加内容框1 + const pc2 = marked(result22.data.hxjzpg); + console.log(pc2, "pc2"); + const ac2 = pc2.replace(katexRegex, (match, formula) => { + try { + return katex.renderToString(formula, { throwOnError: false }); + } catch (error) { + console.error("KaTeX 渲染错误:", error); + return match; + } + }); + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac2, + }); + // 添加标题3-2 + chatStore.messages.push({ + sender: "ai", + class: "title3", + type: "title3", + content: title2, + }); + // 添加内容框2 + // const pc3 = marked(result23.data.zhuli1+'\n'+result23.data.zhuli2+'\n'+result23.data.zhuli3); + // const ac3 = pc3.replace( + // katexRegex, + // (match, formula) => { + // try { + // return katex.renderToString(formula, { throwOnError: false }); + // } catch (error) { + // console.error("KaTeX 渲染错误:", error); + // return match; + // } + // } + // ); + const ac3 = `
【主力行为】
${result23.data.zhuli1}
${result23.data.zhuli2}
${result23.data.zhuli3}
`; + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac3, + }); + // 添加标题3-3 + chatStore.messages.push({ + sender: "ai", + class: "title3", + type: "title3", + content: title3, + }); + // 添加内容框3 + const arr = result23.data.kongjian.split(","); + const kongjian = `【空间维度】
${arr[0]},${arr[1]}
${arr[2]},${arr[3]}
`; + const shijian = `【时间维度】
${result23.data.shijian}
`; + const nengliang = `【能量维度】
${result23.data.nengliang}
`; + const ac4 = kongjian + shijian + nengliang; + + // const pc4 = marked( + // kongjian + + // "\n" + + // result23.data.shijian + + // "\n" + + // result23.data.nengliang + // ); + // const ac4 = pc4.replace(katexRegex, (match, formula) => { + // try { + // return katex.renderToString(formula, { throwOnError: false }); + // } catch (error) { + // console.error("KaTeX 渲染错误:", error); + // return match; + // } + // }); + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac4, + }); + // 添加标题3-4 + chatStore.messages.push({ + sender: "ai", + class: "title3", + type: "title3", + content: title4, + }); + // 添加内容框4 + const cftj = `【触发条件】
${result24.data.cftl}
`; + const gfzl = `【攻防指令】
${result24.data.gfzl}
`; + const ac5 = cftj + gfzl; + + // const pc5 = marked(result24.data.cftl + "/n" + result24.data.gfzl); + // const ac5 = pc5.replace(katexRegex, (match, formula) => { + // try { + // return katex.renderToString(formula, { throwOnError: false }); + // } catch (error) { + // console.error("KaTeX 渲染错误:", error); + // return match; + // } + // }); + chatStore.messages.push({ + sender: "ai", + class: "content3", + type: "content3", + content: ac5, + }); - console.log("K线消息已添加到聊天列表"); + chatStore.messages.push({ + sender: "ai", + class: "mianze", + type: "mianze", + content: "内容由AI生成,请注意甄别", + }); - // 再推送文字分析内容的消息 - chatStore.messages.push({ - sender: "ai", - content: "AI正在思考中...", - }); + // 调用工作流获取回复 + const result = await getReplyAPI(params1); + // 获取结果 + const ans = ref(); + await result.then((res) => { + // 解析 data 字段中的 JSON + ans.value = JSON.parse(res.data); + }); + const AIcontent = ref(""); + // 处理不同的 answer 字段 - // 在渲染完成后初始化图表 - 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 === klineMessageId) { - klineIndex = i; - break; - } - } + if (ans.value.resp !== "" && ans.value.resp !== null) { + } else { + // 判断是否是股票问题 + if (ans.value.answer !== "") { + AIcontent.value = ans.value.answer; + const type = ans.value.type; + const data = JSON.parse(ans.value.data); + + console.log("处理 K 线数据 - 开始"); + console.log(data, "data"); + + const Kline20 = { + name: data.data.HomePage.StockInformation.Name, + Kline: data.data, + type: type, + }; + + // 打印K线数据结构 + console.log("K线数据结构:", Kline20); + console.log("K线数据名称:", Kline20.name); + console.log("K线数据类型:", Kline20.type); + console.log("K线数据:", Kline20.Kline ? Kline20.Kline : null); + + // 设置数据有效标志 + hasValidData.value = true; + console.log("hasValidData设置为:", hasValidData.value); + + // chatStore.messages.pop(); + + // 先推送K线图消息 + const klineMessageId = `kline-${Date.now()}`; + console.log("生成K线消息ID:", klineMessageId); + + chatStore.messages.push({ + sender: "ai", + type: "kline", + chartData: Kline20, + messageId: klineMessageId, + hasValidData: true, // 添加hasValidData标志 + }); - console.log("找到的K线消息索引:", klineIndex); + console.log("K线消息已添加到聊天列表"); - if (klineIndex !== -1) { - const containerId = `kline-container-${klineIndex}`; - console.log("图表容器ID:", containerId); + // 在渲染完成后初始化图表 + 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 === klineMessageId) { + klineIndex = i; + break; + } + } - // 确保DOM已经渲染完成 - setTimeout(() => { - console.log("延时执行,确保DOM已渲染"); - KlineCanvsEcharts(containerId); - }, 100); // 短暂延时确保DOM已渲染 - } else { - console.warn("未找到K线消息"); - } - }); - } + console.log("找到的K线消息索引:", klineIndex); - // 修改后的消息处理逻辑 - 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); - }); + if (klineIndex !== -1) { + const containerId = `kline-container-${klineIndex}`; + console.log("图表容器ID:", containerId); - 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; - } + // 确保DOM已经渲染完成 + setTimeout(() => { + console.log("延时执行,确保DOM已渲染"); + KlineCanvsEcharts(containerId); + }, 100); // 短暂延时确保DOM已渲染 + } else { + console.warn("未找到K线消息"); + } + }); + } - if (ttsUrl.value) { - nextTick(() => { - if (audioStore.isVoiceEnabled) { - console.log("ttsUrl.value", ttsUrl.value); - // 播放音频 - playAudio(ttsUrl.value); - } + // 修改后的消息处理逻辑 + 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); }); - } - - // 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; + 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; + } - // 延迟处理KaTeX确保DOM已更新 + if (ttsUrl.value) { 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); + if (audioStore.isVoiceEnabled) { + console.log("ttsUrl.value", ttsUrl.value); + // 播放音频 + playAudio(ttsUrl.value); + } }); } - }, 50); // 调整速度为50ms/字符 - // } else { - // chatStore.messages.pop(); - // chatStore.messages.push({ - // sender: "ai", - // content: status.msg - // }); - - // chatStore.setLoading(false); - // } + + // 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; // 请求失败时设置数据无效 + // chatStore.messages.pop(); + // chatStore.messages.push({ + // sender: "ai", + // content: "AI思考失败,请稍后再试... ", + // }); + chatStore.setLoading(false); + } finally { + await chatStore.getUserCount(); } - } catch (e) { - console.error("请求失败:", e); - hasValidData.value = false; // 请求失败时设置数据无效 - // chatStore.messages.pop(); - chatStore.messages.push({ - sender: "ai", - content: "AI思考失败,请稍后再试... ", - }); - chatStore.setLoading(false); - } finally { - await chatStore.getUserCount(); } } }, @@ -5145,11 +5218,19 @@ function renderAllKlineCharts() { // 初始化随机GIF onMounted(() => { + // 初始化marked组件 + marked.setOptions({ + breaks: true, // 支持换行符转换为- 试运行期间,AI小财神可以检索全市场数据 -
-- (每个市场20支股票,股票详情参见【公告】页面), -
-- 弘历会员每人每日拥有10次检索机会! -
+试运行期间,AI小财神可以检索全市场数据
+(每个市场20支股票,股票详情参见【公告】页面),
+弘历会员每人每日拥有10次检索机会!