/** * 热点概览组件 - 科技感设计 * 展示大盘分时走势 + 概念异动标注 * * 布局设计: * - 顶部:统计摘要(指数信息 + 异动统计) * - 中部:大尺寸分时图(主要展示区域) * - 底部:异动列表(横向滚动卡片) */ import React, { useState, useCallback } from 'react'; import { Box, Heading, Text, HStack, VStack, Spinner, Center, Icon, Flex, Spacer, Tooltip, useColorModeValue, IconButton, Collapse, SimpleGrid, } from '@chakra-ui/react'; import { keyframes } from '@emotion/react'; import { Flame, List, LineChart, ChevronDown, ChevronUp, Info, Zap, AlertCircle, TrendingUp, TrendingDown, } from 'lucide-react'; import { useHotspotData } from './hooks'; import { IndexMinuteChart, ConceptAlertList, AlertSummary } from './components'; import { ALERT_TYPE_CONFIG, getAlertTypeLabel } from './utils/chartHelpers'; // 动画效果 const gradientShift = keyframes` 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } `; const pulseGlow = keyframes` 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } `; /** * 紧凑型异动卡片(用于横向滚动) */ const CompactAlertCard = ({ alert, onClick, isSelected }) => { const cardBg = useColorModeValue('white', '#0d0d0d'); const borderColor = useColorModeValue('gray.200', '#2d2d2d'); const textColor = useColorModeValue('gray.800', 'white'); const subTextColor = useColorModeValue('gray.500', 'gray.400'); const config = ALERT_TYPE_CONFIG[alert.alert_type] || ALERT_TYPE_CONFIG.surge; const isUp = alert.alert_type !== 'surge_down'; return ( onClick?.(alert)} transition="all 0.2s" _hover={{ borderColor: config.color, transform: 'translateY(-2px)', boxShadow: `0 4px 15px ${config.color}25`, }} position="relative" overflow="hidden" > {/* 顶部渐变条 */} {/* 时间 + 类型 */} {alert.time} {getAlertTypeLabel(alert.alert_type)} {/* 概念名称 */} {alert.concept_name} {/* 分数 + Alpha */} 评分 {Math.round(alert.final_score || 0)} {alert.alpha != null && ( = 0 ? '#ff4d4f' : '#52c41a'} > α {alert.alpha >= 0 ? '+' : ''}{alert.alpha.toFixed(1)}% )} ); }; /** * 热点概览主组件 * @param {Object} props * @param {Date|null} props.selectedDate - 选中的交易日期 */ const HotspotOverview = ({ selectedDate }) => { const [selectedAlert, setSelectedAlert] = useState(null); const [showDetailList, setShowDetailList] = useState(false); // 获取数据 const { loading, error, data } = useHotspotData(selectedDate); // 颜色主题 const cardBg = useColorModeValue('white', '#0a0a0a'); const borderColor = useColorModeValue('gray.200', '#1f1f1f'); const textColor = useColorModeValue('gray.800', 'white'); const subTextColor = useColorModeValue('gray.600', 'gray.400'); const sectionBg = useColorModeValue('gray.50', '#0d0d0d'); const scrollbarColor = useColorModeValue('#ddd', '#333'); // 点击异动标注 const handleAlertClick = useCallback((alert) => { setSelectedAlert(alert); }, []); // 渲染加载状态 if (loading) { return (
加载热点概览数据 正在获取市场异动信息...
); } // 渲染错误状态 if (error) { return (
数据加载失败 {error}
); } if (!data) return null; const { index, alerts, alert_summary } = data; return ( {/* 顶部装饰条 */} {/* 头部 */} 热点概览 实时概念异动监控 {alerts.length > 0 && ( {alerts.length} )} {/* 统计摘要 - 简化版 */} {/* 指数信息 */} {index?.name || '上证指数'} = 0 ? '#ff4d4f' : '#52c41a'} > {index?.latest_price?.toFixed(2) || '-'} = 0 ? 'red.50' : 'green.50'} > = 0 ? TrendingUp : TrendingDown} boxSize={3} color={(index?.change_pct || 0) >= 0 ? '#ff4d4f' : '#52c41a'} /> = 0 ? '#ff4d4f' : '#52c41a'} > {(index?.change_pct || 0) >= 0 ? '+' : ''}{(index?.change_pct || 0).toFixed(2)}% {index?.high?.toFixed(2)} {index?.low?.toFixed(2)} {/* 异动统计 */} 今日异动 {alerts.length} 次 {Object.entries(alert_summary || {}) .filter(([_, count]) => count > 0) .slice(0, 4) .map(([type, count]) => { const config = ALERT_TYPE_CONFIG[type]; if (!config) return null; return ( {config.label} {count} ); })} {/* 大尺寸分时图 */} 大盘分时走势 {/* 异动列表 - 横向滚动 */} {alerts.length > 0 && ( 异动记录 (横向滚动查看更多) } size="sm" variant="ghost" borderRadius="lg" onClick={() => setShowDetailList(!showDetailList)} aria-label="切换详细列表" /> {/* 横向滚动卡片 */} {[...alerts] .sort((a, b) => (b.time || '').localeCompare(a.time || '')) .map((alert, idx) => ( ))} {/* 详细列表(可展开) */} )} {/* 无异动提示 */} {alerts.length === 0 && (
当日暂无概念异动数据
)}
); }; export default HotspotOverview;