更新Company页面的UI为FUI风格

This commit is contained in:
2025-12-17 19:20:10 +08:00
parent 7054124eaf
commit 7b5ac2ef15
5 changed files with 475 additions and 85 deletions

View File

@@ -1,4 +1,4 @@
// 指标卡片组件 // 指标卡片组件 - FUI 科幻风格
import React from 'react'; import React from 'react';
import { Box, VStack } from '@chakra-ui/react'; import { Box, VStack } from '@chakra-ui/react';
import { DarkGoldCard, CardTitle, MetricValue } from './atoms'; import { DarkGoldCard, CardTitle, MetricValue } from './atoms';
@@ -17,7 +17,13 @@ export interface MetricCardProps {
} }
/** /**
* 指标卡片组件 - 用于展示单个指标数据 * 指标卡片组件 - FUI 科幻风格
*
* 特点:
* - Glassmorphism 卡片
* - 角落装饰
* - 发光数值
* - 环境光效果
*/ */
const MetricCard: React.FC<MetricCardProps> = ({ const MetricCard: React.FC<MetricCardProps> = ({
title, title,
@@ -29,28 +35,94 @@ const MetricCard: React.FC<MetricCardProps> = ({
mainColor, mainColor,
mainSuffix, mainSuffix,
subText, subText,
}) => ( }) => {
<DarkGoldCard> // 根据数值颜色生成环境光
<CardTitle const getAmbientColor = (color: string) => {
title={title} if (color.includes('red') || color === '#EF4444' || color === darkGoldTheme.priceUp) {
subtitle={subtitle} return 'rgba(239, 68, 68, 0.15)';
leftIcon={leftIcon} }
rightIcon={rightIcon} if (color.includes('green') || color === '#22C55E' || color === darkGoldTheme.priceDown) {
/> return 'rgba(34, 197, 94, 0.15)';
}
return 'rgba(212, 175, 55, 0.1)';
};
<VStack align="start" spacing={0.5} mb={2}> const ambientColor = getAmbientColor(mainColor);
<MetricValue
label={mainLabel} return (
value={mainValue} <DarkGoldCard cornerDecor={true} position="relative" overflow="hidden">
color={mainColor} {/* James Turrell 环境光效果 */}
suffix={mainSuffix} <Box
position="absolute"
top="-30%"
left="-20%"
w="80%"
h="100%"
borderRadius="full"
bg={ambientColor}
filter="blur(30px)"
opacity={0.6}
pointerEvents="none"
/> />
</VStack>
<Box color={darkGoldTheme.textMuted} fontSize="xs"> {/* 数据脉冲动画装饰 */}
{subText} <Box
</Box> position="absolute"
</DarkGoldCard> top="50%"
); right="10px"
w="3px"
h="40%"
transform="translateY(-50%)"
bg={`linear-gradient(180deg, transparent, ${mainColor}40, transparent)`}
sx={{ animation: 'dataFlow 3s ease-in-out infinite' }}
/>
{/* 卡片标题 */}
<Box position="relative" zIndex={1}>
<CardTitle
title={title}
subtitle={subtitle}
leftIcon={leftIcon}
rightIcon={rightIcon}
/>
</Box>
{/* 主数值区域 */}
<VStack align="start" spacing={0.5} mb={2} position="relative" zIndex={1}>
<MetricValue
label={mainLabel}
value={mainValue}
color={mainColor}
suffix={mainSuffix}
glowing={true}
/>
</VStack>
{/* 辅助信息 */}
<Box
color={darkGoldTheme.textMuted}
fontSize="xs"
position="relative"
zIndex={1}
p={2}
bg="rgba(0, 0, 0, 0.2)"
borderRadius="md"
border="1px solid rgba(212, 175, 55, 0.1)"
>
{subText}
</Box>
{/* 底部渐变线 */}
<Box
position="absolute"
bottom={0}
left="5%"
right="5%"
h="1px"
bg={`linear-gradient(90deg, transparent, ${mainColor}30, transparent)`}
/>
</DarkGoldCard>
);
};
export default MetricCard; export default MetricCard;

View File

@@ -1,7 +1,7 @@
// 股票信息卡片组件4列布局版本 // 股票信息卡片组件4列布局版本- FUI 科幻风格
import React from 'react'; import React from 'react';
import { Box, HStack, Text, Icon } from '@chakra-ui/react'; import { Box, HStack, VStack, Text, Icon, Badge } from '@chakra-ui/react';
import { TrendingUp, TrendingDown } from 'lucide-react'; import { TrendingUp, TrendingDown, Activity } from 'lucide-react';
import { DarkGoldCard } from './atoms'; import { DarkGoldCard } from './atoms';
import { getTrendDescription, getPriceColor } from './utils'; import { getTrendDescription, getPriceColor } from './utils';
import { darkGoldTheme } from '../../constants'; import { darkGoldTheme } from '../../constants';
@@ -14,7 +14,13 @@ export interface StockHeaderCardProps {
} }
/** /**
* 股票信息卡片 - 4 列布局中的第一个卡片 * 股票信息卡片 - FUI 科幻风格
*
* 设计特点:
* - Glassmorphism 毛玻璃效果
* - 价格发光效果
* - James Turrell 环境光
* - 角落装饰
*/ */
const StockHeaderCard: React.FC<StockHeaderCardProps> = ({ const StockHeaderCard: React.FC<StockHeaderCardProps> = ({
stockName, stockName,
@@ -26,63 +32,176 @@ const StockHeaderCard: React.FC<StockHeaderCardProps> = ({
const priceColor = getPriceColor(changePercent); const priceColor = getPriceColor(changePercent);
const trendDesc = getTrendDescription(changePercent); const trendDesc = getTrendDescription(changePercent);
// 根据涨跌生成发光颜色
const glowColor = isUp
? 'rgba(239, 68, 68, 0.4)'
: 'rgba(34, 197, 94, 0.4)';
return ( return (
<DarkGoldCard position="relative" overflow="hidden"> <DarkGoldCard
{/* 背景装饰线 */} position="relative"
overflow="hidden"
cornerDecor={true}
_hover={{
'& .price-glow': {
opacity: 1,
},
}}
>
{/* 背景装饰线 - 增强版 */}
<Box <Box
position="absolute" position="absolute"
right={0} right={0}
top={0} top={0}
width="60%" width="60%"
height="100%" height="100%"
opacity={0.12} opacity={0.15}
background={`linear-gradient(135deg, transparent 30%, ${priceColor})`} background={`linear-gradient(135deg, transparent 30%, ${priceColor})`}
clipPath="polygon(40% 0, 100% 0, 100% 100%, 20% 100%)" clipPath="polygon(40% 0, 100% 0, 100% 100%, 20% 100%)"
/> />
{/* James Turrell 环境光效果 */}
<Box
position="absolute"
top="-20%"
right="-10%"
w="50%"
h="80%"
borderRadius="full"
bg={glowColor}
filter="blur(40px)"
opacity={0.3}
pointerEvents="none"
/>
{/* 数据扫描线动画 */}
<Box
position="absolute"
top={0}
left={0}
right={0}
h="2px"
bg="linear-gradient(90deg, transparent 0%, rgba(212, 175, 55, 0.6) 50%, transparent 100%)"
sx={{ animation: 'scanline 4s ease-in-out infinite' }}
/>
{/* 股票名称和代码 */} {/* 股票名称和代码 */}
<HStack spacing={1.5} mb={2}> <HStack spacing={2} mb={2} position="relative" zIndex={1}>
{/* 状态指示器 */}
<Box
w="6px"
h="6px"
borderRadius="full"
bg={priceColor}
boxShadow={`0 0 8px ${priceColor}`}
sx={{ animation: 'pulse 2s ease-in-out infinite' }}
/>
<Text <Text
color={darkGoldTheme.textPrimary} color={darkGoldTheme.textPrimary}
fontSize="md" fontSize="md"
fontWeight="bold" fontWeight="bold"
letterSpacing="wide"
> >
{stockName} {stockName}
</Text> </Text>
<Text color={darkGoldTheme.textMuted} fontSize="xs"> <Badge
({stockCode}) bg="rgba(212, 175, 55, 0.15)"
</Text> color="rgba(212, 175, 55, 0.9)"
fontSize="2xs"
px={1.5}
py={0.5}
borderRadius="md"
border="1px solid rgba(212, 175, 55, 0.3)"
fontFamily="mono"
>
{stockCode}
</Badge>
</HStack> </HStack>
{/* 价格和涨跌幅 */} {/* 价格和涨跌幅 */}
<HStack spacing={2} align="baseline" mb={1.5}> <HStack spacing={3} align="baseline" mb={2} position="relative" zIndex={1}>
<Text {/* 价格发光效果 */}
color={priceColor} <Box position="relative">
fontSize="2xl" <Text
fontWeight="bold" className="price-glow"
lineHeight="1" position="absolute"
color={priceColor}
fontSize="2xl"
fontWeight="bold"
lineHeight="1"
fontFamily="mono"
filter={`blur(8px)`}
opacity={0.6}
transition="opacity 0.3s"
>
{price.toFixed(2)}
</Text>
<Text
color={priceColor}
fontSize="2xl"
fontWeight="bold"
lineHeight="1"
fontFamily="mono"
textShadow={`0 0 20px ${glowColor}`}
>
{price.toFixed(2)}
</Text>
</Box>
{/* 涨跌幅徽章 - FUI 风格 */}
<Box
display="inline-flex"
alignItems="center"
gap={1}
px={2}
py={0.5}
borderRadius="md"
bg={isUp ? 'rgba(239, 68, 68, 0.15)' : 'rgba(34, 197, 94, 0.15)'}
border="1px solid"
borderColor={isUp ? 'rgba(239, 68, 68, 0.4)' : 'rgba(34, 197, 94, 0.4)'}
boxShadow={`0 0 12px ${glowColor}`}
> >
{price.toFixed(2)}
</Text>
<HStack spacing={0.5} align="center">
<Icon <Icon
as={isUp ? TrendingUp : TrendingDown} as={isUp ? TrendingUp : TrendingDown}
color={priceColor} color={priceColor}
boxSize={3} boxSize={3}
/> />
<Text color={priceColor} fontSize="sm" fontWeight="bold"> <Text
color={priceColor}
fontSize="sm"
fontWeight="bold"
fontFamily="mono"
>
{isUp ? '+' : ''}{changePercent.toFixed(2)}% {isUp ? '+' : ''}{changePercent.toFixed(2)}%
</Text> </Text>
</HStack> </Box>
</HStack> </HStack>
{/* 走势简述 */} {/* 走势简述 - FUI 标签风格 */}
<Text color={darkGoldTheme.textMuted} fontSize="xs"> <HStack spacing={2} position="relative" zIndex={1}>
<Icon as={Activity} color={darkGoldTheme.textMuted} boxSize={3} />
<Text as="span" color={priceColor} fontWeight="medium"> <Text color={darkGoldTheme.textMuted} fontSize="xs">
{trendDesc}
<Text
as="span"
color={priceColor}
fontWeight="semibold"
textShadow={`0 0 8px ${glowColor}`}
>
{trendDesc}
</Text>
</Text> </Text>
</Text> </HStack>
{/* 底部数据线 */}
<Box
position="absolute"
bottom={0}
left="10%"
right="10%"
h="1px"
bg={`linear-gradient(90deg, transparent, ${priceColor}40, transparent)`}
/>
</DarkGoldCard> </DarkGoldCard>
); );
}; };

View File

@@ -1,6 +1,6 @@
// 卡片标题原子组件 // 卡片标题原子组件 - FUI 科幻风格
import React from 'react'; import React from 'react';
import { Flex, HStack, Box, Text } from '@chakra-ui/react'; import { Flex, HStack, Box, Text, Badge } from '@chakra-ui/react';
import { darkGoldTheme } from '../../../constants'; import { darkGoldTheme } from '../../../constants';
interface CardTitleProps { interface CardTitleProps {
@@ -11,7 +11,13 @@ interface CardTitleProps {
} }
/** /**
* 卡片标题组件 - 显示图标+标题+副标题 * 卡片标题组件 - FUI 风格
*
* 特点:
* - 图标发光效果
* - 标题发光文字
* - 副标题徽章样式
* - 装饰性分割线
*/ */
const CardTitle: React.FC<CardTitleProps> = ({ const CardTitle: React.FC<CardTitleProps> = ({
title, title,
@@ -19,17 +25,73 @@ const CardTitle: React.FC<CardTitleProps> = ({
leftIcon, leftIcon,
rightIcon, rightIcon,
}) => ( }) => (
<Flex justify="space-between" align="center" mb={2}> <Flex justify="space-between" align="center" mb={3} position="relative">
<HStack spacing={1.5}> <HStack spacing={2}>
<Box color={darkGoldTheme.gold}>{leftIcon}</Box> {/* 图标容器 - 发光效果 */}
<Text color={darkGoldTheme.gold} fontSize="sm" fontWeight="bold"> <Box
color={darkGoldTheme.gold}
position="relative"
sx={{
'& > *': {
filter: 'drop-shadow(0 0 4px rgba(212, 175, 55, 0.6))',
},
}}
>
{leftIcon}
</Box>
{/* 标题 - 发光文字 */}
<Text
color={darkGoldTheme.gold}
fontSize="sm"
fontWeight="bold"
letterSpacing="wide"
textShadow="0 0 12px rgba(212, 175, 55, 0.4)"
>
{title} {title}
</Text> </Text>
<Text color={darkGoldTheme.textMuted} fontSize="xs">
({subtitle}) {/* 副标题 - 徽章风格 */}
</Text> <Badge
bg="rgba(212, 175, 55, 0.1)"
color={darkGoldTheme.textMuted}
fontSize="2xs"
px={1.5}
py={0.5}
borderRadius="sm"
border="1px solid rgba(212, 175, 55, 0.2)"
fontWeight="normal"
>
{subtitle}
</Badge>
</HStack> </HStack>
{rightIcon && <Box color={darkGoldTheme.gold}>{rightIcon}</Box>}
{/* 右侧图标 - 发光效果 */}
{rightIcon && (
<Box
color={darkGoldTheme.gold}
opacity={0.8}
transition="all 0.3s"
_hover={{ opacity: 1, transform: 'scale(1.1)' }}
sx={{
'& > *': {
filter: 'drop-shadow(0 0 4px rgba(212, 175, 55, 0.4))',
},
}}
>
{rightIcon}
</Box>
)}
{/* 底部装饰线 */}
<Box
position="absolute"
bottom="-6px"
left={0}
right={0}
h="1px"
bg="linear-gradient(90deg, rgba(212, 175, 55, 0.4) 0%, rgba(212, 175, 55, 0.1) 50%, transparent 100%)"
/>
</Flex> </Flex>
); );

View File

@@ -1,4 +1,4 @@
// 黑金主题卡片容器原子组件 // 黑金主题卡片容器原子组件 - FUI 科幻风格
import React from 'react'; import React from 'react';
import { Box, BoxProps } from '@chakra-ui/react'; import { Box, BoxProps } from '@chakra-ui/react';
import { darkGoldTheme } from '../../../constants'; import { darkGoldTheme } from '../../../constants';
@@ -6,36 +6,113 @@ import { darkGoldTheme } from '../../../constants';
interface DarkGoldCardProps extends BoxProps { interface DarkGoldCardProps extends BoxProps {
children: React.ReactNode; children: React.ReactNode;
hoverable?: boolean; hoverable?: boolean;
/** 是否显示角落装饰 */
cornerDecor?: boolean;
/** 是否显示发光效果 */
glowing?: boolean;
} }
/** /**
* 黑金主题卡片容器 * 黑金主题卡片容器 - FUI 风格
*
* 特点:
* - Glassmorphism 毛玻璃效果
* - 悬停发光动画
* - 可选角落装饰
*/ */
const DarkGoldCard: React.FC<DarkGoldCardProps> = ({ const DarkGoldCard: React.FC<DarkGoldCardProps> = ({
children, children,
hoverable = true, hoverable = true,
cornerDecor = false,
glowing = false,
...props ...props
}) => ( }) => (
<Box <Box
bg={darkGoldTheme.bgCard} position="relative"
borderRadius="lg" bg="linear-gradient(145deg, rgba(26, 26, 46, 0.9) 0%, rgba(15, 15, 26, 0.95) 100%)"
backdropFilter="blur(12px)"
borderRadius="12px"
border="1px solid" border="1px solid"
borderColor={darkGoldTheme.border} borderColor="rgba(212, 175, 55, 0.2)"
p={3} p={3}
transition="all 0.3s ease" overflow="hidden"
transition="all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
boxShadow={glowing
? '0 0 20px rgba(212, 175, 55, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.05)'
: 'inset 0 1px 0 rgba(255, 255, 255, 0.05)'
}
_hover={ _hover={
hoverable hoverable
? { ? {
bg: darkGoldTheme.bgCardHover, borderColor: 'rgba(212, 175, 55, 0.4)',
borderColor: darkGoldTheme.borderHover, transform: 'translateY(-2px)',
transform: 'translateY(-1px)', boxShadow: '0 8px 32px rgba(0, 0, 0, 0.4), 0 0 20px rgba(212, 175, 55, 0.2)',
boxShadow: '0 4px 16px rgba(0, 0, 0, 0.4)',
} }
: undefined : undefined
} }
sx={glowing ? { animation: 'glowPulse 3s ease-in-out infinite' } : undefined}
{...props} {...props}
> >
{children} {/* 角落装饰 */}
{cornerDecor && (
<>
<Box
position="absolute"
top="6px"
left="6px"
w="10px"
h="10px"
borderTop="1.5px solid"
borderLeft="1.5px solid"
borderColor="rgba(212, 175, 55, 0.5)"
/>
<Box
position="absolute"
top="6px"
right="6px"
w="10px"
h="10px"
borderTop="1.5px solid"
borderRight="1.5px solid"
borderColor="rgba(212, 175, 55, 0.5)"
/>
<Box
position="absolute"
bottom="6px"
left="6px"
w="10px"
h="10px"
borderBottom="1.5px solid"
borderLeft="1.5px solid"
borderColor="rgba(212, 175, 55, 0.5)"
/>
<Box
position="absolute"
bottom="6px"
right="6px"
w="10px"
h="10px"
borderBottom="1.5px solid"
borderRight="1.5px solid"
borderColor="rgba(212, 175, 55, 0.5)"
/>
</>
)}
{/* 顶部光线 */}
<Box
position="absolute"
top={0}
left="20%"
right="20%"
h="1px"
bg="linear-gradient(90deg, transparent, rgba(212, 175, 55, 0.3), transparent)"
/>
{/* 内容 */}
<Box position="relative" zIndex={1}>
{children}
</Box>
</Box> </Box>
); );

View File

@@ -1,6 +1,6 @@
// 核心数值展示原子组件 // 核心数值展示原子组件 - FUI 科幻风格
import React from 'react'; import React from 'react';
import { HStack, Text } from '@chakra-ui/react'; import { Box, HStack, Text } from '@chakra-ui/react';
import { darkGoldTheme } from '../../../constants'; import { darkGoldTheme } from '../../../constants';
interface MetricValueProps { interface MetricValueProps {
@@ -9,6 +9,8 @@ interface MetricValueProps {
color: string; color: string;
suffix?: string; suffix?: string;
size?: 'sm' | 'md' | 'lg'; size?: 'sm' | 'md' | 'lg';
/** 是否启用发光效果 */
glowing?: boolean;
} }
const sizeMap = { const sizeMap = {
@@ -18,7 +20,12 @@ const sizeMap = {
}; };
/** /**
* 核心数值展示组件 - 显示标签+数值 * 核心数值展示组件 - FUI 风格
*
* 特点:
* - 发光数值效果
* - 等宽字体显示
* - 悬停增强效果
*/ */
const MetricValue: React.FC<MetricValueProps> = ({ const MetricValue: React.FC<MetricValueProps> = ({
label, label,
@@ -26,24 +33,77 @@ const MetricValue: React.FC<MetricValueProps> = ({
color, color,
suffix, suffix,
size = 'lg', size = 'lg',
glowing = true,
}) => { }) => {
const sizes = sizeMap[size]; const sizes = sizeMap[size];
// 生成发光颜色(从传入的颜色中提取或使用默认)
const getGlowColor = (c: string) => {
if (c.includes('red') || c === '#EF4444' || c === darkGoldTheme.priceUp) {
return 'rgba(239, 68, 68, 0.5)';
}
if (c.includes('green') || c === '#22C55E' || c === darkGoldTheme.priceDown) {
return 'rgba(34, 197, 94, 0.5)';
}
return 'rgba(212, 175, 55, 0.5)';
};
const glowColor = getGlowColor(color);
return ( return (
<HStack spacing={2} align="baseline"> <HStack spacing={2} align="baseline">
<Text color={darkGoldTheme.textMuted} fontSize={sizes.label}> {/* 标签 - 添加微妙动画 */}
<Text
color={darkGoldTheme.textMuted}
fontSize={sizes.label}
letterSpacing="wider"
textTransform="uppercase"
>
{label} {label}
</Text> </Text>
<Text
color={color} {/* 数值 - FUI 发光效果 */}
fontSize={sizes.value} <Box position="relative" display="inline-flex" alignItems="baseline">
fontWeight="bold" {/* 发光层 */}
lineHeight="1" {glowing && (
> <Text
{value} position="absolute"
</Text> color={color}
fontSize={sizes.value}
fontWeight="bold"
lineHeight="1"
fontFamily="mono"
filter="blur(6px)"
opacity={0.5}
aria-hidden="true"
>
{value}
</Text>
)}
{/* 主数值 */}
<Text
color={color}
fontSize={sizes.value}
fontWeight="bold"
lineHeight="1"
fontFamily="mono"
textShadow={glowing ? `0 0 16px ${glowColor}` : undefined}
transition="text-shadow 0.3s ease"
_hover={glowing ? { textShadow: `0 0 24px ${glowColor}, 0 0 48px ${glowColor}` } : undefined}
>
{value}
</Text>
</Box>
{/* 后缀 */}
{suffix && ( {suffix && (
<Text color={color} fontSize={sizes.suffix} fontWeight="bold"> <Text
color={color}
fontSize={sizes.suffix}
fontWeight="bold"
fontFamily="mono"
opacity={0.9}
>
{suffix} {suffix}
</Text> </Text>
)} )}