From 145b6575d8e56a8789c47c60f27f7c0ac1117aaa Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Tue, 23 Dec 2025 15:28:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(MarketDashboard):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=B8=82=E5=9C=BA=E6=A6=82=E5=86=B5=E5=8D=A1=E7=89=87=EF=BC=88?= =?UTF-8?q?=E4=B8=8A=E8=AF=81/=E6=B7=B1=E8=AF=81/=E6=80=BB=E5=B8=82?= =?UTF-8?q?=E5=80=BC/=E6=88=90=E4=BA=A4=E9=A2=9D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增组件: - MarketSummaryCard: 紧凑型 2x2 网格布局 - 上证指数:价格、涨跌额、涨跌幅 - 深证指数:价格、涨跌额、涨跌幅 - 总市值:万亿级格式化显示 - 成交额:万亿级格式化显示 布局更新: - MarketOverview: 从 3 列扩展为 4 列 - 市场概况卡片位于最左侧 Mock API: - /api/market/summary: 返回实时市场概况数据 - 数据基于时间产生小波动,模拟真实行情 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/mocks/handlers/market.js | 50 +++++- .../components/MarketOverview.js | 10 +- .../components/atoms/MarketSummaryCard.js | 160 ++++++++++++++++++ .../MarketDashboard/components/atoms/index.js | 3 + 4 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 src/views/Profile/components/MarketDashboard/components/atoms/MarketSummaryCard.js diff --git a/src/mocks/handlers/market.js b/src/mocks/handlers/market.js index 4e15a72d..1e0b8659 100644 --- a/src/mocks/handlers/market.js +++ b/src/mocks/handlers/market.js @@ -512,7 +512,55 @@ export const marketHandlers = [ }); }), - // 12. 市场统计数据(个股中心页面使用) + // 12. 市场概况数据(投资仪表盘使用)- 上证/深证/总市值/成交额 + http.get('/api/market/summary', async () => { + await delay(150); + + // 生成实时数据(基于当前时间产生小波动) + const now = new Date(); + const seed = now.getHours() * 60 + now.getMinutes(); + + // 上证指数(基准 3400) + const shBasePrice = 3400; + const shChange = parseFloat(((Math.sin(seed / 30) + Math.random() - 0.5) * 2).toFixed(2)); + const shPrice = parseFloat((shBasePrice * (1 + shChange / 100)).toFixed(2)); + const shChangeAmount = parseFloat((shPrice - shBasePrice).toFixed(2)); + + // 深证指数(基准 10800) + const szBasePrice = 10800; + const szChange = parseFloat(((Math.sin(seed / 25) + Math.random() - 0.5) * 2.5).toFixed(2)); + const szPrice = parseFloat((szBasePrice * (1 + szChange / 100)).toFixed(2)); + const szChangeAmount = parseFloat((szPrice - szBasePrice).toFixed(2)); + + // 总市值(约 100-110 万亿波动) + const totalMarketCap = parseFloat((105 + (Math.sin(seed / 60) * 5)).toFixed(1)) * 1000000000000; + + // 成交额(约 0.8-1.5 万亿波动) + const turnover = parseFloat((1.0 + (Math.random() * 0.5 - 0.2)).toFixed(2)) * 1000000000000; + + console.log('[Mock Market] 获取市场概况数据'); + + return HttpResponse.json({ + success: true, + data: { + shanghai: { + value: shPrice, + change: shChange, + changeAmount: shChangeAmount, + }, + shenzhen: { + value: szPrice, + change: szChange, + changeAmount: szChangeAmount, + }, + totalMarketCap, + turnover, + updateTime: now.toISOString(), + }, + }); + }), + + // 13. 市场统计数据(个股中心页面使用) http.get('/api/market/statistics', async ({ request }) => { await delay(200); const url = new URL(request.url); diff --git a/src/views/Profile/components/MarketDashboard/components/MarketOverview.js b/src/views/Profile/components/MarketDashboard/components/MarketOverview.js index 0669e9b0..34b36a9b 100644 --- a/src/views/Profile/components/MarketDashboard/components/MarketOverview.js +++ b/src/views/Profile/components/MarketDashboard/components/MarketOverview.js @@ -1,20 +1,24 @@ // 市场概况组件 - 顶部横条(与事件中心头部保持一致) -// 布局:上证指数 | 深证成指 | 创业板指+涨跌分布 +// 布局:市场概况 | 上证指数 | 深证成指 | 创业板指+涨跌分布 import React from 'react'; import { Box, SimpleGrid } from '@chakra-ui/react'; import { IndexKLineCard, GemIndexCard, + MarketSummaryCard, } from './atoms'; const MarketOverview = ({ marketStats = {} }) => { return ( - {/* 3列网格布局:上证指数 | 深证成指 | 创业板指+涨跌 */} + {/* 4列网格布局:市场概况 | 上证指数 | 深证成指 | 创业板指+涨跌 */} + {/* 市场概况 - 上证/深证/总市值/成交额 */} + + {/* 上证指数 - K线卡片 */} { + if (!num && num !== 0) return '--'; + const trillion = 1000000000000; // 万亿 + const billion = 100000000; // 亿 + + if (num >= trillion) { + return `${(num / trillion).toFixed(1)}万亿`; + } else if (num >= billion) { + return `${(num / billion).toFixed(1)}亿`; + } + return num.toLocaleString(); +}; + +/** + * 单个指数/统计项 + */ +const SummaryItem = ({ label, value, change, changeAmount, subValue, isIndex = true }) => { + const isUp = change > 0; + const isFlat = change === 0; + const changeColor = isFlat + ? 'rgba(255, 255, 255, 0.6)' + : isUp ? THEME.status.up : THEME.status.down; + + return ( + + {/* 标签 */} + + {label} + + + {/* 主数值 */} + + {typeof value === 'number' ? value.toFixed(2) : value} + + + {/* 涨跌信息(仅指数显示) */} + {isIndex && change !== undefined ? ( + + {changeAmount !== undefined && ( + + {isUp ? '+' : ''}{typeof changeAmount === 'number' ? changeAmount.toFixed(2) : changeAmount} + + )} + {isUp ? '+' : ''}{change.toFixed(2)}% + + ) : ( + // 非指数项显示副标签 + + {subValue || label} + + )} + + ); +}; + +/** + * 市场概况卡片 + */ +const MarketSummaryCard = () => { + const [marketData, setMarketData] = useState({ + shanghai: { value: 3391.88, change: 0.52, changeAmount: 17.55 }, + shenzhen: { value: 10723.49, change: 0.68, changeAmount: 72.38 }, + totalMarketCap: 105.6 * 1000000000000, // 105.6万亿 + turnover: 1.0 * 1000000000000, // 1.0万亿 + }); + + // 获取实时数据 + useEffect(() => { + const fetchMarketData = async () => { + try { + const base = getApiBase(); + const response = await fetch(`${base}/api/market/summary`, { + credentials: 'include', + }); + if (response.ok) { + const data = await response.json(); + if (data.success && data.data) { + setMarketData(prev => ({ + ...prev, + ...data.data, + })); + } + } + } catch (error) { + // 使用默认数据 + console.debug('Using default market data'); + } + }; + + fetchMarketData(); + // 每分钟更新一次 + const interval = setInterval(fetchMarketData, 60000); + return () => clearInterval(interval); + }, []); + + return ( + + + {/* 上证 */} + + + {/* 深证 */} + + + {/* 总市值 */} + + + {/* 成交额 */} + + + + ); +}; + +export default MarketSummaryCard; diff --git a/src/views/Profile/components/MarketDashboard/components/atoms/index.js b/src/views/Profile/components/MarketDashboard/components/atoms/index.js index b5879973..17acab67 100644 --- a/src/views/Profile/components/MarketDashboard/components/atoms/index.js +++ b/src/views/Profile/components/MarketDashboard/components/atoms/index.js @@ -12,3 +12,6 @@ export { default as HotSectorsRanking } from './HotSectorsRanking'; export { default as IndexKLineCard } from './IndexKLineCard'; export { default as RiseFallProgressBar } from './RiseFallProgressBar'; export { default as GemIndexCard } from './GemIndexCard'; + +// 市场概况卡片(上证/深证/总市值/成交额) +export { default as MarketSummaryCard } from './MarketSummaryCard';