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';