diff --git a/src/assets/img/AIchat/圈1.png b/src/assets/img/AIchat/圈1.png new file mode 100644 index 0000000..d0116bb Binary files /dev/null and b/src/assets/img/AIchat/圈1.png differ diff --git a/src/views/AIchat.vue b/src/views/AIchat.vue index 1bea9f2..325db04 100644 --- a/src/views/AIchat.vue +++ b/src/views/AIchat.vue @@ -31,6 +31,7 @@ import title4 from "@/assets/img/AIchat/综合作战.png"; import logo1 from "@/assets/img/AIchat/夺宝奇兵logo.png"; import logo2 from "@/assets/img/AIchat/开启无限财富.png"; import bgc from "@/assets/img/AIchat/圈.png"; +import bgc1 from "@/assets/img/AIchat/圈1.png"; const chatStore = useChatStore(); const audioStore = useAudioStore(); const dataStore = useDataStore(); @@ -3771,7 +3772,7 @@ onUnmounted(() => {
- 夺宝奇兵大模型logo + 夺宝奇兵大模型logo 夺宝奇兵大模型logo 夺宝奇兵大模型logo
diff --git a/src/views/AiEmotion.vue b/src/views/AiEmotion.vue index deb4441..d930dfa 100644 --- a/src/views/AiEmotion.vue +++ b/src/views/AiEmotion.vue @@ -45,11 +45,11 @@
{{ displayDate }} -
+
情绪监控图标
-
+
温度计图标 @@ -63,11 +63,11 @@
-
+
情绪解码图标
-
+
情绪解码器图标 情绪解码器 @@ -76,11 +76,11 @@
-
+
情绪推演图标
-
+
探底雷达图表 情绪探底雷达 @@ -89,11 +89,11 @@
-
+
情绪套利
-
+
能量转化器图标 情绪能量转化器 @@ -277,6 +277,14 @@ const moduleVisibility = ref({ four: false, disclaimer: false }); + +// 图表组件显示状态 +const chartVisibility = ref({ + marketTemperature: false, + emotionDecod: false, + emotionalBottomRadar: false, + emoEnergyConverter: false +}); const typewriterTimers = ref([]); // 记录每个股票是否已经显示过打字机效果 const stockTypewriterShown = ref(new Map()); @@ -294,7 +302,7 @@ const displayDate = computed(() => { if (!currentStock.value?.apiData) return ""; const lastData = currentStock.value.apiData.GSWDJ?.at(-1); if (!lastData || !lastData[0]) return ""; - + const dateStr = lastData[0]; // 假设原格式为 YYYY-MM-DD 或 YYYY/MM/DD const dateMatch = dateStr.match(/(\d{4})[\-\/](\d{1,2})[\-\/](\d{1,2})/); @@ -303,7 +311,7 @@ const displayDate = computed(() => { // 转换为 DD/MM/YYYY 格式 return `更新时间:${day.padStart(2, '0')}/${month.padStart(2, '0')}/${year}`; } - + // 如果不匹配预期格式,返回原始值 return dateStr; }); @@ -372,6 +380,13 @@ watch(() => emotionStore.stockList, (newStockList) => { four: false, disclaimer: false }; + // 隐藏所有图表组件 + chartVisibility.value = { + marketTemperature: false, + emotionDecod: false, + emotionalBottomRadar: false, + emoEnergyConverter: false + }; console.log('股票列表已清空,页面数据已隐藏'); } }, { deep: true }); @@ -583,6 +598,13 @@ watch(currentStock, (newStock) => { } } else { console.log('股票数据不存在或API数据未加载'); + // 隐藏所有图表组件 + chartVisibility.value = { + marketTemperature: false, + emotionDecod: false, + emotionalBottomRadar: false, + emoEnergyConverter: false + }; } }, { immediate: true }); @@ -625,7 +647,7 @@ watch(parsedConclusion, (newConclusion) => { }, { immediate: true }); // 打字机效果函数 -function startTypewriterEffect(conclusion) { +function startTypewriterEffect(conclusion, onComplete) { console.log('开始打字机效果,结论数据:', conclusion); // 详细调试各个字段 @@ -758,10 +780,14 @@ function startTypewriterEffect(conclusion) { for (let i = 0; i <= disclaimerText.length; i++) { const timer = setTimeout(() => { displayedTexts.value.disclaimer = disclaimerText.substring(0, i); - // 在打字机效果的最后一个字符显示完成后,滚动到底部 + // 在打字机效果的最后一个字符显示完成后,滚动到底部并调用完成回调 if (i === disclaimerText.length) { setTimeout(() => { scrollToBottom(); + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } }, 100); } }, totalDelay + i * typeSpeed); @@ -877,7 +903,7 @@ function startImageRotation() { // 发送消息方法 -async function handleSendMessage(input) { +async function handleSendMessage(input, onComplete) { console.log("发送内容:", input); // 标记为用户主动搜索 isUserInitiated.value = true; @@ -885,6 +911,10 @@ async function handleSendMessage(input) { // 检查用户输入内容是否为空 if (!input || !input.trim()) { ElMessage.warning("输入内容不能为空"); + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } return; } @@ -903,6 +933,10 @@ async function handleSendMessage(input) { // 停止图片旋转,恢复历史数据 isRotating.value = false; messages.value = [...previousMessages, ...messages.value]; + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } return; } @@ -920,6 +954,10 @@ async function handleSendMessage(input) { // 停止图片旋转,恢复历史数据 isRotating.value = false; messages.value = [...previousMessages, ...messages.value]; + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } return; } @@ -947,7 +985,6 @@ async function handleSendMessage(input) { const result = await getReplyAPI(params); const response = await result.json(); const parsedData = JSON.parse(response.data); - console.log("第一个接口解析后的数据:", parsedData); // 检查用户输入是否合法 if (!parsedData || !parsedData.market || !parsedData.code) { @@ -956,6 +993,10 @@ async function handleSendMessage(input) { messages.value.push(aiMessage); isRotating.value = false; messages.value = [...previousMessages, ...messages.value]; + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } return; } @@ -963,7 +1004,6 @@ async function handleSendMessage(input) { // 设置加载状态,隐藏图表页面 isLoading.value = true; - console.log("工作流接口返回股票信息:", parsedData); isPageLoaded.value = false; // 调用第二个工作流接口 @@ -985,7 +1025,6 @@ async function handleSendMessage(input) { // 处理结论接口返回的数据 const conclusionResponse = await conclusionResult.json(); - console.log("第二个工作流接口返回数据:", conclusionResponse); // 检查所有数据是否都加载成功 if (conclusionResponse && conclusionResponse.data && fetchDataResult) { @@ -1006,26 +1045,28 @@ async function handleSendMessage(input) { console.error('更新用户次数失败:', error); } - console.log('所有数据加载完成,开始渲染页面'); // 确保页面状态更新后触发图表渲染和音频文本 nextTick(() => { if (currentStock.value && currentStock.value.apiData) { renderCharts(currentStock.value.apiData); - console.log('数据加载完成后开始渲染图表'); // 只有在用户主动搜索时才自动触发音频和文本 if (isUserInitiated.value && parsedConclusion.value && audioUrl.value) { const stockCode = currentStock.value.stockInfo?.code || currentStock.value.stockInfo?.symbol; if (stockCode && !stockTypewriterShown.value.has(stockCode)) { - console.log('用户主动搜索,立即触发音频和打字机效果'); - startTypewriterEffect(parsedConclusion.value); + startTypewriterEffect(parsedConclusion.value, onComplete); if (!stockAudioPlayed.value.has(stockCode)) { stockAudioPlayed.value.set(stockCode, true); playAudio(audioUrl.value); } stockTypewriterShown.value.set(stockCode, true); + } else { + // 如果不需要打字机效果,直接调用完成回调 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } } } @@ -1040,6 +1081,10 @@ async function handleSendMessage(input) { messages.value.push(aiMessage); isRotating.value = false; messages.value = [...previousMessages, ...messages.value]; + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } return; } } catch (error) { @@ -1048,6 +1093,10 @@ async function handleSendMessage(input) { // 请求失败时停止图片旋转,恢复历史数据 isRotating.value = false; messages.value = [...previousMessages, ...messages.value]; + // 调用完成回调,重新启用输入框 + if (onComplete && typeof onComplete === 'function') { + onComplete(); + } return; } finally { // 停止图片旋转(只有在设置了旋转状态时才需要停止) @@ -1082,11 +1131,8 @@ async function fetchData(code, market, stockName, queryText) { ); const stockDataResponse = stockDataResult.data; // 获取返回所有的数据 - console.log('图表数据接口返回数据:', stockDataResponse.data); if (stockDataResponse.code === 200 && stockDataResponse.data) { - console.log(stockDataResponse.code) - // 创建股票数据对象 const stockData = { queryText: queryText, @@ -1108,7 +1154,6 @@ async function fetchData(code, market, stockName, queryText) { return false; // 返回失败标识 } } catch (error) { - console.error('fetchData error:', error); const aiMessage = reactive({ sender: 'ai', text: '图表数据请求失败,请检查网络连接' }); messages.value.push(aiMessage); return false; // 返回失败标识 @@ -1117,52 +1162,114 @@ async function fetchData(code, market, stockName, queryText) { // 渲染组件图表的方法 function renderCharts(data) { + console.log('开始渲染图表,数据:', data); + + // 深拷贝数据避免污染原始数据 + const clonedData = JSON.parse(JSON.stringify(data)); + + // 先设置图表组件显示状态 + chartVisibility.value = { + marketTemperature: !!(clonedData.GSWDJ && clonedData.GSWDJ.length > 0), + emotionDecod: !!(clonedData.QXJMQ && clonedData.QXJMQ.length > 0), + emotionalBottomRadar: !!(clonedData.QXTDLD && clonedData.QXTDLD.length > 0), + emoEnergyConverter: !!(clonedData.QXNLZHQ && clonedData.QXNLZHQ.length > 0) + }; + + console.log('图表显示状态:', chartVisibility.value); + nextTick(() => { - // 添加小延迟确保DOM完全更新 + // 增加延迟确保DOM完全更新和组件完全挂载 setTimeout(() => { try { - // 深拷贝数据避免污染原始数据 - const clonedData = JSON.parse(JSON.stringify(data)); - console.log('已深拷贝数据,避免污染原始数据'); - console.log('所有数据1111111111111:', clonedData) + console.log('图表组件ref状态:', { + marketTemperatureRef: !!marketTemperatureRef.value, + emotionDecodRef: !!emotionDecodRef.value, + emotionalBottomRadarRef: !!emotionalBottomRadarRef.value, + emoEnergyConverterRef: !!emoEnergyConverterRef.value + }); + // 渲染股市温度计图表 - if (marketTemperatureRef.value && clonedData.GSWDJ) { - console.log("开始渲染股市温度计图表"); - console.log("股市温度计数据", clonedData.GSWDJ); - marketTemperatureRef.value.initChart(clonedData.GSWDJ, clonedData.KLine20, clonedData.WDRL); - console.log("股市温度计图表已渲染"); + if (marketTemperatureRef.value && chartVisibility.value.marketTemperature) { + console.log('开始渲染股市温度计图表'); + console.log('marketTemperatureRef方法:', typeof marketTemperatureRef.value.initChart); + if (typeof marketTemperatureRef.value.initChart === 'function') { + try { + marketTemperatureRef.value.initChart(clonedData.GSWDJ, clonedData.KLine20, clonedData.WDRL); + console.log('股市温度计图表渲染成功'); + } catch (error) { + console.error('股市温度计图表渲染失败:', error); + } + } else { + console.error('marketTemperatureRef.initChart 方法不存在'); + } + } else { + console.log('股市温度计图表未渲染,ref存在:', !!marketTemperatureRef.value, '数据存在:', chartVisibility.value.marketTemperature); } + // 渲染情绪解码器图表 - if (emotionDecodRef.value && clonedData.QXJMQ) { - console.log("开始渲染情绪解码器图表"); - console.log("情绪解码器数据", clonedData.QXJMQ); - emotionDecodRef.value.initQXNLZHEcharts(clonedData.KLine20, clonedData.QXJMQ); - console.log("情绪解码器图表已渲染"); + if (emotionDecodRef.value && chartVisibility.value.emotionDecod) { + console.log('开始渲染情绪解码器图表'); + console.log('emotionDecodRef方法:', typeof emotionDecodRef.value.initQXNLZHEcharts); + if (typeof emotionDecodRef.value.initQXNLZHEcharts === 'function') { + try { + emotionDecodRef.value.initQXNLZHEcharts(clonedData.KLine20, clonedData.QXJMQ); + console.log('情绪解码器图表渲染成功'); + } catch (error) { + console.error('情绪解码器图表渲染失败:', error); + } + } else { + console.error('emotionDecodRef.initQXNLZHEcharts 方法不存在'); + } + } else { + console.log('情绪解码器图表未渲染,ref存在:', !!emotionDecodRef.value, '数据存在:', chartVisibility.value.emotionDecod); } + // 渲染情绪探底雷达图表 - if (emotionalBottomRadarRef.value && clonedData.QXTDLD) { - console.log("开始渲染情绪探底雷达图表"); - console.log("探底雷达数据", clonedData.QXTDLD); - emotionalBottomRadarRef.value.initEmotionalBottomRadar( - clonedData.KLine20, - clonedData.QXTDLD - ); - console.log("情绪探底雷达图表已渲染"); + if (emotionalBottomRadarRef.value && chartVisibility.value.emotionalBottomRadar) { + console.log('开始渲染情绪探底雷达图表'); + console.log('emotionalBottomRadarRef方法:', typeof emotionalBottomRadarRef.value.initEmotionalBottomRadar); + if (typeof emotionalBottomRadarRef.value.initEmotionalBottomRadar === 'function') { + try { + emotionalBottomRadarRef.value.initEmotionalBottomRadar( + clonedData.KLine20, + clonedData.QXTDLD + ); + console.log('情绪探底雷达图表渲染成功'); + } catch (error) { + console.error('情绪探底雷达图表渲染失败:', error); + } + } else { + console.error('emotionalBottomRadarRef.initEmotionalBottomRadar 方法不存在'); + } + } else { + console.log('情绪探底雷达图表未渲染,ref存在:', !!emotionalBottomRadarRef.value, '数据存在:', chartVisibility.value.emotionalBottomRadar); } + // 渲染情绪能量转化器图表 - if (emoEnergyConverterRef.value && clonedData.QXNLZHQ) { - console.log("开始渲染情绪能量转化器图表"); - console.log("KLine20:", clonedData.KLine20); - console.log("QXNLZHQ:", clonedData.QXNLZHQ); - emoEnergyConverterRef.value.initQXNLZHEcharts(clonedData.KLine20, clonedData.QXNLZHQ); - console.log("情绪能量转化器图表已渲染"); + if (emoEnergyConverterRef.value && chartVisibility.value.emoEnergyConverter) { + console.log('开始渲染情绪能量转化器图表'); + console.log('emoEnergyConverterRef方法:', typeof emoEnergyConverterRef.value.initQXNLZHEcharts); + if (typeof emoEnergyConverterRef.value.initQXNLZHEcharts === 'function') { + try { + emoEnergyConverterRef.value.initQXNLZHEcharts(clonedData.KLine20, clonedData.QXNLZHQ); + console.log('情绪能量转化器图表渲染成功'); + } catch (error) { + console.error('情绪能量转化器图表渲染失败:', error); + } + } else { + console.error('emoEnergyConverterRef.initQXNLZHEcharts 方法不存在'); + } + } else { + console.log('情绪能量转化器图表未渲染,ref存在:', !!emoEnergyConverterRef.value, '数据存在:', chartVisibility.value.emoEnergyConverter); } + + console.log('图表渲染完成'); } catch (error) { - console.error('图表渲染过程中发生错误:', error); + console.error('图表渲染错误:', error); const aiMessage = reactive({ sender: 'ai', text: '图表渲染失败,请重试' }); messages.value.push(aiMessage); } - }, 100); // 100ms延迟确保DOM稳定 + }, 500); // 增加延迟到500ms确保DOM和组件完全稳定 }); } @@ -1172,7 +1279,7 @@ const scrollToBottom = async () => { console.log('用户正在手动滚动,跳过自动滚动'); return; } - + const container = userInputDisplayRef.value; if (!container) return; await nextTick(); @@ -1185,12 +1292,12 @@ const scrollToBottom = async () => { // 处理用户滚动事件 const handleUserScroll = () => { isUserScrolling.value = true; - + // 清除之前的定时器 if (scrollTimeout.value) { clearTimeout(scrollTimeout.value); } - + // 设置定时器,2秒后重新允许自动滚动 scrollTimeout.value = setTimeout(() => { isUserScrolling.value = false; @@ -1408,7 +1515,7 @@ onMounted(async () => { // 添加新的监听器 window.addEventListener('resize', globalResizeHandler); window.aiEmotionGlobalResizeHandler = globalResizeHandler; - + // 添加滚动事件监听器 const container = userInputDisplayRef.value; if (container) { @@ -1488,7 +1595,7 @@ onUnmounted(() => { window.removeEventListener('resize', window.aiEmotionGlobalResizeHandler); window.aiEmotionGlobalResizeHandler = null; } - + // 清理滚动事件监听器 const container = userInputDisplayRef.value; if (container) { @@ -1496,7 +1603,7 @@ onUnmounted(() => { container.removeEventListener('touchmove', handleTouchMove); container.removeEventListener('scroll', handleUserScroll); } - + // 清理滚动定时器 if (scrollTimeout.value) { clearTimeout(scrollTimeout.value); @@ -1515,10 +1622,10 @@ defineExpose({