From 0668475e40ce2696c97120f33a1373aa28a95902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E6=9D=B0?= Date: Sun, 22 Jun 2025 09:05:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=AC=E5=91=8A=E5=AD=97=E4=BD=93=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=9B=E6=AC=A1=E6=95=B0=E5=8F=B3=E7=A7=BB=EF=BC=9B?= =?UTF-8?q?=E6=8E=A2=E5=BA=95=E9=9B=B7=E8=BE=BE=E5=9B=BE=E8=A1=A8=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=9B=E8=83=BD=E9=87=8F=E8=BD=AC=E5=8C=96=E5=99=A8?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9B=E8=A7=A3=E7=A0=81=E5=99=A8=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=9B=E6=B8=A9=E5=BA=A6=E8=AE=A1y=E8=BD=B4?= =?UTF-8?q?=E5=88=BB=E5=BA=A6=E5=80=BC=E4=BF=AE=E6=94=B9=EF=BC=9B=E6=B8=85?= =?UTF-8?q?=E7=A9=BA=E6=8C=89=E9=92=AE=E5=A4=A7=E5=B0=8F=E8=B0=83=E6=95=B4?= =?UTF-8?q?=EF=BC=9B=E6=83=85=E7=BB=AA=E5=A4=A7=E6=A8=A1=E5=9E=8B=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E8=B0=83=E6=95=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/AiEmotion.vue | 51 +++++----- src/views/Announcement.vue | 5 + src/views/components/StockTabs.vue | 2 +- src/views/components/emoEnergyConverter.vue | 105 +++++++++++++++++++- src/views/components/emotionDecod.vue | 13 +-- src/views/components/emotionalBottomRadar.vue | 138 ++++++++++++++++++-------- src/views/components/marketTemperature.vue | 29 ++++-- src/views/homePage.vue | 2 +- 8 files changed, 263 insertions(+), 82 deletions(-) diff --git a/src/views/AiEmotion.vue b/src/views/AiEmotion.vue index 59987b8..19d40ef 100644 --- a/src/views/AiEmotion.vue +++ b/src/views/AiEmotion.vue @@ -109,13 +109,17 @@

🔍 情绪监控-金融宇宙的【量子检测网络】 - 核心任务:构建全市场情绪引力场雷达,实时监测资金流向和情绪波动

+ 核心任务:构建全市场情绪引力场雷达,实时监测资金流向和情绪波动 +

🧠 情绪解码-主力思维的【神经破译矩阵】 - 核心任务:解构资金行为的量子密码,破译主力操盘意图和策略布局

+ 核心任务:解构资金行为的量子密码,破译主力操盘意图和策略布局 +

🔮 情绪推演-未来战争的【时空推演舱】 - 核心任务:基于情绪数据推演未来走势,预测市场转折点和机会窗口

+ 核心任务:基于情绪数据推演未来走势,预测市场转折点和机会窗口 +

💰 情绪套利-财富裂变的【粒子对撞机】 - 核心任务:将情绪差转化为收益粒子流,实现情绪能量的价值转换

+ 核心任务:将情绪差转化为收益粒子流,实现情绪能量的价值转换 +

