update pay ui

This commit is contained in:
2025-12-11 07:32:30 +08:00
parent f545c9ec15
commit 8c6ebe01ed
5 changed files with 1379 additions and 321 deletions

View File

@@ -1,5 +1,5 @@
/**
* 热点概览组件
* 热点概览组件 - 科技感设计
* 展示大盘分时走势 + 概念异动标注
*
* 模块化结构:
@@ -12,8 +12,6 @@
import React, { useState, useCallback } from 'react';
import {
Box,
Card,
CardBody,
Heading,
Text,
HStack,
@@ -27,16 +25,36 @@ import {
useColorModeValue,
Grid,
GridItem,
Divider,
IconButton,
Collapse,
keyframes,
} from '@chakra-ui/react';
import { FaFire, FaList, FaChartArea, FaChevronDown, FaChevronUp } from 'react-icons/fa';
import { InfoIcon } from '@chakra-ui/icons';
import {
Flame,
List,
LineChart,
ChevronDown,
ChevronUp,
Info,
Zap,
AlertCircle,
} from 'lucide-react';
import { useHotspotData } from './hooks';
import { IndexMinuteChart, ConceptAlertList, AlertSummary } from './components';
// 动画效果
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; }
`;
/**
* 热点概览主组件
* @param {Object} props
@@ -50,46 +68,102 @@ const HotspotOverview = ({ selectedDate }) => {
const { loading, error, data } = useHotspotData(selectedDate);
// 颜色主题
const cardBg = useColorModeValue('white', '#1a1a1a');
const borderColor = useColorModeValue('gray.200', '#333333');
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 headerGradient = useColorModeValue(
'linear(to-r, orange.500, red.500)',
'linear(to-r, orange.400, red.400)'
);
// 点击异动标注
const handleAlertClick = useCallback((alert) => {
setSelectedAlert(alert);
// 可以在这里添加滚动到对应位置的逻辑
}, []);
// 渲染加载状态
if (loading) {
return (
<Card bg={cardBg} borderWidth="1px" borderColor={borderColor}>
<CardBody>
<Center h="400px">
<VStack spacing={4}>
<Spinner size="xl" color="purple.500" thickness="4px" />
<Text color={subTextColor}>加载热点概览数据...</Text>
<Box
bg={cardBg}
borderRadius="2xl"
borderWidth="1px"
borderColor={borderColor}
overflow="hidden"
>
{/* 顶部装饰条 */}
<Box
h="4px"
bgGradient="linear(to-r, orange.400, red.500, pink.500)"
backgroundSize="200% 200%"
animation={`${gradientShift} 3s ease infinite`}
/>
<Center h="400px" p={6}>
<VStack spacing={4}>
<Box position="relative">
<Spinner
size="xl"
color="orange.400"
thickness="3px"
speed="0.8s"
/>
<Box
position="absolute"
inset={0}
borderRadius="full"
animation={`${pulseGlow} 2s ease-in-out infinite`}
boxShadow="0 0 30px rgba(251, 146, 60, 0.3)"
/>
</Box>
<VStack spacing={1}>
<Text color={textColor} fontWeight="medium">
加载热点概览数据
</Text>
<Text color={subTextColor} fontSize="sm">
正在获取市场异动信息...
</Text>
</VStack>
</Center>
</CardBody>
</Card>
</VStack>
</Center>
</Box>
);
}
// 渲染错误状态
if (error) {
return (
<Card bg={cardBg} borderWidth="1px" borderColor={borderColor}>
<CardBody>
<Center h="400px">
<VStack spacing={4}>
<Icon as={InfoIcon} boxSize={10} color="red.400" />
<Text color="red.500">{error}</Text>
<Box
bg={cardBg}
borderRadius="2xl"
borderWidth="1px"
borderColor={borderColor}
overflow="hidden"
>
<Box h="4px" bg="red.500" />
<Center h="400px" p={6}>
<VStack spacing={4}>
<Box
p={4}
borderRadius="full"
bg="red.500"
bgOpacity={0.1}
>
<Icon as={AlertCircle} boxSize={10} color="red.400" />
</Box>
<VStack spacing={1}>
<Text color="red.400" fontWeight="medium">
数据加载失败
</Text>
<Text color={subTextColor} fontSize="sm" textAlign="center">
{error}
</Text>
</VStack>
</Center>
</CardBody>
</Card>
</VStack>
</Center>
</Box>
);
}
@@ -101,53 +175,131 @@ const HotspotOverview = ({ selectedDate }) => {
const { index, alerts, alert_summary } = data;
return (
<Card bg={cardBg} borderWidth="1px" borderColor={borderColor}>
<CardBody>
<Box
bg={cardBg}
borderRadius="2xl"
borderWidth="1px"
borderColor={borderColor}
overflow="hidden"
transition="all 0.3s"
_hover={{
boxShadow: useColorModeValue(
'0 4px 20px rgba(0,0,0,0.08)',
'0 4px 20px rgba(0,0,0,0.4)'
),
}}
>
{/* 顶部装饰条 */}
<Box
h="4px"
bgGradient="linear(to-r, orange.400, red.500, pink.500)"
backgroundSize="200% 200%"
animation={`${gradientShift} 3s ease infinite`}
/>
<Box p={5}>
{/* 头部 */}
<Flex align="center" mb={4}>
<Flex align="center" mb={5}>
<HStack spacing={3}>
<Icon as={FaFire} boxSize={6} color="orange.500" />
<Heading size="md" color={textColor}>
热点概览
</Heading>
<Box
p={2}
borderRadius="xl"
bgGradient="linear(to-br, orange.400, red.500)"
boxShadow="0 4px 15px rgba(251, 146, 60, 0.4)"
>
<Icon as={Flame} boxSize={5} color="white" />
</Box>
<VStack align="flex-start" spacing={0}>
<Heading size="md" color={textColor} fontWeight="bold">
热点概览
</Heading>
<Text fontSize="xs" color={subTextColor}>
实时概念异动监控
</Text>
</VStack>
</HStack>
<Spacer />
<HStack spacing={2}>
<Tooltip label={showAlertList ? '收起异动列表' : '展开异动列表'}>
{/* 异动数量徽章 */}
{alerts.length > 0 && (
<HStack
spacing={1}
px={3}
py={1.5}
borderRadius="full"
bg="orange.500"
bgOpacity={0.15}
>
<Icon as={Zap} boxSize={3.5} color="orange.400" />
<Text fontSize="sm" fontWeight="bold" color="orange.400">
{alerts.length}
</Text>
</HStack>
)}
{/* 切换按钮 */}
<Tooltip label={showAlertList ? '收起异动列表' : '展开异动列表'} hasArrow>
<IconButton
icon={showAlertList ? <FaChevronUp /> : <FaList />}
icon={<Icon as={showAlertList ? ChevronUp : List} boxSize={4} />}
size="sm"
variant="ghost"
borderRadius="lg"
onClick={() => setShowAlertList(!showAlertList)}
aria-label="切换异动列表"
_hover={{
bg: useColorModeValue('gray.100', 'gray.800'),
}}
/>
</Tooltip>
<Tooltip label="展示大盘走势与概念异动的关联">
<Icon as={InfoIcon} color={subTextColor} />
{/* 信息提示 */}
<Tooltip
label="展示大盘走势与概念异动的关联,帮助发现市场热点"
hasArrow
maxW="200px"
>
<Box cursor="help">
<Icon as={Info} color={subTextColor} boxSize={4} />
</Box>
</Tooltip>
</HStack>
</Flex>
{/* 统计摘要 */}
<Box mb={4}>
<Box mb={5}>
<AlertSummary indexData={index} alerts={alerts} alertSummary={alert_summary} />
</Box>
<Divider mb={4} />
{/* 主体内容:图表 + 异动列表 */}
<Grid
templateColumns={{ base: '1fr', lg: showAlertList ? '1fr 300px' : '1fr' }}
gap={4}
templateColumns={{ base: '1fr', lg: showAlertList ? '1fr 320px' : '1fr' }}
gap={5}
>
{/* 分时图 */}
<GridItem>
<Box>
<HStack spacing={2} mb={2}>
<Icon as={FaChartArea} color="purple.500" boxSize={4} />
<Text fontSize="sm" fontWeight="medium" color={textColor}>
<Box
bg={useColorModeValue('gray.50', '#0d0d0d')}
borderRadius="xl"
borderWidth="1px"
borderColor={borderColor}
p={4}
transition="all 0.2s"
>
<HStack spacing={2} mb={3}>
<Box
p={1.5}
borderRadius="lg"
bg="purple.500"
bgOpacity={0.15}
>
<Icon as={LineChart} boxSize={4} color="purple.400" />
</Box>
<Text fontSize="sm" fontWeight="bold" color={textColor}>
大盘分时走势
</Text>
<Tooltip label="图表上的标记点表示概念异动时刻" hasArrow>
<Icon as={Info} boxSize={3} color={subTextColor} cursor="help" />
</Tooltip>
</HStack>
<IndexMinuteChart
indexData={index}
@@ -159,12 +311,26 @@ const HotspotOverview = ({ selectedDate }) => {
</GridItem>
{/* 异动列表(可收起) */}
<Collapse in={showAlertList} animateOpacity>
<Collapse in={showAlertList} animateOpacity style={{ overflow: 'visible' }}>
<GridItem>
<Box>
<HStack spacing={2} mb={2}>
<Icon as={FaList} color="orange.500" boxSize={4} />
<Text fontSize="sm" fontWeight="medium" color={textColor}>
<Box
bg={useColorModeValue('gray.50', '#0d0d0d')}
borderRadius="xl"
borderWidth="1px"
borderColor={borderColor}
p={4}
h="100%"
>
<HStack spacing={2} mb={3}>
<Box
p={1.5}
borderRadius="lg"
bg="orange.500"
bgOpacity={0.15}
>
<Icon as={List} boxSize={4} color="orange.400" />
</Box>
<Text fontSize="sm" fontWeight="bold" color={textColor}>
异动记录
</Text>
<Text fontSize="xs" color={subTextColor}>
@@ -175,7 +341,7 @@ const HotspotOverview = ({ selectedDate }) => {
alerts={alerts}
onAlertClick={handleAlertClick}
selectedAlert={selectedAlert}
maxHeight="350px"
maxHeight="380px"
/>
</Box>
</GridItem>
@@ -184,14 +350,22 @@ const HotspotOverview = ({ selectedDate }) => {
{/* 无异动提示 */}
{alerts.length === 0 && (
<Center py={4}>
<Text color={subTextColor} fontSize="sm">
当日暂无概念异动数据
</Text>
<Center
py={8}
mt={4}
bg={useColorModeValue('gray.50', '#0d0d0d')}
borderRadius="xl"
>
<VStack spacing={2}>
<Icon as={Zap} boxSize={8} color={subTextColor} opacity={0.5} />
<Text color={subTextColor} fontSize="sm">
当日暂无概念异动数据
</Text>
</VStack>
</Center>
)}
</CardBody>
</Card>
</Box>
</Box>
);
};