update ui

This commit is contained in:
2025-11-13 16:51:35 +08:00
parent 9d6c0ac55c
commit 58d1e6f2ad

View File

@@ -19,6 +19,8 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { TrendingUp, Activity, Globe, Zap } from 'lucide-react'; import { TrendingUp, Activity, Globe, Zap } from 'lucide-react';
import ReactECharts from 'echarts-for-react'; import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import 'echarts-wordcloud'; // 导入词云插件
import { logger } from '../../../utils/logger'; import { logger } from '../../../utils/logger';
/** /**
@@ -130,7 +132,8 @@ const MiniIndexChart = ({ indexCode, indexName }) => {
item.close, item.close,
item.low, item.low,
item.high item.high
]) ]),
rawData: recentData // 保存原始数据用于 tooltip
}); });
} }
@@ -223,6 +226,59 @@ const MiniIndexChart = ({ indexCode, indexName }) => {
bottom: 20, bottom: 20,
containLabel: false containLabel: false
}, },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
lineStyle: {
color: 'rgba(255, 215, 0, 0.5)',
width: 1,
type: 'dashed'
}
},
backgroundColor: 'rgba(20, 20, 20, 0.95)',
borderColor: '#FFD700',
borderWidth: 1,
textStyle: {
color: '#fff',
fontSize: 11,
fontFamily: 'monospace'
},
padding: [8, 12],
formatter: function (params) {
const dataIndex = params[0].dataIndex;
const rawDataItem = chartData.rawData[dataIndex];
if (!rawDataItem) return '';
const open = rawDataItem.open;
const high = rawDataItem.high;
const low = rawDataItem.low;
const close = rawDataItem.close;
const prevClose = rawDataItem.prev_close || open;
const change = close - prevClose;
const changePct = prevClose ? ((change / prevClose) * 100).toFixed(2) : '0.00';
const isUp = close >= prevClose;
// Bloomberg 风格格式化
const changeColor = isUp ? '#00da3c' : '#ec0000';
const changeSign = isUp ? '+' : '';
return `
<div style="font-weight: bold; border-bottom: 1px solid #FFD700; padding-bottom: 4px; margin-bottom: 6px;">
${rawDataItem.time}
</div>
<div style="display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; line-height: 1.6;">
<span style="color: #aaa;">开盘</span><span style="font-weight: bold;">${open.toFixed(2)}</span>
<span style="color: #aaa;">最高</span><span style="font-weight: bold; color: #00da3c;">${high.toFixed(2)}</span>
<span style="color: #aaa;">最低</span><span style="font-weight: bold; color: #ec0000;">${low.toFixed(2)}</span>
<span style="color: #aaa;">收盘</span><span style="font-weight: bold;">${close.toFixed(2)}</span>
<span style="color: #aaa;">涨跌</span><span style="font-weight: bold; color: ${changeColor};">${changeSign}${change.toFixed(2)}</span>
<span style="color: #aaa;">涨跌幅</span><span style="font-weight: bold; color: ${changeColor};">${changeSign}${changePct}%</span>
</div>
`;
}
},
xAxis: { xAxis: {
type: 'category', type: 'category',
data: chartData.dates, data: chartData.dates,
@@ -324,16 +380,35 @@ const ConceptWordCloud = () => {
}, []); }, []);
const chartOption = useMemo(() => { const chartOption = useMemo(() => {
if (concepts.length === 0) return {}; if (concepts.length === 0) {
logger.warn('ConceptWordCloud', 'No concepts data available');
return {};
}
logger.debug('ConceptWordCloud', 'Rendering word cloud with concepts', {
count: concepts.length,
sample: concepts.slice(0, 3)
});
return { return {
backgroundColor: chartBg, backgroundColor: chartBg,
tooltip: { tooltip: {
show: true, show: true,
backgroundColor: 'rgba(20, 20, 20, 0.95)',
borderColor: '#FFD700',
borderWidth: 1,
textStyle: {
color: '#fff',
fontSize: 12
},
formatter: (params) => { formatter: (params) => {
const changePct = params.data.change_pct; const changePct = params.data.change_pct;
const sign = changePct > 0 ? '+' : ''; const sign = changePct > 0 ? '+' : '';
return `${params.name}<br/>涨跌: ${sign}${changePct.toFixed(2)}%`; const color = changePct > 0 ? '#ec0000' : '#00da3c';
return `
<div style="font-weight: bold; margin-bottom: 4px;">${params.name}</div>
<div style="color: ${color}; font-weight: bold;">涨跌幅: ${sign}${changePct.toFixed(2)}%</div>
`;
} }
}, },
series: [{ series: [{
@@ -345,33 +420,35 @@ const ConceptWordCloud = () => {
height: '100%', height: '100%',
right: null, right: null,
bottom: null, bottom: null,
sizeRange: [12, 40], sizeRange: [14, 42],
rotationRange: [-45, 45], rotationRange: [-30, 30],
rotationStep: 45, rotationStep: 15,
gridSize: 8, gridSize: 10,
drawOutOfBound: false, drawOutOfBound: false,
layoutAnimation: true, layoutAnimation: true,
textStyle: { textStyle: {
fontFamily: 'sans-serif', fontFamily: 'sans-serif',
fontWeight: 'bold', fontWeight: 'bold',
color: function (params) { color: function (params) {
// 根据涨跌幅设置颜色 // 根据涨跌幅设置颜色(中国市场惯例:涨红跌绿)
const changePct = params.data.change_pct; const changePct = params.data.change_pct;
if (changePct > 5) return '#ff4d4f'; // 大涨:红色 if (changePct > 5) return '#ff1744'; // 大涨:红色
if (changePct > 3) return '#ff7875'; // 中涨: if (changePct > 3) return '#ff4d4f'; // 中涨:红
if (changePct > 0) return '#ffa940'; // 小涨:橙色 if (changePct > 1) return '#ff7875'; // 小涨:浅红
if (changePct > 0) return '#ffa940'; // 微涨:橙色
if (changePct === 0) return '#FFD700'; // 平盘:金色 if (changePct === 0) return '#FFD700'; // 平盘:金色
if (changePct > -3) return '#95de64'; // 跌:浅绿 if (changePct > -1) return '#95de64'; // 跌:浅绿
if (changePct > -5) return '#52c41a'; // 跌:绿色 if (changePct > -3) return '#52c41a'; // 跌:绿色
return '#13c2c2'; // 跌:青色 if (changePct > -5) return '#00c853'; // 跌:深绿
return '#00796b'; // 大跌:墨绿
} }
}, },
emphasis: { emphasis: {
focus: 'self', focus: 'self',
textStyle: { textStyle: {
shadowBlur: 10, shadowBlur: 12,
shadowColor: '#FFD700', shadowColor: '#FFD700',
fontSize: 20 fontSize: 24
} }
}, },
data: concepts data: concepts
@@ -387,11 +464,24 @@ const ConceptWordCloud = () => {
); );
} }
if (concepts.length === 0) {
return (
<Center h="200px">
<Text fontSize="sm" color="whiteAlpha.600">
暂无热门概念数据
</Text>
</Center>
);
}
return ( return (
<ReactECharts <ReactECharts
echarts={echarts}
option={chartOption} option={chartOption}
style={{ height: '200px', width: '100%' }} style={{ height: '200px', width: '100%' }}
opts={{ renderer: 'canvas' }} opts={{ renderer: 'canvas' }}
notMerge={true}
lazyUpdate={true}
/> />
); );
}; };