@@ -353,17 +357,17 @@ watch(currentStock, (newStock) => { nextTick(() => { renderCharts(newStock.apiData); - + console.log('0000000000000000000000000',newStock.apiData) // 检查场景应用部分是否已经在视口中,如果是则立即触发效果 setTimeout(() => { if (scenarioApplicationRef.value && parsedConclusion.value) { const stockCode = newStock.stockInfo?.code || newStock.stockInfo?.symbol; - + // 如果该股票已经显示过,不需要再处理 if (stockCode && stockTypewriterShown.value.has(stockCode)) { return; } - + const rect = scenarioApplicationRef.value.getBoundingClientRect(); const isInViewport = rect.top < window.innerHeight && rect.bottom > 0; @@ -395,7 +399,7 @@ watch(currentStock, (newStock) => { } else { // 非第一次或已经触发过:直接显示完整内容,不播放音频和打字机效果 console.log('非第一次股票切换或已触发过,直接显示完整内容'); - + // 直接显示完整内容 const conclusion = parsedConclusion.value; displayedTexts.value = { @@ -469,7 +473,7 @@ watch(parsedConclusion, (newConclusion) => { if (stockTypewriterShown.value.has(stockCode)) { return; } - + // 该股票第一次:播放音频和打字机效果 console.log('该股票第一次音频准备完成且场景应用部分在视口中,立即触发效果'); hasTriggeredTypewriter.value = true; @@ -876,7 +880,7 @@ function renderCharts(data) { // 深拷贝数据避免污染原始数据 const clonedData = JSON.parse(JSON.stringify(data)); console.log('已深拷贝数据,避免污染原始数据'); - + console.log('所有数据1111111111111:', clonedData) // 渲染股市温度计图表 if (marketTemperatureRef.value && clonedData.GSWDJ) { console.log("开始渲染股市温度计图表"); @@ -894,7 +898,7 @@ function renderCharts(data) { // 渲染情绪探底雷达图表 if (emotionalBottomRadarRef.value && clonedData.QXTDLD) { console.log("开始渲染情绪探底雷达图表"); - console.log("数据", clonedData.QXTDLD); + console.log("探底雷达数据", clonedData.QXTDLD); emotionalBottomRadarRef.value.initEmotionalBottomRadar( clonedData.KLine20, clonedData.QXTDLD @@ -1051,7 +1055,7 @@ function setupIntersectionObserver() { } else { // 非第一次或已经触发过:直接显示完整内容,不播放音频和打字机效果 console.log('非第一次进入场景应用或已触发过,直接显示完整内容'); - + // 直接显示完整内容 const conclusion = parsedConclusion.value; displayedTexts.value = { @@ -1421,10 +1425,6 @@ defineExpose({ margin-bottom: 1%; } -/* .class0503 { - min-width: 100%; -} */ - .class0402 { width: 80%; margin: 0 auto; @@ -1580,7 +1580,7 @@ defineExpose({ /* 设置容器宽度 */ height: auto; /* 高度根据内容动态变化 */ - min-height: 72rem; + min-height: 66rem; /* 设置最小高度,确保图片显示 */ margin: 0 auto; } @@ -1596,7 +1596,7 @@ defineExpose({ /* 设置容器宽度 */ height: auto; /* 高度根据内容动态变化 */ - min-height: 70rem; + min-height: 86rem; /* 设置最小高度,确保图片显示 */ margin: 0 auto; } @@ -2178,7 +2178,7 @@ defineExpose({ background-repeat: no-repeat; width: 100%; height: auto; - min-height: 45rem; + min-height: 48rem; } .class06 { @@ -2186,7 +2186,7 @@ defineExpose({ background-repeat: no-repeat; width: 100%; height: auto; - min-height: 33rem; + min-height: 35rem; margin: 0 auto; } @@ -2259,6 +2259,7 @@ defineExpose({ padding-top: 10%; } } + /* 加载提示样式 */ .loading-container { display: flex; @@ -2289,8 +2290,13 @@ defineExpose({ } @keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } } .loading-text { @@ -2300,5 +2306,4 @@ defineExpose({ text-shadow: 0 2px 8px rgba(0, 212, 255, 0.5); letter-spacing: 1px; } - \ No newline at end of file diff --git a/src/views/Announcement.vue b/src/views/Announcement.vue index ba59f39..b8e413b 100644 --- a/src/views/Announcement.vue +++ b/src/views/Announcement.vue @@ -163,6 +163,11 @@ onMounted(() => { .announcementItem { margin-bottom: 10px; + color: white; +} + +p { + color: white; } .codeItem { diff --git a/src/views/components/StockTabs.vue b/src/views/components/StockTabs.vue index 779521f..8134075 100644 --- a/src/views/components/StockTabs.vue +++ b/src/views/components/StockTabs.vue @@ -188,7 +188,7 @@ const clearAllStocks = async () => { .clear-all-btn { padding: 4px 8px; - font-size: 12px; + font-size: 17px; background: #dc3545; color: white; border: none; diff --git a/src/views/components/emoEnergyConverter.vue b/src/views/components/emoEnergyConverter.vue index 32beed8..646c338 100644 --- a/src/views/components/emoEnergyConverter.vue +++ b/src/views/components/emoEnergyConverter.vue @@ -81,7 +81,6 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { value, }); }); - // 动态区域配置 // dd到zc 低吸区------情绪冰点区 ; zc到ht 关注区------认知潜伏区; ht到qs 回调区------多空消化区 ; qs到tp 拉升区------共识加速区; // tp到js 突破区------情绪临界区 ; js到yl 警示区-------杠杆失衡区 ; yl到gg 风险区-------情绪熔断区; @@ -241,6 +240,108 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { let option; // 设置图表配置 option = { + tooltip: { + show: true, + trigger: 'axis', + axisPointer: { + type: 'cross', + crossStyle: { + color: '#fff', + width: 1, + type: 'solid' + }, + lineStyle: { + color: '#fff', + width: 1, + type: 'solid' + }, + label: { + backgroundColor: 'rgba(0, 0, 0, 0.8)', + color: '#fff', + borderColor: '#fff', + borderWidth: 1 + } + }, + backgroundColor: 'rgba(0, 0, 0, 0.8)', + borderColor: '#fff', + borderWidth: 1, + padding: 10, + textStyle: { + color: '#fff', + fontSize: 12 + }, + formatter: function (params) { + if (!params || params.length === 0) return '' + + let result = `
${params[0].name}
` + + params.forEach(param => { + let value = param.value + let color = param.color + + if (param.seriesType === 'candlestick') { + let openPrice = value[0] // 开盘价 + let closePrice = value[1] // 收盘价 + let lowPrice = value[2] // 最低价 + let highPrice = value[3] // 最高价 + + // 检查数据有效性 + if (typeof openPrice !== 'number' || typeof closePrice !== 'number' || + typeof lowPrice !== 'number' || typeof highPrice !== 'number') { + return '' + } + + let priceChange = closePrice - openPrice + let changePercent = ((priceChange / openPrice) * 100).toFixed(2) + let changeColor = priceChange >= 0 ? '#ef232a' : '#14b143' + + result += `
` + result += `
${param.seriesName}
` + result += `
开盘: ${openPrice.toFixed(2)}
` + result += `
收盘: ${closePrice.toFixed(2)}
` + result += `
最低: ${lowPrice.toFixed(2)}
` + result += `
最高: ${highPrice.toFixed(2)}
` + result += `
涨跌: ${priceChange >= 0 ? '+' : ''}${priceChange.toFixed(2)} (${changePercent}%)
` + result += `
` + } else if (param.seriesName === '止盈线' && value !== null && value !== undefined && typeof value === 'number') { + result += `
${param.seriesName}: ${value.toFixed(2)}
` + } else if (param.seriesName === '止损线' && value !== null && value !== undefined && typeof value === 'number') { + result += `
${param.seriesName}: ${value.toFixed(2)}
` + } + }) + + return result + } + }, + dataZoom: [ + { + type: 'slider', + xAxisIndex: 0, + start: 40, + end: 100, + show: true, + bottom: 10, + height: 20, + borderColor: '#fff', + fillerColor: 'rgba(255, 255, 255, 0.2)', + handleStyle: { + color: '#fff', + borderColor: '#fff' + }, + textStyle: { + color: '#fff' + } + }, + { + type: 'inside', + xAxisIndex: 0, + start: 70, + end: 100, + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: false + } + ], xAxis: { type: "category", data: mixData.map((item) => item.date), @@ -420,7 +521,7 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { left: "7%", right: "10", top: '10', - bottom: "0", + bottom: "60", containLabel: true, width: '85%', height: 'auto', diff --git a/src/views/components/emotionDecod.vue b/src/views/components/emotionDecod.vue index 5204ae0..6bf2dd6 100644 --- a/src/views/components/emotionDecod.vue +++ b/src/views/components/emotionDecod.vue @@ -58,8 +58,9 @@ function initQXNLZHEcharts(kline, qxnlzhqData) { const categoryData = []; let value = []; for (let i = 0; i < a.length; i++) { - categoryData.push(a[i].splice(0, 1)[0]); - value.push(a[i]); + // 使用非破坏性的方法,避免修改原数组 + categoryData.push(a[i][0]); + value.push(a[i].slice(1)); // 使用 slice 而不是 splice } return { categoryData, value }; }; @@ -380,9 +381,9 @@ onBeforeUnmount(() => { } #qxjmqEcharts { - width: 100%; + width: 130%; height: 800px; - margin-left: 1rem; + margin-left: -15%; top: 5rem; } @@ -391,13 +392,13 @@ onBeforeUnmount(() => { #qxjmqEcharts { width: 100%; height: 400px; - margin-left: 1rem; + margin-left: -6%; top: 5rem; } .qxjmqbox { height: auto; - width: 110%; + width: 130%; margin-top: -5rem; margin-left: -1rem; } diff --git a/src/views/components/emotionalBottomRadar.vue b/src/views/components/emotionalBottomRadar.vue index 83fdd1a..a056922 100644 --- a/src/views/components/emotionalBottomRadar.vue +++ b/src/views/components/emotionalBottomRadar.vue @@ -18,7 +18,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) { bottomRadarChart = echarts.init(bottomRadarChartDom) // 日期-作为x轴 - let dateArray = KlineData.map(subArray => subArray[0]) + let dateArray = barAndLineData.map(subArray => subArray[0]) // k线,取前四个即可 let kLineDataArray = KlineData.map(subArray => subArray.slice(1, 5)) // 红线,取第二个值 @@ -103,33 +103,84 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) { let option = { // backgroundColor: '#000046', // 设置整个图表的背景色 tooltip: { - show: false, // 不展示tip - // 当前echart版本十字准星独立渲染了; 4.x+才有showAxisPointer + show: true, // 启用tooltip显示 trigger: 'axis', + triggerOn: 'mousemove', + confine: true, axisPointer: { type: 'cross', crossStyle: { - color: '#999' + color: '#fff', + width: 1, + type: 'solid' + }, + lineStyle: { + color: '#fff', + width: 1, + type: 'solid' + }, + label: { + backgroundColor: 'rgba(0, 0, 0, 0.8)', + color: '#fff', + borderColor: '#fff', + borderWidth: 1 } }, - backgroundColor: 'rgba(255, 255, 255, 0.8)', - borderColor: '#ccc', + backgroundColor: 'rgba(0, 0, 0, 0.8)', + borderColor: '#fff', borderWidth: 1, padding: 10, textStyle: { - color: '#333' + color: '#fff', + fontSize: 12 }, formatter: function (params) { - let result = `
${params[0].name}
` + if (!params || params.length === 0) return '' + + // 检查是否有第二个或第三个网格的数据,如果有则不显示tooltip + let hasSecondOrThirdGrid = params.some(param => { + return (param.seriesName === '红线' && param.axisIndex === 1) || + (param.axisIndex === 2) || + (param.seriesName !== 'K线' && param.seriesName !== '基础base') + }) + + // 如果鼠标悬浮在第二个或第三个网格上,不显示tooltip + if (hasSecondOrThirdGrid && !params.some(param => param.seriesType === 'candlestick')) { + return '' + } + + let result = `
${params[0].name}
` params.forEach(param => { let value = param.value let color = param.color if (param.seriesType === 'candlestick') { - result += `
${param.seriesName}: 开 ${value[0]}, 收 ${value[1]}, 低 ${value[2]}, 高 ${value[3]}
` - } else { - result += `
${param.seriesName}: ${value}
` + // ECharts candlestick的value格式:[开盘, 收盘, 最低, 最高] + // 但param.value可能包含额外信息,需要从原始数据中获取 + let dataIndex = param.dataIndex + let candlestickData = kLineDataArray[dataIndex] + + let openPrice = candlestickData[0] // 开盘价 + let closePrice = candlestickData[1] // 收盘价 + let lowPrice = candlestickData[2] // 最低价 + let highPrice = candlestickData[3] // 最高价 + let priceChange = closePrice - openPrice + let changePercent = ((priceChange / openPrice) * 100).toFixed(2) + let changeColor = priceChange >= 0 ? '#14b143' : '#ef232a' // 互换颜色:上涨绿色,下跌红色 + + result += `
` + result += `
${param.seriesName}
` + result += `
开盘: ${openPrice.toFixed(2)}
` + result += `
收盘: ${closePrice.toFixed(2)}
` + result += `
最低: ${lowPrice.toFixed(2)}
` + result += `
最高: ${highPrice.toFixed(2)}
` + result += `
涨跌: ${priceChange >= 0 ? '+' : ''}${priceChange.toFixed(2)} (${changePercent}%)
` + result += `
` + } else if (param.seriesName === '红线') { + result += `
${param.seriesName}: ${value}
` + } else if (param.seriesName !== '基础base' && value > 0) { + result += `
${param.seriesName}: ${value}
` } }) @@ -372,37 +423,38 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) { dataZoom: [ { type: 'slider', - xAxisIndex: [0, 2], - // start: 80, - // end: 100, - show: false - }, - { - type: 'slider', - xAxisIndex: [0, 2], - // start: 80, - // end: 100, - show: false - }, - { - type: 'slider', - xAxisIndex: [0, 2], - // 一次性全部 or 后20% - // start: 80, - // end: 100, - show: false, // 先不显示 + xAxisIndex: [0, 1, 2], + start: 70, + end: 100, + show: true, + bottom: 10, + height: 20, borderColor: '#CFD6E3', + fillerColor: 'rgba(135, 175, 274, 0.2)', + handleStyle: { + color: '#CFD6E3' + }, + textStyle: { + color: '#fff' + }, dataBackground: { - // 线 lineStyle: { color: '#CFD6E3' }, - // 阴影 areaStyle: { color: 'rgba(241,243,247,0.5)' } } }, + { + type: 'inside', + xAxisIndex: [0, 1, 2], + start: 70, + end: 100, + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: false + } ], series: [ { @@ -412,18 +464,18 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) { xAxisIndex: 0, yAxisIndex: 0, itemStyle: { - color: '#ef232a', // 上涨颜色 (红) - color0: '#14b143', // 下跌颜色 (绿) - borderColor: '#ef232a', - borderColor0: '#14b143', + color: '#14b143', // 上涨颜色 (绿) + color0: '#ef232a', // 下跌颜色 (红) + borderColor: '#14b143', + borderColor0: '#ef232a', normal: { - color: '#ef232a', // 上涨颜色 (红) - color0: '#14b143', // 下跌颜色 (绿) - borderColor: '#ef232a', - borderColor0: '#14b143', + color: '#14b143', // 上涨颜色 (绿) + color0: '#ef232a', // 下跌颜色 (红) + borderColor: '#14b143', + borderColor0: '#ef232a', opacity: function (params) { - // 收盘价 > 开盘价时为阳线,设置边框不透明、填充透明 - return params.data[2] > params.data[1] ? 0 : 1 + // K线数据格式:[开,收,低,高] 收盘价 > 开盘价时为阳线,设置边框不透明、填充透明 + return params.data[1] > params.data[0] ? 0 : 1 } } } @@ -472,7 +524,7 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) { data: transparentFillingDataArray, }, { - name: '黄色块', + name: '黄色', type: 'bar', stack: 'total', // barGap: '-100%', // 重叠 diff --git a/src/views/components/marketTemperature.vue b/src/views/components/marketTemperature.vue index 9668cfb..f200ef0 100644 --- a/src/views/components/marketTemperature.vue +++ b/src/views/components/marketTemperature.vue @@ -179,6 +179,21 @@ function initChart(raw, klineDataRawValue, WDRLValue) { return [open, close, low, high] }) + // 计算K线数据的最小值和最大值 + let minPrice = Infinity + let maxPrice = -Infinity + klineDataRawValue.forEach(item => { + const low = item[3] + const high = item[4] + minPrice = Math.min(minPrice, low) + maxPrice = Math.max(maxPrice, high) + }) + + // 将最小值向下取整到10的倍数 + const yAxisMin = Math.floor(minPrice / 10) * 10 + // 将最大值向上取整到10的倍数,并增加一些余量 + const yAxisMax = Math.ceil(maxPrice / 10) * 10 + 10 + // 温度日历 WDRL.value = WDRLValue klineDataRaw.value = klineDataRawValue @@ -224,7 +239,7 @@ function initChart(raw, klineDataRawValue, WDRLValue) { return '' } }, - legend: { data: ['K线', '市场温度', '股票温度'], textStyle: { color: 'white' } }, + legend: { data: ['K线', '市场温度', '股票温度'], textStyle: { color: 'white',fontSize: 18 }}, xAxis: { type: 'category', data: dateLabels, @@ -251,6 +266,8 @@ function initChart(raw, klineDataRawValue, WDRLValue) { } }, yAxis: [{ + min: yAxisMin, + max: yAxisMax, axisLine: { lineStyle: { color: '#00FF7F' } }, axisLabel: { color: '#FFFFFF', @@ -320,10 +337,10 @@ function initChart(raw, klineDataRawValue, WDRLValue) { data: klineData, itemStyle: { normal: { - color: '#FF0000', // 阳线红色 - color0: '#00FF00', // 阴线绿色 - borderColor: '#FF0000', // 阳线边框红色 - borderColor0: '#00FF00' // 阴线边框绿色 + color: '#00FF00', // 阳线红色 + color0: '#FF0000', // 阴线绿色 + borderColor: '#00FF00', // 阳线边框红色 + borderColor0: '#FF0000' // 阴线边框绿色 } } }, @@ -439,7 +456,7 @@ defineExpose({ initChart }) .KlineClass { width: 100%; - height: 400px; + height: 600px; } .market-temperature { diff --git a/src/views/homePage.vue b/src/views/homePage.vue index 6e2f4b9..e8e034c 100644 --- a/src/views/homePage.vue +++ b/src/views/homePage.vue @@ -820,7 +820,7 @@ body { .homepage-right-group .count-badge .count-number { position: absolute; top: 6px; - right: 29px; + right: 20px; color: #573dfc; font-size: 12px; font-weight: bold;