diff --git a/src/views/Community/components/HeroPanel.js b/src/views/Community/components/HeroPanel.js
index b9b7345e..b144f0a1 100644
--- a/src/views/Community/components/HeroPanel.js
+++ b/src/views/Community/components/HeroPanel.js
@@ -96,30 +96,39 @@ const isInTradingTime = () => {
};
/**
- * 紧凑型K线指数卡片
+ * 精美K线指数卡片 - 类似 KLineChartModal 风格
*/
const CompactIndexCard = ({ indexCode, indexName }) => {
const [chartData, setChartData] = useState(null);
const [loading, setLoading] = useState(true);
const [latestData, setLatestData] = useState(null);
- const upColor = '#ec0000';
- const downColor = '#00da3c';
+ const upColor = '#ef5350'; // 涨 - 红色
+ const downColor = '#26a69a'; // 跌 - 绿色
const loadData = useCallback(async () => {
const data = await fetchIndexKline(indexCode);
if (data?.data?.length > 0) {
const latest = data.data[data.data.length - 1];
- const prevClose = latest.prev_close || latest.close;
+ const prevClose = latest.prev_close || data.data[data.data.length - 2]?.close || latest.open;
+ const changeAmount = latest.close - prevClose;
+ const changePct = prevClose ? ((changeAmount / prevClose) * 100) : 0;
+
setLatestData({
close: latest.close,
- change: prevClose ? (((latest.close - prevClose) / prevClose) * 100).toFixed(2) : '0.00',
- isPositive: latest.close >= prevClose
+ open: latest.open,
+ high: latest.high,
+ low: latest.low,
+ changeAmount: changeAmount,
+ changePct: changePct,
+ isPositive: changeAmount >= 0
});
- const recentData = data.data.slice(-40);
+
+ const recentData = data.data.slice(-60); // 增加到60天
setChartData({
dates: recentData.map(item => item.time),
klineData: recentData.map(item => [item.open, item.close, item.low, item.high]),
+ volumes: recentData.map(item => item.volume || 0),
rawData: recentData
});
}
@@ -134,58 +143,204 @@ const CompactIndexCard = ({ indexCode, indexName }) => {
if (!chartData) return {};
return {
backgroundColor: 'transparent',
- grid: { left: 5, right: 5, top: 5, bottom: 5, containLabel: false },
+ grid: [
+ { left: 0, right: 0, top: 8, bottom: 28, containLabel: false },
+ { left: 0, right: 0, top: '75%', bottom: 4, 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',
+ axisPointer: {
+ type: 'cross',
+ crossStyle: { color: 'rgba(255, 215, 0, 0.6)', width: 1 },
+ lineStyle: { color: 'rgba(255, 215, 0, 0.4)', width: 1, type: 'dashed' }
+ },
+ backgroundColor: 'rgba(15, 15, 25, 0.98)',
+ borderColor: 'rgba(255, 215, 0, 0.5)',
borderWidth: 1,
- textStyle: { color: '#fff', fontSize: 10, fontFamily: 'monospace' },
- padding: [6, 10],
+ borderRadius: 8,
+ padding: [12, 16],
+ textStyle: { color: '#e0e0e0', fontSize: 12 },
+ extraCssText: 'box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);',
formatter: (params) => {
- const idx = params[0].dataIndex;
+ const idx = params[0]?.dataIndex;
+ if (idx === undefined) return '';
+
const raw = chartData.rawData[idx];
if (!raw) return '';
- const prevClose = raw.prev_close || raw.open;
- const changePct = prevClose ? (((raw.close - prevClose) / prevClose) * 100).toFixed(2) : '0.00';
- const isUp = raw.close >= prevClose;
- const color = isUp ? '#ec0000' : '#00da3c';
- return `
${raw.time}
收盘: ${raw.close.toFixed(2)}
${isUp ? '+' : ''}${changePct}%
`;
+
+ // 计算涨跌
+ const prevClose = raw.prev_close || (idx > 0 ? chartData.rawData[idx - 1]?.close : raw.open) || raw.open;
+ const changeAmount = raw.close - prevClose;
+ const changePct = prevClose ? ((changeAmount / prevClose) * 100) : 0;
+ const isUp = changeAmount >= 0;
+ const color = isUp ? '#ef5350' : '#26a69a';
+ const sign = isUp ? '+' : '';
+
+ return `
+
+
+ 📅 ${raw.time}
+
+
+ 开盘
+ ${raw.open.toFixed(2)}
+ 收盘
+ ${raw.close.toFixed(2)}
+ 最高
+ ${raw.high.toFixed(2)}
+ 最低
+ ${raw.low.toFixed(2)}
+
+
+ 涨跌幅
+
+ ${sign}${changeAmount.toFixed(2)} (${sign}${changePct.toFixed(2)}%)
+
+
+
+ `;
}
},
- xAxis: { type: 'category', data: chartData.dates, show: false },
- yAxis: { type: 'value', show: false, scale: true },
- series: [{
- type: 'candlestick',
- data: chartData.klineData,
- itemStyle: { color: upColor, color0: downColor, borderColor: upColor, borderColor0: downColor },
- barWidth: '70%'
- }]
+ xAxis: [
+ {
+ type: 'category',
+ data: chartData.dates,
+ gridIndex: 0,
+ show: false,
+ boundaryGap: true
+ },
+ {
+ type: 'category',
+ data: chartData.dates,
+ gridIndex: 1,
+ show: false,
+ boundaryGap: true
+ }
+ ],
+ yAxis: [
+ {
+ type: 'value',
+ gridIndex: 0,
+ show: false,
+ scale: true
+ },
+ {
+ type: 'value',
+ gridIndex: 1,
+ show: false,
+ scale: true
+ }
+ ],
+ dataZoom: [{
+ type: 'inside',
+ xAxisIndex: [0, 1],
+ start: 50,
+ end: 100,
+ zoomOnMouseWheel: true,
+ moveOnMouseMove: true
+ }],
+ series: [
+ {
+ name: 'K线',
+ type: 'candlestick',
+ data: chartData.klineData,
+ xAxisIndex: 0,
+ yAxisIndex: 0,
+ itemStyle: {
+ color: upColor,
+ color0: downColor,
+ borderColor: upColor,
+ borderColor0: downColor,
+ borderWidth: 1
+ },
+ barWidth: '65%'
+ },
+ {
+ name: '成交量',
+ type: 'bar',
+ data: chartData.volumes,
+ xAxisIndex: 1,
+ yAxisIndex: 1,
+ itemStyle: {
+ color: (params) => {
+ const idx = params.dataIndex;
+ const raw = chartData.rawData[idx];
+ return raw && raw.close >= raw.open ? 'rgba(239,83,80,0.5)' : 'rgba(38,166,154,0.5)';
+ }
+ },
+ barWidth: '65%'
+ }
+ ]
};
}, [chartData, upColor, downColor]);
- if (loading) return ;
+ if (loading) {
+ return (
+
+
+
+ 加载{indexName}...
+
+
+ );
+ }
return (
-
- {/* 左侧数据 */}
-
- {indexName}
-
- {latestData?.close.toFixed(2)}
-
+
+ {/* 顶部:指数名称和数据 */}
+
+
+
+
+ {indexName}
+
+
+
+
+ {latestData?.close?.toFixed(2)}
+
+
+
+ {latestData?.isPositive ? '▲' : '▼'} {latestData?.isPositive ? '+' : ''}{latestData?.changePct?.toFixed(2)}%
+
+
+
+
+
+ {/* K线图区域 */}
+
+
+ {/* 底部提示 */}
- {latestData?.isPositive ? '▲' : '▼'} {latestData?.isPositive ? '+' : ''}{latestData?.change}%
+ 滚轮缩放 · 拖动查看
-
- {/* 右侧K线图 */}
-
-
);
@@ -377,7 +532,7 @@ const FlowingConcepts = () => {
};
/**
- * 极简提示标签 - 悬停显示详情
+ * 详细使用说明提示框
*/
const InfoTooltip = () => {
const [isOpen, setIsOpen] = useState(false);
@@ -414,16 +569,16 @@ const InfoTooltip = () => {
top="calc(100% + 8px)"
left="0"
zIndex={1000}
- minW="320px"
- p={4}
+ w="380px"
+ p={5}
bg="rgba(10,10,20,0.98)"
- borderRadius="lg"
+ borderRadius="xl"
border="1px solid rgba(255,215,0,0.3)"
- boxShadow="0 10px 40px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,215,0,0.1)"
+ boxShadow="0 15px 50px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,215,0,0.1), inset 0 1px 0 rgba(255,255,255,0.05)"
opacity={isOpen ? 1 : 0}
visibility={isOpen ? 'visible' : 'hidden'}
transform={isOpen ? 'translateY(0)' : 'translateY(-10px)'}
- transition="all 0.2s ease"
+ transition="all 0.25s ease"
onMouseEnter={() => setIsOpen(true)}
onMouseLeave={() => setIsOpen(false)}
>
@@ -440,56 +595,118 @@ const InfoTooltip = () => {
transform="rotate(45deg)"
/>
-
- {/* SABC说明 */}
-
- SABC
-
- 基于事件影响力评级,非收益预测
-
-
+
+ {/* 标题 */}
+
+ 📖 事件中心使用指南
+
- {/* 涨跌幅说明 */}
-
- 涨跌幅
-
- 新闻发布时股价 → 当前价格的变化
+ {/* 事件级别说明 */}
+
+
+ 🏷️ 事件重要性等级 (SABC)
-
-
- {/* 延迟提醒 */}
-
-
-
-
-
- 数据延迟 2-3分钟
- ,切勿追高
-
-
+
+
+
+ S级
+
+ 重大事件 - 可能引发板块涨停潮
+
+
+
+ A级
+
+ 重要事件 - 龙头股可能涨停
+
+
+
+ B级
+
+ 一般事件 - 相关股票可能异动
+
+
+
+ C级
+
+ 普通事件 - 仅供参考
+
+
+
{/* 分隔线 */}
-
+
- {/* 盘前新闻 */}
-
-
-
- 关注盘前新闻
- (收盘后至次日开盘前的消息)
+ {/* 涨跌幅说明 */}
+
+
+ 📊 涨跌幅计算方式
-
+
+
+ • 相关股涨跌:新闻发布时 → 当前价格的变化
+
+
+ • 红色 表示上涨,绿色 表示下跌
+
+
+ • K线图悬停可查看:开盘、收盘、最高、最低、涨跌幅
+
+
+
- {/* 利好利空 */}
-
-
-
- 事件含
- 利好/
- 利空
- ,需自行判断
+ {/* 分隔线 */}
+
+
+ {/* 重要提醒 */}
+
+
+ ⚠️ 重要提醒
-
+
+
+
+
+ 数据延迟 2-3分钟,切勿追高
+
+
+
+
+
+ 关注 盘前新闻(收盘后至次日开盘前发布的消息)
+
+
+
+
+
+ 事件可能含 利好 或 利空,需自行分析判断
+
+
+
+
+
+ {/* 操作提示 */}
+
+
+ 💡 操作提示
+
+
+
+ • 点击事件卡片查看详情和相关股票
+
+
+ • 点击热门概念标签跳转概念详情页
+
+
+ • K线图支持滚轮缩放和拖动查看
+
+
+
@@ -596,14 +813,15 @@ const HeroPanel = () => {
@@ -613,14 +831,15 @@ const HeroPanel = () => {