heropanel修改
This commit is contained in:
@@ -64,121 +64,113 @@ const getChgColor = (val) => {
|
|||||||
* 获取胜率颜色(>50%红色,<50%绿色)
|
* 获取胜率颜色(>50%红色,<50%绿色)
|
||||||
*/
|
*/
|
||||||
const getRateColor = (rate) => {
|
const getRateColor = (rate) => {
|
||||||
if (rate >= 50) return '#FF4D4F'; // 红色(上涨多)
|
if (rate >= 50) return '#F31260'; // HeroUI 红色
|
||||||
return '#52C41A'; // 绿色(下跌多)
|
return '#17C964'; // HeroUI 绿色
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 半圆仪表盘组件 - 使用 SVG 实现渐变弧线
|
* HeroUI 风格圆环仪表盘
|
||||||
* 渐变色:左侧绿色 -> 中间黄色 -> 右侧红色
|
|
||||||
*/
|
*/
|
||||||
const SemiCircleGauge = ({ rate, label, size = 'normal' }) => {
|
const CircularGauge = ({ rate, label, icon }) => {
|
||||||
const validRate = Math.min(100, Math.max(0, rate || 0));
|
const validRate = Math.min(100, Math.max(0, rate || 0));
|
||||||
// 角度:0% = -90deg (左), 50% = 0deg (上), 100% = 90deg (右)
|
|
||||||
const needleAngle = (validRate / 100) * 180 - 90;
|
|
||||||
|
|
||||||
const gaugeColor = getRateColor(validRate);
|
const gaugeColor = getRateColor(validRate);
|
||||||
const isSmall = size === 'small';
|
const circumference = 2 * Math.PI * 42; // 半径42
|
||||||
const svgSize = isSmall ? 80 : 100;
|
const strokeDashoffset = circumference - (validRate / 100) * circumference;
|
||||||
const strokeWidth = isSmall ? 6 : 8;
|
|
||||||
const radius = (svgSize - strokeWidth) / 2;
|
|
||||||
const needleLength = isSmall ? 28 : 35;
|
|
||||||
const gradientId = `gauge-gradient-${label.replace(/\s/g, '-')}`;
|
|
||||||
|
|
||||||
// 计算半圆弧的路径(从左到右)
|
|
||||||
const arcPath = `M ${strokeWidth / 2} ${svgSize / 2} A ${radius} ${radius} 0 0 1 ${svgSize - strokeWidth / 2} ${svgSize / 2}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box position="relative" w={`${svgSize}px`} h={`${svgSize / 2 + 18}px`}>
|
<Box
|
||||||
{/* SVG 半圆弧 */}
|
bg="rgba(255,255,255,0.03)"
|
||||||
<svg
|
backdropFilter="blur(20px)"
|
||||||
width={svgSize}
|
borderRadius="2xl"
|
||||||
height={svgSize / 2 + 2}
|
p={4}
|
||||||
style={{ position: 'absolute', top: 0, left: 0 }}
|
border="1px solid"
|
||||||
>
|
borderColor="rgba(255,255,255,0.08)"
|
||||||
<defs>
|
position="relative"
|
||||||
<linearGradient id={gradientId} x1="0%" y1="0%" x2="100%" y2="0%">
|
overflow="hidden"
|
||||||
<stop offset="0%" stopColor="#52C41A" />
|
flex="1"
|
||||||
<stop offset="50%" stopColor="#FADB14" />
|
_before={{
|
||||||
<stop offset="100%" stopColor="#FF4D4F" />
|
content: '""',
|
||||||
</linearGradient>
|
position: 'absolute',
|
||||||
</defs>
|
top: 0,
|
||||||
<path
|
left: 0,
|
||||||
d={arcPath}
|
right: 0,
|
||||||
fill="none"
|
bottom: 0,
|
||||||
stroke={`url(#${gradientId})`}
|
background: `radial-gradient(circle at 30% 20%, ${gaugeColor}15 0%, transparent 50%)`,
|
||||||
strokeWidth={strokeWidth}
|
pointerEvents: 'none',
|
||||||
strokeLinecap="round"
|
}}
|
||||||
/>
|
>
|
||||||
</svg>
|
{/* 圆环仪表盘 */}
|
||||||
|
<Center>
|
||||||
|
<Box position="relative" w="100px" h="100px">
|
||||||
|
<svg width="100" height="100" style={{ transform: 'rotate(-90deg)' }}>
|
||||||
|
{/* 背景圆环 */}
|
||||||
|
<circle
|
||||||
|
cx="50"
|
||||||
|
cy="50"
|
||||||
|
r="42"
|
||||||
|
fill="none"
|
||||||
|
stroke="rgba(255,255,255,0.08)"
|
||||||
|
strokeWidth="8"
|
||||||
|
/>
|
||||||
|
{/* 渐变定义 */}
|
||||||
|
<defs>
|
||||||
|
<linearGradient id={`gauge-grad-${label}`} x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
|
<stop offset="0%" stopColor={gaugeColor} stopOpacity="0.6" />
|
||||||
|
<stop offset="100%" stopColor={gaugeColor} />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
{/* 进度圆环 */}
|
||||||
|
<circle
|
||||||
|
cx="50"
|
||||||
|
cy="50"
|
||||||
|
r="42"
|
||||||
|
fill="none"
|
||||||
|
stroke={`url(#gauge-grad-${label})`}
|
||||||
|
strokeWidth="8"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeDasharray={circumference}
|
||||||
|
strokeDashoffset={strokeDashoffset}
|
||||||
|
style={{
|
||||||
|
transition: 'stroke-dashoffset 0.8s ease-out',
|
||||||
|
filter: `drop-shadow(0 0 8px ${gaugeColor}60)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{/* 中心数值 */}
|
||||||
|
<VStack
|
||||||
|
position="absolute"
|
||||||
|
top="50%"
|
||||||
|
left="50%"
|
||||||
|
transform="translate(-50%, -50%)"
|
||||||
|
spacing={0}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontSize="2xl"
|
||||||
|
fontWeight="bold"
|
||||||
|
color={gaugeColor}
|
||||||
|
lineHeight="1"
|
||||||
|
textShadow={`0 0 20px ${gaugeColor}40`}
|
||||||
|
>
|
||||||
|
{validRate.toFixed(1)}
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.600">%</Text>
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
</Center>
|
||||||
|
|
||||||
{/* 指针 */}
|
{/* 标签 */}
|
||||||
<Box
|
<HStack justify="center" mt={2} spacing={2}>
|
||||||
position="absolute"
|
<Box color={gaugeColor} fontSize="sm">{icon}</Box>
|
||||||
bottom="18px"
|
<Text fontSize="sm" color="whiteAlpha.800" fontWeight="medium">
|
||||||
left="50%"
|
{label}
|
||||||
w="2px"
|
|
||||||
h={`${needleLength}px`}
|
|
||||||
bg={gaugeColor}
|
|
||||||
borderRadius="full"
|
|
||||||
transformOrigin="bottom center"
|
|
||||||
transform={`translateX(-50%) rotate(${needleAngle}deg)`}
|
|
||||||
boxShadow={`0 0 6px ${gaugeColor}`}
|
|
||||||
transition="transform 0.5s ease-out"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 指针中心点 */}
|
|
||||||
<Box
|
|
||||||
position="absolute"
|
|
||||||
bottom="15px"
|
|
||||||
left="50%"
|
|
||||||
transform="translateX(-50%)"
|
|
||||||
w="6px"
|
|
||||||
h="6px"
|
|
||||||
bg={gaugeColor}
|
|
||||||
borderRadius="full"
|
|
||||||
boxShadow={`0 0 4px ${gaugeColor}`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 刻度标记 */}
|
|
||||||
<Text
|
|
||||||
position="absolute"
|
|
||||||
bottom="18px"
|
|
||||||
left="2px"
|
|
||||||
fontSize="2xs"
|
|
||||||
color="gray.600"
|
|
||||||
>
|
|
||||||
0
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
position="absolute"
|
|
||||||
bottom="18px"
|
|
||||||
right="2px"
|
|
||||||
fontSize="2xs"
|
|
||||||
color="gray.600"
|
|
||||||
>
|
|
||||||
100
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{/* 数值和标签 */}
|
|
||||||
<VStack
|
|
||||||
position="absolute"
|
|
||||||
bottom="0"
|
|
||||||
left="50%"
|
|
||||||
transform="translateX(-50%)"
|
|
||||||
spacing={0}
|
|
||||||
>
|
|
||||||
<Text fontSize={isSmall ? 'sm' : 'md'} fontWeight="bold" color={gaugeColor} lineHeight="1">
|
|
||||||
{validRate.toFixed(1)}%
|
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="2xs" color="gray.500">{label}</Text>
|
</HStack>
|
||||||
</VStack>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 胜率对比组件 - 双仪表盘
|
* HeroUI 风格胜率对比面板
|
||||||
*/
|
*/
|
||||||
const WinRateGauge = ({ eventRate, marketRate, marketStats }) => {
|
const WinRateGauge = ({ eventRate, marketRate, marketStats }) => {
|
||||||
const eventRateVal = eventRate || 0;
|
const eventRateVal = eventRate || 0;
|
||||||
@@ -186,60 +178,122 @@ const WinRateGauge = ({ eventRate, marketRate, marketStats }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
{/* 双仪表盘对比 */}
|
{/* 双仪表盘对比 - HeroUI 毛玻璃卡片 */}
|
||||||
<HStack spacing={2} justify="center" mb={1}>
|
<HStack spacing={4} mb={4}>
|
||||||
<VStack spacing={0}>
|
<CircularGauge
|
||||||
<SemiCircleGauge rate={eventRateVal} label="事件胜率" size="small" />
|
rate={eventRateVal}
|
||||||
</VStack>
|
label="事件胜率"
|
||||||
<Box w="1px" h="50px" bg="rgba(255,215,0,0.2)" />
|
icon={<TrophyOutlined />}
|
||||||
<VStack spacing={0}>
|
/>
|
||||||
<SemiCircleGauge rate={marketRateVal} label="大盘上涨率" size="small" />
|
<CircularGauge
|
||||||
</VStack>
|
rate={marketRateVal}
|
||||||
|
label="大盘上涨率"
|
||||||
|
icon={<RiseOutlined />}
|
||||||
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{/* 市场统计 */}
|
{/* 市场统计 - 毛玻璃条 */}
|
||||||
{marketStats && (
|
{marketStats && marketStats.totalCount > 0 && (
|
||||||
<HStack justify="center" spacing={3} mt={1}>
|
<Box
|
||||||
<HStack spacing={1}>
|
bg="rgba(255,255,255,0.03)"
|
||||||
<Box w="6px" h="6px" borderRadius="full" bg="#FF4D4F" />
|
backdropFilter="blur(10px)"
|
||||||
<Text fontSize="2xs" color="#FF4D4F">{marketStats.risingCount}涨</Text>
|
borderRadius="xl"
|
||||||
|
p={3}
|
||||||
|
border="1px solid rgba(255,255,255,0.06)"
|
||||||
|
>
|
||||||
|
<HStack justify="space-between" mb={2}>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.500">沪深两市实时</Text>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.400">{marketStats.totalCount} 只</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
<HStack spacing={1}>
|
{/* 进度条 */}
|
||||||
<Box w="6px" h="6px" borderRadius="full" bg="gray.400" />
|
<Box position="relative" h="6px" borderRadius="full" overflow="hidden" bg="rgba(255,255,255,0.05)">
|
||||||
<Text fontSize="2xs" color="gray.400">{marketStats.flatCount}平</Text>
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
left="0"
|
||||||
|
top="0"
|
||||||
|
h="100%"
|
||||||
|
w={`${(marketStats.risingCount / marketStats.totalCount) * 100}%`}
|
||||||
|
bg="linear-gradient(90deg, #F31260, #FF6B9D)"
|
||||||
|
borderRadius="full"
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
left={`${(marketStats.risingCount / marketStats.totalCount) * 100}%`}
|
||||||
|
top="0"
|
||||||
|
h="100%"
|
||||||
|
w={`${(marketStats.flatCount / marketStats.totalCount) * 100}%`}
|
||||||
|
bg="rgba(255,255,255,0.3)"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
{/* 数字统计 */}
|
||||||
|
<HStack justify="space-between" mt={2}>
|
||||||
|
<HStack spacing={1}>
|
||||||
|
<Box w="8px" h="8px" borderRadius="full" bg="#F31260" boxShadow="0 0 8px #F3126060" />
|
||||||
|
<Text fontSize="sm" color="#FF6B9D" fontWeight="bold">{marketStats.risingCount}</Text>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.500">涨</Text>
|
||||||
|
</HStack>
|
||||||
|
<HStack spacing={1}>
|
||||||
|
<Box w="8px" h="8px" borderRadius="full" bg="whiteAlpha.400" />
|
||||||
|
<Text fontSize="sm" color="whiteAlpha.700" fontWeight="bold">{marketStats.flatCount}</Text>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.500">平</Text>
|
||||||
|
</HStack>
|
||||||
|
<HStack spacing={1}>
|
||||||
|
<Box w="8px" h="8px" borderRadius="full" bg="#17C964" boxShadow="0 0 8px #17C96460" />
|
||||||
|
<Text fontSize="sm" color="#17C964" fontWeight="bold">{marketStats.fallingCount}</Text>
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.500">跌</Text>
|
||||||
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
<HStack spacing={1}>
|
</Box>
|
||||||
<Box w="6px" h="6px" borderRadius="full" bg="#52C41A" />
|
|
||||||
<Text fontSize="2xs" color="#52C41A">{marketStats.fallingCount}跌</Text>
|
|
||||||
</HStack>
|
|
||||||
</HStack>
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 紧凑数据卡片
|
* HeroUI 风格紧凑数据卡片
|
||||||
*/
|
*/
|
||||||
const CompactStatCard = ({ label, value, icon, color = '#FFD700', subText }) => (
|
const CompactStatCard = ({ label, value, icon, color = '#7C3AED', subText }) => (
|
||||||
<Box
|
<Box
|
||||||
bg="rgba(0,0,0,0.25)"
|
bg="rgba(255,255,255,0.03)"
|
||||||
borderRadius="md"
|
backdropFilter="blur(10px)"
|
||||||
p={2}
|
borderRadius="xl"
|
||||||
|
p={3}
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="rgba(255,215,0,0.12)"
|
borderColor="rgba(255,255,255,0.06)"
|
||||||
_hover={{ borderColor: 'rgba(255,215,0,0.25)' }}
|
_hover={{
|
||||||
transition="all 0.2s"
|
borderColor: 'rgba(255,255,255,0.12)',
|
||||||
|
bg: 'rgba(255,255,255,0.05)',
|
||||||
|
transform: 'translateY(-2px)',
|
||||||
|
}}
|
||||||
|
transition="all 0.3s ease"
|
||||||
|
position="relative"
|
||||||
|
overflow="hidden"
|
||||||
|
_before={{
|
||||||
|
content: '""',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
w: '60px',
|
||||||
|
h: '60px',
|
||||||
|
background: `radial-gradient(circle, ${color}15 0%, transparent 70%)`,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<HStack spacing={1.5} mb={0.5}>
|
<HStack spacing={2} mb={1}>
|
||||||
<Box color={color} fontSize="xs">
|
<Box
|
||||||
|
color={color}
|
||||||
|
fontSize="sm"
|
||||||
|
p={1.5}
|
||||||
|
borderRadius="lg"
|
||||||
|
bg={`${color}15`}
|
||||||
|
>
|
||||||
{icon}
|
{icon}
|
||||||
</Box>
|
</Box>
|
||||||
<Text fontSize="2xs" color="gray.500" fontWeight="medium">
|
<Text fontSize="xs" color="whiteAlpha.600" fontWeight="medium">
|
||||||
{label}
|
{label}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
<Text fontSize="md" fontWeight="bold" color={color} lineHeight="1.2">
|
<Text fontSize="lg" fontWeight="bold" color={color} lineHeight="1.2" textShadow={`0 0 20px ${color}30`}>
|
||||||
{value}
|
{value}
|
||||||
</Text>
|
</Text>
|
||||||
{subText && (
|
{subText && (
|
||||||
@@ -424,90 +478,137 @@ const EventDailyStats = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
bg="linear-gradient(180deg, rgba(25, 32, 55, 0.95) 0%, rgba(17, 24, 39, 0.98) 100%)"
|
bg="linear-gradient(135deg, rgba(10, 10, 20, 0.9) 0%, rgba(20, 20, 40, 0.95) 50%, rgba(15, 15, 30, 0.9) 100%)"
|
||||||
borderRadius="xl"
|
backdropFilter="blur(20px)"
|
||||||
p={3}
|
borderRadius="2xl"
|
||||||
|
p={4}
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="rgba(255, 215, 0, 0.15)"
|
borderColor="rgba(255, 255, 255, 0.08)"
|
||||||
position="relative"
|
position="relative"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
h="100%"
|
h="100%"
|
||||||
display="flex"
|
display="flex"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
|
boxShadow="0 8px 32px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255,255,255,0.05)"
|
||||||
>
|
>
|
||||||
{/* 背景装饰 */}
|
{/* 背景光效 */}
|
||||||
<Box
|
<Box
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top="-30%"
|
top="-100px"
|
||||||
right="-20%"
|
right="-100px"
|
||||||
w="150px"
|
w="300px"
|
||||||
h="150px"
|
h="300px"
|
||||||
bg="radial-gradient(circle, rgba(255,215,0,0.06) 0%, transparent 70%)"
|
bg="radial-gradient(circle, rgba(124, 58, 237, 0.15) 0%, transparent 60%)"
|
||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
|
filter="blur(40px)"
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
bottom="-80px"
|
||||||
|
left="-80px"
|
||||||
|
w="250px"
|
||||||
|
h="250px"
|
||||||
|
bg="radial-gradient(circle, rgba(6, 182, 212, 0.1) 0%, transparent 60%)"
|
||||||
|
pointerEvents="none"
|
||||||
|
filter="blur(40px)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 标题行 */}
|
{/* 标题行 */}
|
||||||
<Flex justify="space-between" align="center" mb={2}>
|
<Flex justify="space-between" align="center" mb={4}>
|
||||||
<HStack spacing={2}>
|
<HStack spacing={3}>
|
||||||
<Box
|
<Box
|
||||||
w="3px"
|
w="4px"
|
||||||
h="16px"
|
h="20px"
|
||||||
bg="linear-gradient(180deg, #FFD700, #FFA500)"
|
bg="linear-gradient(180deg, #7C3AED, #06B6D4)"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
|
boxShadow="0 0 10px rgba(124, 58, 237, 0.5)"
|
||||||
/>
|
/>
|
||||||
<Text fontSize="sm" fontWeight="bold" color="white" letterSpacing="wide">
|
<Text fontSize="md" fontWeight="bold" color="white" letterSpacing="wide">
|
||||||
{isToday ? '今日统计' : '历史统计'}
|
{isToday ? '今日统计' : '历史统计'}
|
||||||
</Text>
|
</Text>
|
||||||
{isToday && (
|
{isToday && (
|
||||||
<Badge colorScheme="yellow" variant="subtle" fontSize="2xs" px={1.5}>
|
|
||||||
实时
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</HStack>
|
|
||||||
<HStack spacing={1}>
|
|
||||||
{/* 今天按钮 - 仅在查看历史时显示 */}
|
|
||||||
{!isToday && (
|
|
||||||
<Box
|
<Box
|
||||||
px={2}
|
px={2}
|
||||||
py={0.5}
|
py={0.5}
|
||||||
bg="rgba(255,215,0,0.15)"
|
bg="rgba(23, 201, 100, 0.15)"
|
||||||
border="1px solid rgba(255,215,0,0.3)"
|
border="1px solid rgba(23, 201, 100, 0.3)"
|
||||||
borderRadius="md"
|
borderRadius="full"
|
||||||
cursor="pointer"
|
|
||||||
_hover={{ bg: 'rgba(255,215,0,0.25)' }}
|
|
||||||
onClick={() => setSelectedDate('')}
|
|
||||||
>
|
>
|
||||||
<Text fontSize="xs" color="#FFD700" fontWeight="bold">今天</Text>
|
<HStack spacing={1}>
|
||||||
|
<Box
|
||||||
|
w="6px"
|
||||||
|
h="6px"
|
||||||
|
borderRadius="full"
|
||||||
|
bg="#17C964"
|
||||||
|
animation="pulse 2s infinite"
|
||||||
|
boxShadow="0 0 8px #17C964"
|
||||||
|
/>
|
||||||
|
<Text fontSize="xs" color="#17C964" fontWeight="medium">实时</Text>
|
||||||
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<CalendarOutlined style={{ color: '#FFD700', fontSize: '12px' }} />
|
</HStack>
|
||||||
<Input
|
<HStack spacing={2}>
|
||||||
type="date"
|
{/* 今天按钮 - 仅在查看历史时显示 */}
|
||||||
size="xs"
|
{!isToday && (
|
||||||
value={selectedDate}
|
<Box
|
||||||
onChange={handleDateChange}
|
px={3}
|
||||||
max={new Date().toISOString().split('T')[0]}
|
py={1}
|
||||||
bg="rgba(0,0,0,0.3)"
|
bg="rgba(124, 58, 237, 0.15)"
|
||||||
border="1px solid rgba(255,215,0,0.2)"
|
border="1px solid rgba(124, 58, 237, 0.3)"
|
||||||
borderRadius="md"
|
borderRadius="lg"
|
||||||
color="white"
|
cursor="pointer"
|
||||||
fontSize="xs"
|
_hover={{ bg: 'rgba(124, 58, 237, 0.25)', transform: 'scale(1.02)' }}
|
||||||
w="110px"
|
transition="all 0.2s"
|
||||||
h="24px"
|
onClick={() => setSelectedDate('')}
|
||||||
_hover={{ borderColor: 'rgba(255,215,0,0.4)' }}
|
>
|
||||||
_focus={{ borderColor: '#FFD700', boxShadow: 'none' }}
|
<Text fontSize="xs" color="#A78BFA" fontWeight="bold">返回今天</Text>
|
||||||
css={{
|
</Box>
|
||||||
'&::-webkit-calendar-picker-indicator': {
|
)}
|
||||||
filter: 'invert(1)',
|
<Box
|
||||||
cursor: 'pointer',
|
as="label"
|
||||||
},
|
display="flex"
|
||||||
}}
|
alignItems="center"
|
||||||
/>
|
gap={2}
|
||||||
|
px={3}
|
||||||
|
py={1.5}
|
||||||
|
bg="rgba(255,255,255,0.03)"
|
||||||
|
border="1px solid rgba(255,255,255,0.08)"
|
||||||
|
borderRadius="lg"
|
||||||
|
cursor="pointer"
|
||||||
|
_hover={{ bg: 'rgba(255,255,255,0.06)', borderColor: 'rgba(255,255,255,0.12)' }}
|
||||||
|
transition="all 0.2s"
|
||||||
|
>
|
||||||
|
<CalendarOutlined style={{ color: 'rgba(255,255,255,0.6)', fontSize: '14px' }} />
|
||||||
|
<Input
|
||||||
|
type="date"
|
||||||
|
size="xs"
|
||||||
|
value={selectedDate}
|
||||||
|
onChange={handleDateChange}
|
||||||
|
max={new Date().toISOString().split('T')[0]}
|
||||||
|
bg="transparent"
|
||||||
|
border="none"
|
||||||
|
color="whiteAlpha.800"
|
||||||
|
fontSize="xs"
|
||||||
|
w="100px"
|
||||||
|
h="20px"
|
||||||
|
p={0}
|
||||||
|
_hover={{ border: 'none' }}
|
||||||
|
_focus={{ border: 'none', boxShadow: 'none' }}
|
||||||
|
css={{
|
||||||
|
'&::-webkit-calendar-picker-indicator': {
|
||||||
|
filter: 'invert(0.8)',
|
||||||
|
cursor: 'pointer',
|
||||||
|
opacity: 0.6,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* 内容区域 - 使用 flex: 1 填充剩余空间 */}
|
{/* 内容区域 - 使用 flex: 1 填充剩余空间 */}
|
||||||
<VStack spacing={2} align="stretch" flex="1">
|
<VStack spacing={4} align="stretch" flex="1">
|
||||||
{/* 胜率对比仪表盘 */}
|
{/* 胜率对比仪表盘 */}
|
||||||
<WinRateGauge
|
<WinRateGauge
|
||||||
eventRate={summary?.positiveRate || 0}
|
eventRate={summary?.positiveRate || 0}
|
||||||
|
|||||||
@@ -2537,41 +2537,77 @@ const CombinedCalendar = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 右侧 Tab 面板 - 连板情绪监测 / 综合日历
|
* 右侧 Tab 面板 - HeroUI 风格毛玻璃
|
||||||
*/
|
*/
|
||||||
const RightPanelTabs = () => {
|
const RightPanelTabs = () => {
|
||||||
const [activeTab, setActiveTab] = useState('comet');
|
// 默认显示日历
|
||||||
|
const [activeTab, setActiveTab] = useState('calendar');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
bg="linear-gradient(180deg, rgba(25, 32, 55, 0.95) 0%, rgba(17, 24, 39, 0.98) 100%)"
|
bg="linear-gradient(135deg, rgba(10, 10, 20, 0.9) 0%, rgba(20, 20, 40, 0.95) 50%, rgba(15, 15, 30, 0.9) 100%)"
|
||||||
borderRadius="xl"
|
backdropFilter="blur(20px)"
|
||||||
|
borderRadius="2xl"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="rgba(255, 215, 0, 0.15)"
|
borderColor="rgba(255, 255, 255, 0.08)"
|
||||||
h="100%"
|
h="100%"
|
||||||
display="flex"
|
display="flex"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
|
boxShadow="0 8px 32px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255,255,255,0.05)"
|
||||||
|
position="relative"
|
||||||
>
|
>
|
||||||
|
{/* 背景光效 */}
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top="-50px"
|
||||||
|
left="-50px"
|
||||||
|
w="200px"
|
||||||
|
h="200px"
|
||||||
|
bg="radial-gradient(circle, rgba(6, 182, 212, 0.1) 0%, transparent 60%)"
|
||||||
|
pointerEvents="none"
|
||||||
|
filter="blur(40px)"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Tab 切换头 */}
|
{/* Tab 切换头 */}
|
||||||
<HStack
|
<HStack
|
||||||
px={4}
|
px={4}
|
||||||
py={2}
|
py={3}
|
||||||
borderBottom="1px solid rgba(255,215,0,0.1)"
|
borderBottom="1px solid rgba(255,255,255,0.06)"
|
||||||
bg="rgba(0,0,0,0.2)"
|
bg="rgba(0,0,0,0.2)"
|
||||||
spacing={0}
|
spacing={2}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
px={4}
|
px={4}
|
||||||
py={2}
|
py={2}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
borderRadius="md"
|
borderRadius="xl"
|
||||||
bg={activeTab === 'comet' ? 'rgba(255,215,0,0.15)' : 'transparent'}
|
bg={activeTab === 'calendar' ? 'rgba(124, 58, 237, 0.2)' : 'transparent'}
|
||||||
color={activeTab === 'comet' ? '#FFD700' : 'gray.400'}
|
color={activeTab === 'calendar' ? '#A78BFA' : 'whiteAlpha.500'}
|
||||||
|
fontWeight={activeTab === 'calendar' ? 'bold' : 'normal'}
|
||||||
|
fontSize="sm"
|
||||||
|
transition="all 0.3s ease"
|
||||||
|
border={activeTab === 'calendar' ? '1px solid rgba(124, 58, 237, 0.3)' : '1px solid transparent'}
|
||||||
|
_hover={{ color: '#A78BFA', bg: 'rgba(124, 58, 237, 0.1)' }}
|
||||||
|
onClick={() => setActiveTab('calendar')}
|
||||||
|
>
|
||||||
|
<HStack spacing={2}>
|
||||||
|
<CalendarOutlined />
|
||||||
|
<Text>涨停与未来日历</Text>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
px={4}
|
||||||
|
py={2}
|
||||||
|
cursor="pointer"
|
||||||
|
borderRadius="xl"
|
||||||
|
bg={activeTab === 'comet' ? 'rgba(6, 182, 212, 0.2)' : 'transparent'}
|
||||||
|
color={activeTab === 'comet' ? '#22D3EE' : 'whiteAlpha.500'}
|
||||||
fontWeight={activeTab === 'comet' ? 'bold' : 'normal'}
|
fontWeight={activeTab === 'comet' ? 'bold' : 'normal'}
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
transition="all 0.2s"
|
transition="all 0.3s ease"
|
||||||
_hover={{ color: '#FFD700', bg: 'rgba(255,215,0,0.08)' }}
|
border={activeTab === 'comet' ? '1px solid rgba(6, 182, 212, 0.3)' : '1px solid transparent'}
|
||||||
|
_hover={{ color: '#22D3EE', bg: 'rgba(6, 182, 212, 0.1)' }}
|
||||||
onClick={() => setActiveTab('comet')}
|
onClick={() => setActiveTab('comet')}
|
||||||
>
|
>
|
||||||
<HStack spacing={2}>
|
<HStack spacing={2}>
|
||||||
@@ -2579,32 +2615,18 @@ const RightPanelTabs = () => {
|
|||||||
<Text>连板情绪监测</Text>
|
<Text>连板情绪监测</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
|
||||||
px={4}
|
|
||||||
py={2}
|
|
||||||
cursor="pointer"
|
|
||||||
borderRadius="md"
|
|
||||||
bg={activeTab === 'calendar' ? 'rgba(255,215,0,0.15)' : 'transparent'}
|
|
||||||
color={activeTab === 'calendar' ? '#FFD700' : 'gray.400'}
|
|
||||||
fontWeight={activeTab === 'calendar' ? 'bold' : 'normal'}
|
|
||||||
fontSize="sm"
|
|
||||||
transition="all 0.2s"
|
|
||||||
_hover={{ color: '#FFD700', bg: 'rgba(255,215,0,0.08)' }}
|
|
||||||
onClick={() => setActiveTab('calendar')}
|
|
||||||
>
|
|
||||||
<HStack spacing={2}>
|
|
||||||
<CalendarOutlined />
|
|
||||||
<Text>事件日历</Text>
|
|
||||||
</HStack>
|
|
||||||
</Box>
|
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{/* Tab 内容区域 */}
|
{/* Tab 内容区域 - 固定高度确保一致 */}
|
||||||
<Box flex="1" minH={0} p={3}>
|
<Box flex="1" minH="650px" p={3} overflow="hidden">
|
||||||
{activeTab === 'comet' ? (
|
{activeTab === 'comet' ? (
|
||||||
<ThemeCometChart />
|
<Box h="100%">
|
||||||
|
<ThemeCometChart />
|
||||||
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<CombinedCalendar />
|
<Box h="100%">
|
||||||
|
<CombinedCalendar />
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user