/** * 热点概览组件 - Modern Spatial & Glassmorphism 设计 * 展示大盘分时走势 + 概念异动标注 * * 布局设计: * - 顶部:统计摘要(指数信息 + 异动统计) * - 中部:大尺寸分时图(主要展示区域) * - 底部:异动列表(横向滚动卡片) */ import React, { useState, useCallback } from 'react'; import { Box, Heading, Text, HStack, VStack, Spinner, Center, Icon, Flex, Spacer, Tooltip, IconButton, Collapse, SimpleGrid, useDisclosure, } from '@chakra-ui/react'; import { keyframes, css } from '@emotion/react'; import { Flame, List, LineChart, ChevronDown, ChevronUp, Info, Zap, AlertCircle, TrendingUp, TrendingDown, Sparkles, } from 'lucide-react'; import { useHotspotData } from './hooks'; import { IndexMinuteChart, ConceptAlertList, AlertSummary, AlertDetailDrawer } from './components'; import { ALERT_TYPE_CONFIG, getAlertTypeLabel } from './utils/chartHelpers'; import { glassEffect, colors, glowEffects, getMarketColor, getMarketGlow, } from '../../theme/glassTheme'; // 动画效果 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.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.02); } `; const floatAnimation = keyframes` 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-3px); } `; const shimmer = keyframes` 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } `; /** * 紧凑型异动卡片(用于横向滚动)- Glassmorphism 风格 */ const CompactAlertCard = ({ alert, onClick, isSelected }) => { 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.3s cubic-bezier(0.4, 0, 0.2, 1)" position="relative" overflow="hidden" _hover={{ bg: 'rgba(255, 255, 255, 0.05)', border: `1px solid ${config.color}50`, transform: 'translateY(-4px)', boxShadow: `0 8px 25px ${config.color}20, inset 0 1px 0 rgba(255,255,255,0.1)`, }} css={isSelected ? css`animation: ${floatAnimation} 3s ease-in-out infinite;` : undefined} > {/* 顶部渐变发光条 */} {/* 背景光晕 */} {isSelected && ( )} {/* 时间 + 类型 */} {alert.time} {getAlertTypeLabel(alert.alert_type)} {/* 概念名称 */} {alert.concept_name} {/* 分数 + Alpha */} 评分 {Math.round(alert.final_score || 0)} {alert.alpha != null && ( α {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 [autoExpandAlertKey, setAutoExpandAlertKey] = useState(null); const [drawerAlertData, setDrawerAlertData] = useState(null); // 右边栏抽屉控制 const { isOpen: isDrawerOpen, onOpen: onDrawerOpen, onClose: onDrawerClose } = useDisclosure(); // 获取数据 const { loading, error, data } = useHotspotData(selectedDate); // Glassmorphism 颜色主题 const cardBg = glassEffect.card.bg; const borderColor = colors.border.primary; const textColor = colors.text.primary; const subTextColor = colors.text.secondary; const sectionBg = glassEffect.light.bg; const scrollbarColor = 'rgba(139, 92, 246, 0.3)'; // 点击分时图上的异动标注 - 打开右边栏抽屉显示详情 const handleChartAlertClick = useCallback((alertGroupData) => { // alertGroupData 包含 { alerts, timeRange, alertCount, time } setDrawerAlertData(alertGroupData); onDrawerOpen(); }, [onDrawerOpen]); // 点击底部异动卡片 - 展开详细列表并选中 const handleAlertClick = useCallback((alert) => { setSelectedAlert(alert); // 自动展开详细列表并设置需要展开的项 setShowDetailList(true); const alertKey = `${alert.concept_id}-${alert.time}`; setAutoExpandAlertKey(alertKey); }, []); // 渲染加载状态 - Glassmorphism 风格 if (loading) { return ( {/* 极光背景 */} {/* 顶部发光条 */}
加载热点概览数据 正在获取市场异动信息...
); } // 渲染错误状态 - Glassmorphism 风格 if (error) { return (
数据加载失败 {error}
); } if (!data) return null; const { index, alerts, alert_summary } = data; // 计算市场颜色 const marketColor = getMarketColor(index?.change_pct || 0); const marketGlow = getMarketGlow(index?.change_pct || 0); return ( {/* 极光背景装饰 */} {/* 顶部发光装饰条 */} {/* 头部 - Glassmorphism */} {/* 图标发光效果 */} 热点概览 实时概念异动监控 {alerts.length > 0 && ( {alerts.length} )} {/* 统计摘要 - Glassmorphism Bento Grid */} {/* 指数信息卡片 */} {/* 背景光晕 */} {index?.name || '上证指数'} {index?.latest_price?.toFixed(2) || '-'} = 0 ? TrendingUp : TrendingDown} boxSize={4} color={marketColor} css={css`filter: drop-shadow(0 0 4px ${marketColor});`} /> {(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, 5) .map(([type, count]) => { const config = ALERT_TYPE_CONFIG[type]; if (!config) return null; return ( {config.label} {count} ); })} {/* 大尺寸分时图 - Glassmorphism */} {/* 图表区域背景光晕 */} 大盘分时走势 {/* 异动列表 - Glassmorphism 横向滚动 */} {alerts.length > 0 && ( 异动记录 (点击卡片查看个股详情) } size="sm" variant="ghost" borderRadius="12px" color={colors.text.secondary} _hover={{ bg: 'rgba(255,255,255,0.05)', color: textColor, }} onClick={() => setShowDetailList(!showDetailList)} aria-label="切换详细列表" /> {/* 横向滚动卡片 */} {[...alerts] .sort((a, b) => (b.time || '').localeCompare(a.time || '')) .map((alert, idx) => ( ))} {/* 详细列表(可展开) - Glassmorphism */} {/* 背景光晕 */} setAutoExpandAlertKey(null)} /> )} {/* 无异动提示 - Glassmorphism */} {alerts.length === 0 && (
{/* 背景光晕 */} 当日暂无概念异动数据
)}
{/* 异动详情右边栏抽屉 */}
); }; export default HotspotOverview;