|
@ -684,25 +684,25 @@ const addTypingTask = (message, content, speed) => { |
|
|
async function showThinkingProcess(stockName = null) { |
|
|
async function showThinkingProcess(stockName = null) { |
|
|
// 第一步:正在思考 |
|
|
// 第一步:正在思考 |
|
|
const thinkingMessage1 = reactive({ |
|
|
const thinkingMessage1 = reactive({ |
|
|
sender: 'ai', |
|
|
|
|
|
class: 'ing', |
|
|
|
|
|
type: 'ing', |
|
|
|
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "ing", |
|
|
|
|
|
type: "ing", |
|
|
flag: true, |
|
|
flag: true, |
|
|
content: '正在思考......', |
|
|
|
|
|
gif: '/src/assets/img/gif/思考.gif' |
|
|
|
|
|
|
|
|
content: "正在思考......", |
|
|
|
|
|
gif: "/src/assets/img/gif/思考.gif", |
|
|
}); |
|
|
}); |
|
|
chatStore.messages.push(thinkingMessage1); |
|
|
chatStore.messages.push(thinkingMessage1); |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
chatStore.messages.pop(); |
|
|
chatStore.messages.pop(); |
|
|
|
|
|
|
|
|
// 第二步:正在解析关键数据(持续显示直到获取到股票名称) |
|
|
// 第二步:正在解析关键数据(持续显示直到获取到股票名称) |
|
|
const thinkingMessage2 = reactive({ |
|
|
const thinkingMessage2 = reactive({ |
|
|
sender: 'ai', |
|
|
|
|
|
class: 'ing', |
|
|
|
|
|
type: 'ing', |
|
|
|
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "ing", |
|
|
|
|
|
type: "ing", |
|
|
flag: true, |
|
|
flag: true, |
|
|
content: '正在解析关键数据......', |
|
|
|
|
|
gif: '/src/assets/img/gif/解析.gif' |
|
|
|
|
|
|
|
|
content: "正在解析关键数据......", |
|
|
|
|
|
gif: "/src/assets/img/gif/解析.gif", |
|
|
}); |
|
|
}); |
|
|
chatStore.messages.push(thinkingMessage2); |
|
|
chatStore.messages.push(thinkingMessage2); |
|
|
|
|
|
|
|
@ -712,33 +712,33 @@ async function showThinkingProcess(stockName = null) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 有股票名称后,继续后续步骤 |
|
|
// 有股票名称后,继续后续步骤 |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
chatStore.messages.pop(); |
|
|
chatStore.messages.pop(); |
|
|
|
|
|
|
|
|
// 第三步:生成具体股票的全景作战报告 |
|
|
// 第三步:生成具体股票的全景作战报告 |
|
|
const thinkingMessage3 = reactive({ |
|
|
const thinkingMessage3 = reactive({ |
|
|
sender: 'ai', |
|
|
|
|
|
class: 'ing', |
|
|
|
|
|
type: 'ing', |
|
|
|
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "ing", |
|
|
|
|
|
type: "ing", |
|
|
flag: true, |
|
|
flag: true, |
|
|
content: `正在生成${stockName}全景作战报告......`, |
|
|
content: `正在生成${stockName}全景作战报告......`, |
|
|
gif: '/src/assets/img/gif/生成.gif' |
|
|
|
|
|
|
|
|
gif: "/src/assets/img/gif/生成.gif", |
|
|
}); |
|
|
}); |
|
|
chatStore.messages.push(thinkingMessage3); |
|
|
chatStore.messages.push(thinkingMessage3); |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
chatStore.messages.pop(); |
|
|
chatStore.messages.pop(); |
|
|
|
|
|
|
|
|
// 第四步:报告已生成 |
|
|
// 第四步:报告已生成 |
|
|
const thinkingMessage4 = reactive({ |
|
|
const thinkingMessage4 = reactive({ |
|
|
sender: 'ai', |
|
|
|
|
|
class: 'ing', |
|
|
|
|
|
type: 'ing', |
|
|
|
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "ing", |
|
|
|
|
|
type: "ing", |
|
|
flag: true, |
|
|
flag: true, |
|
|
content: '报告已生成!', |
|
|
|
|
|
gif: '/src/assets/img/gif/生成.gif' |
|
|
|
|
|
|
|
|
content: "报告已生成!", |
|
|
|
|
|
gif: "/src/assets/img/gif/生成.gif", |
|
|
}); |
|
|
}); |
|
|
chatStore.messages.push(thinkingMessage4); |
|
|
chatStore.messages.push(thinkingMessage4); |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
chatStore.messages.pop(); |
|
|
chatStore.messages.pop(); |
|
|
|
|
|
|
|
|
return null; |
|
|
return null; |
|
@ -749,7 +749,7 @@ async function continueThinkingProcess(thinkingMessageRef, stockName) { |
|
|
if (!thinkingMessageRef || !stockName) return; |
|
|
if (!thinkingMessageRef || !stockName) return; |
|
|
|
|
|
|
|
|
// 等待一段时间后继续 |
|
|
// 等待一段时间后继续 |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
// 移除第二步消息 |
|
|
// 移除第二步消息 |
|
|
const index = chatStore.messages.indexOf(thinkingMessageRef); |
|
|
const index = chatStore.messages.indexOf(thinkingMessageRef); |
|
@ -759,27 +759,27 @@ async function continueThinkingProcess(thinkingMessageRef, stockName) { |
|
|
|
|
|
|
|
|
// 第三步:生成具体股票的全景作战报告 |
|
|
// 第三步:生成具体股票的全景作战报告 |
|
|
const thinkingMessage3 = reactive({ |
|
|
const thinkingMessage3 = reactive({ |
|
|
sender: 'ai', |
|
|
|
|
|
class: 'ing', |
|
|
|
|
|
type: 'ing', |
|
|
|
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "ing", |
|
|
|
|
|
type: "ing", |
|
|
flag: true, |
|
|
flag: true, |
|
|
content: `正在生成${stockName}全景作战报告......`, |
|
|
content: `正在生成${stockName}全景作战报告......`, |
|
|
gif: '/src/assets/img/gif/生成.gif' |
|
|
|
|
|
|
|
|
gif: "/src/assets/img/gif/生成.gif", |
|
|
}); |
|
|
}); |
|
|
chatStore.messages.push(thinkingMessage3); |
|
|
chatStore.messages.push(thinkingMessage3); |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
chatStore.messages.pop(); |
|
|
chatStore.messages.pop(); |
|
|
|
|
|
|
|
|
// 第四步:报告已生成 |
|
|
// 第四步:报告已生成 |
|
|
const thinkingMessage4 = reactive({ |
|
|
const thinkingMessage4 = reactive({ |
|
|
sender: 'ai', |
|
|
|
|
|
class: 'ing', |
|
|
|
|
|
type: 'ing', |
|
|
|
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "ing", |
|
|
|
|
|
type: "ing", |
|
|
flag: true, |
|
|
flag: true, |
|
|
content: '报告已生成!' |
|
|
|
|
|
|
|
|
content: "报告已生成!", |
|
|
}); |
|
|
}); |
|
|
chatStore.messages.push(thinkingMessage4); |
|
|
chatStore.messages.push(thinkingMessage4); |
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1500)); |
|
|
chatStore.messages.pop(); |
|
|
chatStore.messages.pop(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -840,7 +840,10 @@ watch( |
|
|
if (result.code == 200) { |
|
|
if (result.code == 200) { |
|
|
// 获取到股票名称后,继续思考过程 |
|
|
// 获取到股票名称后,继续思考过程 |
|
|
if (thinkingMessageRef && codeData.value.name) { |
|
|
if (thinkingMessageRef && codeData.value.name) { |
|
|
await continueThinkingProcess(thinkingMessageRef, codeData.value.name); |
|
|
|
|
|
|
|
|
await continueThinkingProcess( |
|
|
|
|
|
thinkingMessageRef, |
|
|
|
|
|
codeData.value.name |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
chatStore.messages.push({ |
|
|
chatStore.messages.push({ |
|
@ -2347,140 +2350,6 @@ watch( |
|
|
chatStore.isLoading = false; |
|
|
chatStore.isLoading = false; |
|
|
emit("enableInput"); |
|
|
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) { |
|
|
} catch (e) { |
|
|
console.error("请求失败:", e); |
|
|
console.error("请求失败:", e); |
|
|
hasValidData.value = false; // 请求失败时设置数据无效 |
|
|
hasValidData.value = false; // 请求失败时设置数据无效 |
|
@ -2500,6 +2369,274 @@ watch( |
|
|
{ deep: true } |
|
|
{ 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 = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【主力行为】</p><p>${clickRecord.value.wokeFlowData.Three.zhuli1}</p><p>${clickRecord.value.wokeFlowData.Three.zhuli2}</p><p>${clickRecord.value.wokeFlowData.Three.zhuli3}</p>`; |
|
|
|
|
|
|
|
|
|
|
|
// 先推送初始消息 |
|
|
|
|
|
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 = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【空间维度】</p><p style="display:flex;justify-content:center;">${arr[0]},${arr[1]}</p><p style="display:flex;justify-content:center;">${arr[2]},${arr[3]}</p>`; |
|
|
|
|
|
const shijian = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【时间维度】</p><p style="display:flex;justify-content:center;">${clickRecord.value.wokeFlowData.Three.shijian}</p>`; |
|
|
|
|
|
const nengliang = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【能量维度】</p><p style="display:flex;justify-content:center;">${clickRecord.value.wokeFlowData.Three.nengliang}</p>`; |
|
|
|
|
|
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 = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【触发条件】</p><p>${clickRecord.value.wokeFlowData.Four.cftl}</p>`; |
|
|
|
|
|
const gfzl = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【攻防指令】</p><p>${clickRecord.value.wokeFlowData.Four.gfzl}</p>`; |
|
|
|
|
|
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 KlineCanvsEcharts(containerId) { |
|
|
function vwToPx(vw) { |
|
|
function vwToPx(vw) { |
|
|
console.log((window.innerWidth * vw) / 100, "vwToPx"); |
|
|
console.log((window.innerWidth * vw) / 100, "vwToPx"); |
|
@ -4203,7 +4340,7 @@ onUnmounted(() => { |
|
|
:src="isVoice && audioStore.isPlaying ? voiceNoActive : voice" |
|
|
:src="isVoice && audioStore.isPlaying ? voiceNoActive : voice" |
|
|
class="user-message-speaker" |
|
|
class="user-message-speaker" |
|
|
:class="{ |
|
|
:class="{ |
|
|
'speaker-active': isVoice && audioStore.isPlaying |
|
|
|
|
|
|
|
|
'speaker-active': isVoice && audioStore.isPlaying, |
|
|
}" |
|
|
}" |
|
|
@click="toggleVoiceForUser" |
|
|
@click="toggleVoiceForUser" |
|
|
alt="喇叭" |
|
|
alt="喇叭" |
|
@ -4228,73 +4365,81 @@ onUnmounted(() => { |
|
|
[msg.class]: msg.class, |
|
|
[msg.class]: msg.class, |
|
|
}" |
|
|
}" |
|
|
> |
|
|
> |
|
|
<div v-if="msg.type === 'kline'" class="kline-container"> |
|
|
|
|
|
<div :id="'kline-container-' + index" class="chart-mount-point"> |
|
|
|
|
|
<div v-if="!msg.hasValidData" class="no-data-message"> |
|
|
|
|
|
<p>暂无K线数据</p> |
|
|
|
|
|
|
|
|
<div v-if="msg.type === 'kline'" class="kline-container"> |
|
|
|
|
|
<div :id="'kline-container-' + index" class="chart-mount-point"> |
|
|
|
|
|
<div v-if="!msg.hasValidData" class="no-data-message"> |
|
|
|
|
|
<p>暂无K线数据</p> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'ing'" class="ai-message-container"> |
|
|
|
|
|
<img v-if="msg.gif" :src="msg.gif" alt="思考过程" class="thinking-gif" /> |
|
|
|
|
|
<div class="ai-message-content"> |
|
|
|
|
|
<div v-if="msg.flag"> |
|
|
|
|
|
<span>{{ msg.content }}</span> |
|
|
|
|
|
<span class="loading-dots"> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
</span> |
|
|
|
|
|
|
|
|
<div v-else-if="msg.type == 'ing'" class="ai-message-container"> |
|
|
|
|
|
<img |
|
|
|
|
|
v-if="msg.gif" |
|
|
|
|
|
:src="msg.gif" |
|
|
|
|
|
alt="思考过程" |
|
|
|
|
|
class="thinking-gif" |
|
|
|
|
|
/> |
|
|
|
|
|
<div class="ai-message-content"> |
|
|
|
|
|
<div v-if="msg.flag"> |
|
|
|
|
|
<span>{{ msg.content }}</span> |
|
|
|
|
|
<span class="loading-dots"> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
<span class="dot">.</span> |
|
|
|
|
|
</span> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else v-html="msg.content"></div> |
|
|
</div> |
|
|
</div> |
|
|
<div v-else v-html="msg.content"></div> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'title1'" style="display: flex; width: 100%"> |
|
|
|
|
|
<div class="mainTitle"> |
|
|
|
|
|
{{ msg.content }} |
|
|
|
|
|
|
|
|
<div |
|
|
|
|
|
v-else-if="msg.type == 'title1'" |
|
|
|
|
|
style="display: flex; width: 100%" |
|
|
|
|
|
> |
|
|
|
|
|
<div class="mainTitle"> |
|
|
|
|
|
{{ msg.content }} |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="date"> |
|
|
|
|
|
{{ msg.date }} |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="date"> |
|
|
|
|
|
{{ msg.date }} |
|
|
|
|
|
|
|
|
<div v-else-if="msg.type == 'title2'" class="title2"> |
|
|
|
|
|
<img class="title1Img" :src="title1" alt="出错了" /> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'title2'" class="title2"> |
|
|
|
|
|
<img class="title1Img" :src="title1" alt="出错了" /> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'title3'" class="title3"> |
|
|
|
|
|
<img class="title2Img" :src="msg.content" alt="出错了" /> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'content1'" class="content1"> |
|
|
|
|
|
<div v-if="msg.kline" class="kline-container content1chart"> |
|
|
|
|
|
<div :id="'kline-container-' + index" class="chart-mount-point"> |
|
|
|
|
|
<div v-if="!msg.hasValidData" class="no-data-message"> |
|
|
|
|
|
<p>暂无数据</p> |
|
|
|
|
|
|
|
|
<div v-else-if="msg.type == 'title3'" class="title3"> |
|
|
|
|
|
<img class="title2Img" :src="msg.content" alt="出错了" /> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'content1'" class="content1"> |
|
|
|
|
|
<div v-if="msg.kline" class="kline-container content1chart"> |
|
|
|
|
|
<div :id="'kline-container-' + index" class="chart-mount-point"> |
|
|
|
|
|
<div v-if="!msg.hasValidData" class="no-data-message"> |
|
|
|
|
|
<p>暂无数据</p> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else class="content1Text"> |
|
|
|
|
|
<div v-html="msg.content" class="text1"></div> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div v-else class="content1Text"> |
|
|
|
|
|
<div v-html="msg.content" class="text1"></div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'content2'" class="content2"> |
|
|
|
|
|
<div class="kline-container content2chart"> |
|
|
|
|
|
<div :id="'kline-container-' + index" class="chart-mount-point"> |
|
|
|
|
|
<div v-if="!msg.hasValidData" class="no-data-message"> |
|
|
|
|
|
<p>暂无数据</p> |
|
|
|
|
|
|
|
|
<div v-else-if="msg.type == 'content2'" class="content2"> |
|
|
|
|
|
<div class="kline-container content2chart"> |
|
|
|
|
|
<div :id="'kline-container-' + index" class="chart-mount-point"> |
|
|
|
|
|
<div v-if="!msg.hasValidData" class="no-data-message"> |
|
|
|
|
|
<p>暂无数据</p> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'content3'" class="content3"> |
|
|
|
|
|
<div class="content3Text"> |
|
|
|
|
|
<div v-html="msg.content" class="text3"></div> |
|
|
|
|
|
|
|
|
<div v-else-if="msg.type == 'content3'" class="content3"> |
|
|
|
|
|
<div class="content3Text"> |
|
|
|
|
|
<div v-html="msg.content" class="text3"></div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'mianze'" class="mianze"> |
|
|
|
|
|
<div v-html="msg.content"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else-if="msg.type == 'mianze'" class="mianze"> |
|
|
|
|
|
<div v-html="msg.content"></div> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else v-html="msg.content"></div> |
|
|
<div v-else v-html="msg.content"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
@ -4786,7 +4931,8 @@ p { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@keyframes float { |
|
|
@keyframes float { |
|
|
0%, 100% { |
|
|
|
|
|
|
|
|
0%, |
|
|
|
|
|
100% { |
|
|
transform: translateY(0px); |
|
|
transform: translateY(0px); |
|
|
} |
|
|
} |
|
|
50% { |
|
|
50% { |
|
|