更新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 { Box, VStack } from '@chakra-ui/react';
import { DarkGoldCard, CardTitle, MetricValue } from './atoms';
@@ -17,7 +17,13 @@ export interface MetricCardProps {
}
/**
* 指标卡片组件 - 用于展示单个指标数据
* 指标卡片组件 - FUI 科幻风格
*
* 特点:
* - Glassmorphism 卡片
* - 角落装饰
* - 发光数值
* - 环境光效果
*/
const MetricCard: React.FC<MetricCardProps> = ({
title,
@@ -29,28 +35,94 @@ const MetricCard: React.FC<MetricCardProps> = ({
mainColor,
mainSuffix,
subText,
}) => (
<DarkGoldCard>
}) => {
// 根据数值颜色生成环境光
const getAmbientColor = (color: string) => {
if (color.includes('red') || color === '#EF4444' || color === darkGoldTheme.priceUp) {
return 'rgba(239, 68, 68, 0.15)';
}
if (color.includes('green') || color === '#22C55E' || color === darkGoldTheme.priceDown) {
return 'rgba(34, 197, 94, 0.15)';
}
return 'rgba(212, 175, 55, 0.1)';
};
const ambientColor = getAmbientColor(mainColor);
return (
<DarkGoldCard cornerDecor={true} position="relative" overflow="hidden">
{/* James Turrell 环境光效果 */}
<Box
position="absolute"
top="-30%"
left="-20%"
w="80%"
h="100%"
borderRadius="full"
bg={ambientColor}
filter="blur(30px)"
opacity={0.6}
pointerEvents="none"
/>
{/* 数据脉冲动画装饰 */}
<Box
position="absolute"
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}>
{/* 主数值区域 */}
<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">
{/* 辅助信息 */}
<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;

View File

@@ -1,7 +1,7 @@
// 股票信息卡片组件4列布局版本
// 股票信息卡片组件4列布局版本- FUI 科幻风格
import React from 'react';
import { Box, HStack, Text, Icon } from '@chakra-ui/react';
import { TrendingUp, TrendingDown } from 'lucide-react';
import { Box, HStack, VStack, Text, Icon, Badge } from '@chakra-ui/react';
import { TrendingUp, TrendingDown, Activity } from 'lucide-react';
import { DarkGoldCard } from './atoms';
import { getTrendDescription, getPriceColor } from './utils';
import { darkGoldTheme } from '../../constants';
@@ -14,7 +14,13 @@ export interface StockHeaderCardProps {
}
/**
* 股票信息卡片 - 4 列布局中的第一个卡片
* 股票信息卡片 - FUI 科幻风格
*
* 设计特点:
* - Glassmorphism 毛玻璃效果
* - 价格发光效果
* - James Turrell 环境光
* - 角落装饰
*/
const StockHeaderCard: React.FC<StockHeaderCardProps> = ({
stockName,
@@ -26,63 +32,176 @@ const StockHeaderCard: React.FC<StockHeaderCardProps> = ({
const priceColor = getPriceColor(changePercent);
const trendDesc = getTrendDescription(changePercent);
// 根据涨跌生成发光颜色
const glowColor = isUp
? 'rgba(239, 68, 68, 0.4)'
: 'rgba(34, 197, 94, 0.4)';
return (
<DarkGoldCard position="relative" overflow="hidden">
{/* 背景装饰线 */}
<DarkGoldCard
position="relative"
overflow="hidden"
cornerDecor={true}
_hover={{
'& .price-glow': {
opacity: 1,
},
}}
>
{/* 背景装饰线 - 增强版 */}
<Box
position="absolute"
right={0}
top={0}
width="60%"
height="100%"
opacity={0.12}
opacity={0.15}
background={`linear-gradient(135deg, transparent 30%, ${priceColor})`}
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
color={darkGoldTheme.textPrimary}
fontSize="md"
fontWeight="bold"
letterSpacing="wide"
>
{stockName}
</Text>
<Text color={darkGoldTheme.textMuted} fontSize="xs">
({stockCode})
</Text>
<Badge
bg="rgba(212, 175, 55, 0.15)"
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 spacing={2} align="baseline" mb={1.5}>
<HStack spacing={3} align="baseline" mb={2} position="relative" zIndex={1}>
{/* 价格发光效果 */}
<Box position="relative">
<Text
className="price-glow"
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>
<HStack spacing={0.5} align="center">
</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}`}
>
<Icon
as={isUp ? TrendingUp : TrendingDown}
color={priceColor}
boxSize={3}
/>
<Text color={priceColor} fontSize="sm" fontWeight="bold">
<Text
color={priceColor}
fontSize="sm"
fontWeight="bold"
fontFamily="mono"
>
{isUp ? '+' : ''}{changePercent.toFixed(2)}%
</Text>
</HStack>
</Box>
</HStack>
{/* 走势简述 */}
{/* 走势简述 - FUI 标签风格 */}
<HStack spacing={2} position="relative" zIndex={1}>
<Icon as={Activity} color={darkGoldTheme.textMuted} boxSize={3} />
<Text color={darkGoldTheme.textMuted} fontSize="xs">
<Text as="span" color={priceColor} fontWeight="medium">
<Text
as="span"
color={priceColor}
fontWeight="semibold"
textShadow={`0 0 8px ${glowColor}`}
>
{trendDesc}
</Text>
</Text>
</HStack>
{/* 底部数据线 */}
<Box
position="absolute"
bottom={0}
left="10%"
right="10%"
h="1px"
bg={`linear-gradient(90deg, transparent, ${priceColor}40, transparent)`}
/>
</DarkGoldCard>
);
};

View File

@@ -1,6 +1,6 @@
// 卡片标题原子组件
// 卡片标题原子组件 - FUI 科幻风格
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';
interface CardTitleProps {
@@ -11,7 +11,13 @@ interface CardTitleProps {
}
/**
* 卡片标题组件 - 显示图标+标题+副标题
* 卡片标题组件 - FUI 风格
*
* 特点:
* - 图标发光效果
* - 标题发光文字
* - 副标题徽章样式
* - 装饰性分割线
*/
const CardTitle: React.FC<CardTitleProps> = ({
title,
@@ -19,17 +25,73 @@ const CardTitle: React.FC<CardTitleProps> = ({
leftIcon,
rightIcon,
}) => (
<Flex justify="space-between" align="center" mb={2}>
<HStack spacing={1.5}>
<Box color={darkGoldTheme.gold}>{leftIcon}</Box>
<Text color={darkGoldTheme.gold} fontSize="sm" fontWeight="bold">
<Flex justify="space-between" align="center" mb={3} position="relative">
<HStack spacing={2}>
{/* 图标容器 - 发光效果 */}
<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}
</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>
{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>
);

View File

@@ -1,4 +1,4 @@
// 黑金主题卡片容器原子组件
// 黑金主题卡片容器原子组件 - FUI 科幻风格
import React from 'react';
import { Box, BoxProps } from '@chakra-ui/react';
import { darkGoldTheme } from '../../../constants';
@@ -6,37 +6,114 @@ import { darkGoldTheme } from '../../../constants';
interface DarkGoldCardProps extends BoxProps {
children: React.ReactNode;
hoverable?: boolean;
/** 是否显示角落装饰 */
cornerDecor?: boolean;
/** 是否显示发光效果 */
glowing?: boolean;
}
/**
* 黑金主题卡片容器
* 黑金主题卡片容器 - FUI 风格
*
* 特点:
* - Glassmorphism 毛玻璃效果
* - 悬停发光动画
* - 可选角落装饰
*/
const DarkGoldCard: React.FC<DarkGoldCardProps> = ({
children,
hoverable = true,
cornerDecor = false,
glowing = false,
...props
}) => (
<Box
bg={darkGoldTheme.bgCard}
borderRadius="lg"
position="relative"
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"
borderColor={darkGoldTheme.border}
borderColor="rgba(212, 175, 55, 0.2)"
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={
hoverable
? {
bg: darkGoldTheme.bgCardHover,
borderColor: darkGoldTheme.borderHover,
transform: 'translateY(-1px)',
boxShadow: '0 4px 16px rgba(0, 0, 0, 0.4)',
borderColor: 'rgba(212, 175, 55, 0.4)',
transform: 'translateY(-2px)',
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.4), 0 0 20px rgba(212, 175, 55, 0.2)',
}
: undefined
}
sx={glowing ? { animation: 'glowPulse 3s ease-in-out infinite' } : undefined}
{...props}
>
{/* 角落装饰 */}
{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>
);
export default DarkGoldCard;

View File

@@ -1,6 +1,6 @@
// 核心数值展示原子组件
// 核心数值展示原子组件 - FUI 科幻风格
import React from 'react';
import { HStack, Text } from '@chakra-ui/react';
import { Box, HStack, Text } from '@chakra-ui/react';
import { darkGoldTheme } from '../../../constants';
interface MetricValueProps {
@@ -9,6 +9,8 @@ interface MetricValueProps {
color: string;
suffix?: string;
size?: 'sm' | 'md' | 'lg';
/** 是否启用发光效果 */
glowing?: boolean;
}
const sizeMap = {
@@ -18,7 +20,12 @@ const sizeMap = {
};
/**
* 核心数值展示组件 - 显示标签+数值
* 核心数值展示组件 - FUI 风格
*
* 特点:
* - 发光数值效果
* - 等宽字体显示
* - 悬停增强效果
*/
const MetricValue: React.FC<MetricValueProps> = ({
label,
@@ -26,24 +33,77 @@ const MetricValue: React.FC<MetricValueProps> = ({
color,
suffix,
size = 'lg',
glowing = true,
}) => {
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 (
<HStack spacing={2} align="baseline">
<Text color={darkGoldTheme.textMuted} fontSize={sizes.label}>
{/* 标签 - 添加微妙动画 */}
<Text
color={darkGoldTheme.textMuted}
fontSize={sizes.label}
letterSpacing="wider"
textTransform="uppercase"
>
{label}
</Text>
{/* 数值 - FUI 发光效果 */}
<Box position="relative" display="inline-flex" alignItems="baseline">
{/* 发光层 */}
{glowing && (
<Text
position="absolute"
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 && (
<Text color={color} fontSize={sizes.suffix} fontWeight="bold">
<Text
color={color}
fontSize={sizes.suffix}
fontWeight="bold"
fontFamily="mono"
opacity={0.9}
>
{suffix}
</Text>
)}