From cdca8890831f9d1b8200d8e536a081b29e607324 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Wed, 3 Dec 2025 17:28:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8E=BB=E9=99=A4=E4=B8=AA=E8=82=A1?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E5=8A=A8=E7=94=BB=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?mock=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mocks/handlers/market.js | 193 +++++++++++++++++++++++++++++++ src/views/StockOverview/index.js | 20 +--- 2 files changed, 195 insertions(+), 18 deletions(-) diff --git a/src/mocks/handlers/market.js b/src/mocks/handlers/market.js index e9515767..28757c99 100644 --- a/src/mocks/handlers/market.js +++ b/src/mocks/handlers/market.js @@ -71,4 +71,197 @@ export const marketHandlers = [ const data = generateMarketData(stockCode); return HttpResponse.json(data.latestMinuteData); }), + + // 9. 热门概念数据(个股中心页面使用) + http.get('/api/concepts/daily-top', async ({ request }) => { + await delay(300); + const url = new URL(request.url); + const limit = parseInt(url.searchParams.get('limit') || '6'); + const date = url.searchParams.get('date'); + + // 获取当前日期或指定日期 + const tradeDate = date || new Date().toISOString().split('T')[0]; + + // 热门概念列表 + const conceptPool = [ + { name: '人工智能', desc: '人工智能是"技术突破+政策扶持"双轮驱动的硬科技主题。随着大模型技术的突破,AI应用场景不断拓展。' }, + { name: '新能源汽车', desc: '新能源汽车行业景气度持续向好,渗透率不断提升。政策支持力度大,产业链上下游企业均受益。' }, + { name: '半导体', desc: '国产半导体替代加速,自主可控需求强烈。政策和资金支持力度大,行业迎来黄金发展期。' }, + { name: '光伏', desc: '光伏装机量快速增长,成本持续下降,行业景气度维持高位。双碳目标下前景广阔。' }, + { name: '锂电池', desc: '锂电池技术进步,成本优势扩大,下游应用领域持续扩张。新能源汽车和储能需求旺盛。' }, + { name: '储能', desc: '储能市场爆发式增长,政策支持力度大,应用场景不断拓展。未来市场空间巨大。' }, + { name: '算力', desc: 'AI大模型推动算力需求爆发,数据中心、服务器、芯片等产业链受益明显。' }, + { name: '机器人', desc: '人形机器人产业化加速,特斯拉、小米等巨头入局,产业链迎来发展机遇。' }, + ]; + + // 股票池 + const stockPool = [ + { stock_code: '600519', stock_name: '贵州茅台' }, + { stock_code: '300750', stock_name: '宁德时代' }, + { stock_code: '601318', stock_name: '中国平安' }, + { stock_code: '002594', stock_name: '比亚迪' }, + { stock_code: '601012', stock_name: '隆基绿能' }, + { stock_code: '300274', stock_name: '阳光电源' }, + { stock_code: '688981', stock_name: '中芯国际' }, + { stock_code: '000725', stock_name: '京东方A' }, + ]; + + // 生成概念数据 + const concepts = []; + for (let i = 0; i < Math.min(limit, conceptPool.length); i++) { + const concept = conceptPool[i]; + const changePercent = parseFloat((Math.random() * 8 - 1).toFixed(2)); // -1% ~ 7% + const stockCount = Math.floor(Math.random() * 40) + 20; // 20-60只股票 + + // 随机选取3-4只相关股票 + const relatedStocks = []; + const stockIndices = new Set(); + while (stockIndices.size < Math.min(4, stockPool.length)) { + stockIndices.add(Math.floor(Math.random() * stockPool.length)); + } + stockIndices.forEach(idx => relatedStocks.push(stockPool[idx])); + + concepts.push({ + concept_id: `CONCEPT_${1001 + i}`, + concept_name: concept.name, + change_percent: changePercent, + stock_count: stockCount, + description: concept.desc, + stocks: relatedStocks + }); + } + + // 按涨跌幅降序排序 + concepts.sort((a, b) => b.change_percent - a.change_percent); + + console.log('[Mock Market] 获取热门概念:', { limit, date: tradeDate, count: concepts.length }); + + return HttpResponse.json({ + success: true, + data: concepts, + trade_date: tradeDate + }); + }), + + // 10. 市值热力图数据(个股中心页面使用) + http.get('/api/market/heatmap', async ({ request }) => { + await delay(400); + const url = new URL(request.url); + const limit = parseInt(url.searchParams.get('limit') || '500'); + const date = url.searchParams.get('date'); + + const tradeDate = date || new Date().toISOString().split('T')[0]; + + // 行业列表 + const industries = ['食品饮料', '银行', '医药生物', '电子', '计算机', '汽车', '电力设备', '机械设备', '化工', '房地产', '有色金属', '钢铁']; + const provinces = ['北京', '上海', '广东', '浙江', '江苏', '山东', '四川', '湖北', '福建', '安徽']; + + // 常见股票数据 + const majorStocks = [ + { code: '600519', name: '贵州茅台', cap: 1850, industry: '食品饮料', province: '贵州' }, + { code: '601318', name: '中国平安', cap: 920, industry: '保险', province: '广东' }, + { code: '600036', name: '招商银行', cap: 850, industry: '银行', province: '广东' }, + { code: '300750', name: '宁德时代', cap: 780, industry: '电力设备', province: '福建' }, + { code: '601166', name: '兴业银行', cap: 420, industry: '银行', province: '福建' }, + { code: '000858', name: '五粮液', cap: 580, industry: '食品饮料', province: '四川' }, + { code: '002594', name: '比亚迪', cap: 650, industry: '汽车', province: '广东' }, + { code: '601012', name: '隆基绿能', cap: 320, industry: '电力设备', province: '陕西' }, + { code: '688981', name: '中芯国际', cap: 280, industry: '电子', province: '上海' }, + { code: '600900', name: '长江电力', cap: 520, industry: '公用事业', province: '湖北' }, + ]; + + // 生成热力图数据 + const heatmapData = []; + let risingCount = 0; + let fallingCount = 0; + + // 先添加主要股票 + majorStocks.forEach(stock => { + const changePercent = parseFloat((Math.random() * 12 - 4).toFixed(2)); // -4% ~ 8% + const amount = parseFloat((Math.random() * 100 + 10).toFixed(2)); // 10-110亿 + + if (changePercent > 0) risingCount++; + else if (changePercent < 0) fallingCount++; + + heatmapData.push({ + stock_code: stock.code, + stock_name: stock.name, + market_cap: stock.cap, + change_percent: changePercent, + amount: amount, + industry: stock.industry, + province: stock.province + }); + }); + + // 生成更多随机股票数据 + for (let i = majorStocks.length; i < Math.min(limit, 200); i++) { + const changePercent = parseFloat((Math.random() * 14 - 5).toFixed(2)); // -5% ~ 9% + const marketCap = parseFloat((Math.random() * 500 + 20).toFixed(2)); // 20-520亿 + const amount = parseFloat((Math.random() * 50 + 1).toFixed(2)); // 1-51亿 + + if (changePercent > 0) risingCount++; + else if (changePercent < 0) fallingCount++; + + heatmapData.push({ + stock_code: `${600000 + i}`, + stock_name: `股票${i}`, + market_cap: marketCap, + change_percent: changePercent, + amount: amount, + industry: industries[Math.floor(Math.random() * industries.length)], + province: provinces[Math.floor(Math.random() * provinces.length)] + }); + } + + console.log('[Mock Market] 获取热力图数据:', { limit, date: tradeDate, count: heatmapData.length }); + + return HttpResponse.json({ + success: true, + data: heatmapData, + trade_date: tradeDate, + statistics: { + rising_count: risingCount, + falling_count: fallingCount + } + }); + }), + + // 11. 市场统计数据(个股中心页面使用) + http.get('/api/market/statistics', async ({ request }) => { + await delay(200); + const url = new URL(request.url); + const date = url.searchParams.get('date'); + + const tradeDate = date || new Date().toISOString().split('T')[0]; + + // 生成最近30个交易日 + const availableDates = []; + const currentDate = new Date(tradeDate); + for (let i = 0; i < 30; i++) { + const d = new Date(currentDate); + d.setDate(d.getDate() - i); + // 跳过周末 + if (d.getDay() !== 0 && d.getDay() !== 6) { + availableDates.push(d.toISOString().split('T')[0]); + } + } + + console.log('[Mock Market] 获取市场统计数据:', { date: tradeDate }); + + return HttpResponse.json({ + success: true, + summary: { + total_market_cap: parseFloat((Math.random() * 5000 + 80000).toFixed(2)), // 80000-85000亿 + total_amount: parseFloat((Math.random() * 3000 + 8000).toFixed(2)), // 8000-11000亿 + avg_pe: parseFloat((Math.random() * 5 + 12).toFixed(2)), // 12-17 + avg_pb: parseFloat((Math.random() * 0.5 + 1.3).toFixed(2)), // 1.3-1.8 + rising_stocks: Math.floor(Math.random() * 1500 + 1500), // 1500-3000 + falling_stocks: Math.floor(Math.random() * 1500 + 1000), // 1000-2500 + unchanged_stocks: Math.floor(Math.random() * 200 + 100) // 100-300 + }, + trade_date: tradeDate, + available_dates: availableDates.slice(0, 20) // 返回最近20个交易日 + }); + }), ]; diff --git a/src/views/StockOverview/index.js b/src/views/StockOverview/index.js index 52da86e9..1dde440b 100644 --- a/src/views/StockOverview/index.js +++ b/src/views/StockOverview/index.js @@ -42,7 +42,6 @@ import { useDisclosure, Image, Fade, - ScaleFade, Collapse, Stack, Progress, @@ -58,25 +57,12 @@ import { import { SearchIcon, CloseIcon, ArrowForwardIcon, TrendingUpIcon, InfoIcon, ChevronRightIcon, MoonIcon, SunIcon, CalendarIcon } from '@chakra-ui/icons'; import { FaChartLine, FaFire, FaRocket, FaBrain, FaCalendarAlt, FaChevronRight, FaArrowUp, FaArrowDown, FaChartBar } from 'react-icons/fa'; import { BsGraphUp, BsLightningFill } from 'react-icons/bs'; -import { keyframes } from '@emotion/react'; import * as echarts from 'echarts'; import { logger } from '../../utils/logger'; import { useStockOverviewEvents } from './hooks/useStockOverviewEvents'; // Navigation bar now provided by MainLayout // import HomeNavbar from '../../components/Navbars/HomeNavbar'; -// 动画定义 -const pulseAnimation = keyframes` - 0% { transform: scale(1); } - 50% { transform: scale(1.05); } - 100% { transform: scale(1); } -`; - -const floatAnimation = keyframes` - 0%, 100% { transform: translateY(0px); } - 50% { transform: translateY(-10px); } -`; - const StockOverview = () => { const navigate = useNavigate(); const toast = useToast(); @@ -622,7 +608,7 @@ const StockOverview = () => { - + { ) : ( {topConcepts.map((concept, index) => ( - { px={3} py={1} borderRadius="full" - animation={Math.abs(concept.change_percent) > 5 ? `${pulseAnimation} 2s infinite` : 'none'} border={colorMode === 'dark' ? '1px solid' : 'none'} borderColor={colorMode === 'dark' ? concept.change_percent > 0 ? '#ff4d4d' : '#22c55e' : 'transparent'} > @@ -1039,7 +1024,6 @@ const StockOverview = () => { - ))} )}