更新Company页面的UI为FUI风格
This commit is contained in:
@@ -64,8 +64,8 @@ const THEME_PRESETS: Record<string, SubTabTheme> = {
|
|||||||
borderColor: 'rgba(212, 175, 55, 0.15)',
|
borderColor: 'rgba(212, 175, 55, 0.15)',
|
||||||
tabSelectedBg: 'linear-gradient(135deg, rgba(212, 175, 55, 0.95) 0%, rgba(184, 150, 12, 0.95) 100%)',
|
tabSelectedBg: 'linear-gradient(135deg, rgba(212, 175, 55, 0.95) 0%, rgba(184, 150, 12, 0.95) 100%)',
|
||||||
tabSelectedColor: '#0A0A14',
|
tabSelectedColor: '#0A0A14',
|
||||||
tabUnselectedColor: 'rgba(212, 175, 55, 0.75)',
|
tabUnselectedColor: 'rgba(255, 255, 255, 0.85)', // 调亮:白色更清晰
|
||||||
tabHoverBg: 'rgba(212, 175, 55, 0.12)',
|
tabHoverBg: 'rgba(212, 175, 55, 0.15)',
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
bg: 'white',
|
bg: 'white',
|
||||||
|
|||||||
@@ -1,103 +1,254 @@
|
|||||||
/**
|
/**
|
||||||
* StockQuoteCard - 股票行情卡片组件
|
* StockQuoteCard - 股票行情卡片组件
|
||||||
*
|
*
|
||||||
* 展示股票的实时行情、关键指标和主力动态
|
* 采用四卡片布局 FUI 风格设计
|
||||||
* 采用 FUI 科幻风格设计 - Ash Thorp / Linear.app 风格
|
* 参考:交易热度、估值安全、情绪风险等分区展示
|
||||||
*
|
|
||||||
* 优化:数据获取已下沉到组件内部,Props 从 11 个精简为 4 个
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Flex,
|
Flex,
|
||||||
|
Grid,
|
||||||
VStack,
|
VStack,
|
||||||
|
HStack,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Text,
|
Text,
|
||||||
|
Badge,
|
||||||
|
Icon,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
import { TrendingUp, Activity, DollarSign, AlertTriangle } from 'lucide-react';
|
||||||
|
|
||||||
import {
|
import { StockCompareModal } from './components';
|
||||||
StockHeader,
|
|
||||||
PriceDisplay,
|
|
||||||
SecondaryQuote,
|
|
||||||
KeyMetrics,
|
|
||||||
MainForceInfo,
|
|
||||||
CompanyInfo,
|
|
||||||
StockCompareModal,
|
|
||||||
} from './components';
|
|
||||||
import { useStockQuoteData, useStockCompare } from './hooks';
|
import { useStockQuoteData, useStockCompare } from './hooks';
|
||||||
import type { StockQuoteCardProps } from './types';
|
import type { StockQuoteCardProps } from './types';
|
||||||
|
|
||||||
// FUI 主题色彩
|
// FUI 主题色彩
|
||||||
const FUI_THEME = {
|
const FUI = {
|
||||||
gold: '#D4AF37',
|
gold: '#D4AF37',
|
||||||
goldLight: 'rgba(212, 175, 55, 0.15)',
|
orange: '#FF6B35',
|
||||||
goldGlow: 'rgba(212, 175, 55, 0.4)',
|
green: '#00D984',
|
||||||
bgCard: 'linear-gradient(145deg, rgba(26, 26, 46, 0.95) 0%, rgba(15, 15, 26, 0.98) 100%)',
|
red: '#FF4757',
|
||||||
border: 'rgba(212, 175, 55, 0.2)',
|
cyan: '#00D4FF',
|
||||||
borderHover: 'rgba(212, 175, 55, 0.4)',
|
purple: '#A855F7',
|
||||||
textPrimary: 'rgba(255, 255, 255, 0.95)',
|
bgCard: 'rgba(20, 20, 30, 0.95)',
|
||||||
textSecondary: 'rgba(255, 255, 255, 0.7)',
|
bgCardHover: 'rgba(30, 30, 45, 0.98)',
|
||||||
|
border: 'rgba(255, 255, 255, 0.08)',
|
||||||
|
borderGold: 'rgba(212, 175, 55, 0.3)',
|
||||||
|
text: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
textMuted: 'rgba(255, 255, 255, 0.6)',
|
||||||
};
|
};
|
||||||
|
|
||||||
// FUI 角落装饰组件
|
// 单个指标卡片组件
|
||||||
const CornerDecoration: React.FC<{ position: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' }> = ({ position }) => {
|
interface MetricCardProps {
|
||||||
const positionStyles = {
|
icon: React.ElementType;
|
||||||
topLeft: { top: '8px', left: '8px', borderTop: '2px solid', borderLeft: '2px solid' },
|
iconColor: string;
|
||||||
topRight: { top: '8px', right: '8px', borderTop: '2px solid', borderRight: '2px solid' },
|
title: string;
|
||||||
bottomLeft: { bottom: '8px', left: '8px', borderBottom: '2px solid', borderLeft: '2px solid' },
|
badge?: string;
|
||||||
bottomRight: { bottom: '8px', right: '8px', borderBottom: '2px solid', borderRight: '2px solid' },
|
badgeColor?: string;
|
||||||
};
|
mainValue: string | number;
|
||||||
|
mainColor?: string;
|
||||||
|
mainUnit?: string;
|
||||||
|
subItems: Array<{ label: string; value: string | number; color?: string }>;
|
||||||
|
rightIcon?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MetricCard: React.FC<MetricCardProps> = ({
|
||||||
|
icon: IconComponent,
|
||||||
|
iconColor,
|
||||||
|
title,
|
||||||
|
badge,
|
||||||
|
badgeColor = FUI.textMuted,
|
||||||
|
mainValue,
|
||||||
|
mainColor = FUI.orange,
|
||||||
|
mainUnit,
|
||||||
|
subItems,
|
||||||
|
rightIcon,
|
||||||
|
}) => (
|
||||||
|
<Box
|
||||||
|
bg={FUI.bgCard}
|
||||||
|
borderRadius="lg"
|
||||||
|
border="1px solid"
|
||||||
|
borderColor={FUI.border}
|
||||||
|
p={4}
|
||||||
|
position="relative"
|
||||||
|
overflow="hidden"
|
||||||
|
transition="all 0.25s ease"
|
||||||
|
_hover={{
|
||||||
|
bg: FUI.bgCardHover,
|
||||||
|
borderColor: FUI.borderGold,
|
||||||
|
transform: 'translateY(-2px)',
|
||||||
|
boxShadow: `0 8px 24px rgba(0, 0, 0, 0.3), 0 0 1px ${FUI.gold}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 左上角光条 */}
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top={0}
|
||||||
|
left={0}
|
||||||
|
w="40px"
|
||||||
|
h="2px"
|
||||||
|
bg={iconColor}
|
||||||
|
opacity={0.8}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 顶部:图标 + 标题 + 标签 */}
|
||||||
|
<HStack spacing={2} mb={3}>
|
||||||
|
<Icon as={IconComponent} boxSize={4} color={iconColor} />
|
||||||
|
<Text fontSize="sm" fontWeight="600" color={FUI.text}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
{badge && (
|
||||||
|
<Badge
|
||||||
|
fontSize="10px"
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
bg="rgba(255, 255, 255, 0.1)"
|
||||||
|
color={badgeColor}
|
||||||
|
borderRadius="sm"
|
||||||
|
fontWeight="500"
|
||||||
|
>
|
||||||
|
{badge}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{rightIcon && (
|
||||||
|
<Box ml="auto" opacity={0.5}>
|
||||||
|
{rightIcon}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 主数值 */}
|
||||||
|
<Text
|
||||||
|
fontSize="2xl"
|
||||||
|
fontWeight="bold"
|
||||||
|
color={mainColor}
|
||||||
|
lineHeight="1.2"
|
||||||
|
mb={2}
|
||||||
|
>
|
||||||
|
{mainValue}
|
||||||
|
{mainUnit && (
|
||||||
|
<Text as="span" fontSize="md" fontWeight="normal" ml={1}>
|
||||||
|
{mainUnit}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{/* 子项目 */}
|
||||||
|
<VStack align="stretch" spacing={1}>
|
||||||
|
{subItems.map((item, idx) => (
|
||||||
|
<HStack key={idx} justify="space-between" fontSize="xs">
|
||||||
|
<Text color={FUI.textMuted}>{item.label}</Text>
|
||||||
|
<Text color={item.color || FUI.text} fontWeight="500">
|
||||||
|
{item.value}
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
))}
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
// 股票信息卡片(第一个)
|
||||||
|
interface StockInfoCardProps {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
currentPrice: number;
|
||||||
|
changePercent: number;
|
||||||
|
industry?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StockInfoCard: React.FC<StockInfoCardProps> = ({
|
||||||
|
name,
|
||||||
|
code,
|
||||||
|
currentPrice,
|
||||||
|
changePercent,
|
||||||
|
industry,
|
||||||
|
}) => {
|
||||||
|
const isUp = changePercent >= 0;
|
||||||
|
const priceColor = isUp ? FUI.red : FUI.green;
|
||||||
|
const trendText = isUp ? '强势上涨' : '震荡下跌';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
position="absolute"
|
bg={FUI.bgCard}
|
||||||
w="12px"
|
borderRadius="lg"
|
||||||
h="12px"
|
border="1px solid"
|
||||||
borderColor={FUI_THEME.goldGlow}
|
borderColor={FUI.border}
|
||||||
opacity={0.7}
|
p={4}
|
||||||
{...positionStyles[position]}
|
position="relative"
|
||||||
/>
|
overflow="hidden"
|
||||||
|
transition="all 0.25s ease"
|
||||||
|
_hover={{
|
||||||
|
bg: FUI.bgCardHover,
|
||||||
|
borderColor: FUI.borderGold,
|
||||||
|
transform: 'translateY(-2px)',
|
||||||
|
boxShadow: `0 8px 24px rgba(0, 0, 0, 0.3), 0 0 1px ${FUI.gold}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 左上角光条 */}
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top={0}
|
||||||
|
left={0}
|
||||||
|
w="40px"
|
||||||
|
h="2px"
|
||||||
|
bg={priceColor}
|
||||||
|
opacity={0.8}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 股票名称和代码 */}
|
||||||
|
<HStack spacing={2} mb={3}>
|
||||||
|
<Text fontSize="lg" fontWeight="bold" color={FUI.text}>
|
||||||
|
{name}
|
||||||
|
</Text>
|
||||||
|
<Badge
|
||||||
|
fontSize="10px"
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
bg="rgba(255, 255, 255, 0.1)"
|
||||||
|
color={FUI.textMuted}
|
||||||
|
borderRadius="sm"
|
||||||
|
>
|
||||||
|
{code}
|
||||||
|
</Badge>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 价格和涨跌幅 */}
|
||||||
|
<HStack spacing={3} mb={2}>
|
||||||
|
<Text fontSize="2xl" fontWeight="bold" color={priceColor}>
|
||||||
|
{currentPrice.toFixed(2)}
|
||||||
|
</Text>
|
||||||
|
<Badge
|
||||||
|
fontSize="sm"
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
bg={isUp ? 'rgba(255, 71, 87, 0.15)' : 'rgba(0, 217, 132, 0.15)'}
|
||||||
|
color={priceColor}
|
||||||
|
borderRadius="md"
|
||||||
|
fontWeight="bold"
|
||||||
|
>
|
||||||
|
{isUp ? '↗' : '↘'} {isUp ? '+' : ''}{changePercent.toFixed(2)}%
|
||||||
|
</Badge>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 走势标签 */}
|
||||||
|
<HStack fontSize="xs" color={FUI.textMuted}>
|
||||||
|
<Icon as={TrendingUp} boxSize={3} color={priceColor} />
|
||||||
|
<Text>走势:</Text>
|
||||||
|
<Text color={priceColor} fontWeight="500">{trendText}</Text>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// FUI 卡片标题组件
|
|
||||||
const FUICardTitle: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
|
||||||
<Text
|
|
||||||
fontSize="11px"
|
|
||||||
fontWeight="600"
|
|
||||||
letterSpacing="0.15em"
|
|
||||||
textTransform="uppercase"
|
|
||||||
color={FUI_THEME.gold}
|
|
||||||
mb={4}
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
_before={{
|
|
||||||
content: '""',
|
|
||||||
display: 'inline-block',
|
|
||||||
width: '4px',
|
|
||||||
height: '4px',
|
|
||||||
bg: FUI_THEME.gold,
|
|
||||||
borderRadius: '1px',
|
|
||||||
mr: 2,
|
|
||||||
boxShadow: `0 0 6px ${FUI_THEME.gold}`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
|
|
||||||
const StockQuoteCard: React.FC<StockQuoteCardProps> = ({
|
const StockQuoteCard: React.FC<StockQuoteCardProps> = ({
|
||||||
stockCode,
|
stockCode,
|
||||||
isInWatchlist = false,
|
isInWatchlist = false,
|
||||||
isWatchlistLoading = false,
|
isWatchlistLoading = false,
|
||||||
onWatchlistToggle,
|
onWatchlistToggle,
|
||||||
}) => {
|
}) => {
|
||||||
// 内部获取行情数据和基本信息
|
|
||||||
const { quoteData, basicInfo, isLoading } = useStockQuoteData(stockCode);
|
const { quoteData, basicInfo, isLoading } = useStockQuoteData(stockCode);
|
||||||
|
|
||||||
// 内部管理股票对比逻辑
|
|
||||||
const {
|
const {
|
||||||
currentStockInfo,
|
currentStockInfo,
|
||||||
compareStockInfo,
|
compareStockInfo,
|
||||||
@@ -106,185 +257,136 @@ const StockQuoteCard: React.FC<StockQuoteCardProps> = ({
|
|||||||
clearCompare,
|
clearCompare,
|
||||||
} = useStockCompare(stockCode);
|
} = useStockCompare(stockCode);
|
||||||
|
|
||||||
// 对比弹窗控制
|
|
||||||
const { isOpen: isCompareModalOpen, onOpen: openCompareModal, onClose: closeCompareModal } = useDisclosure();
|
const { isOpen: isCompareModalOpen, onOpen: openCompareModal, onClose: closeCompareModal } = useDisclosure();
|
||||||
|
|
||||||
// 处理对比按钮点击
|
|
||||||
const handleCompare = (compareCode: string) => {
|
const handleCompare = (compareCode: string) => {
|
||||||
triggerCompare(compareCode);
|
triggerCompare(compareCode);
|
||||||
openCompareModal();
|
openCompareModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理关闭对比弹窗
|
|
||||||
const handleCloseCompare = () => {
|
const handleCloseCompare = () => {
|
||||||
closeCompareModal();
|
closeCompareModal();
|
||||||
clearCompare();
|
clearCompare();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载中或无数据时显示 FUI 风格骨架屏
|
// 加载中骨架屏
|
||||||
if (isLoading || !quoteData) {
|
if (isLoading || !quoteData) {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Grid templateColumns="repeat(4, 1fr)" gap={4}>
|
||||||
position="relative"
|
{[1, 2, 3, 4].map((i) => (
|
||||||
bg={FUI_THEME.bgCard}
|
<Box
|
||||||
borderRadius="lg"
|
key={i}
|
||||||
border="1px solid"
|
bg={FUI.bgCard}
|
||||||
borderColor={FUI_THEME.border}
|
borderRadius="lg"
|
||||||
p={6}
|
border="1px solid"
|
||||||
overflow="hidden"
|
borderColor={FUI.border}
|
||||||
boxShadow={`0 4px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.05)`}
|
p={4}
|
||||||
>
|
>
|
||||||
<CornerDecoration position="topLeft" />
|
<Skeleton height="20px" width="120px" mb={3} startColor="rgba(255,255,255,0.05)" endColor="rgba(255,255,255,0.1)" />
|
||||||
<CornerDecoration position="topRight" />
|
<Skeleton height="32px" width="80px" mb={2} startColor="rgba(255,255,255,0.05)" endColor="rgba(255,255,255,0.1)" />
|
||||||
<CornerDecoration position="bottomLeft" />
|
<Skeleton height="14px" width="100%" startColor="rgba(255,255,255,0.05)" endColor="rgba(255,255,255,0.1)" />
|
||||||
<CornerDecoration position="bottomRight" />
|
</Box>
|
||||||
<VStack spacing={4} align="stretch">
|
))}
|
||||||
<Skeleton height="30px" width="200px" startColor="rgba(212, 175, 55, 0.1)" endColor="rgba(212, 175, 55, 0.2)" />
|
</Grid>
|
||||||
<Skeleton height="60px" startColor="rgba(212, 175, 55, 0.1)" endColor="rgba(212, 175, 55, 0.2)" />
|
|
||||||
<Skeleton height="80px" startColor="rgba(212, 175, 55, 0.1)" endColor="rgba(212, 175, 55, 0.2)" />
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 格式化数值
|
||||||
|
const formatVolume = (val: number) => {
|
||||||
|
if (!val) return '-';
|
||||||
|
if (val >= 100000000) return `${(val / 100000000).toFixed(2)}亿`;
|
||||||
|
if (val >= 10000) return `${(val / 10000).toFixed(0)}万`;
|
||||||
|
return val.toString();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<>
|
||||||
position="relative"
|
<Grid templateColumns="repeat(4, 1fr)" gap={4}>
|
||||||
bg={FUI_THEME.bgCard}
|
{/* 卡片1: 股票基本信息 */}
|
||||||
borderRadius="lg"
|
<StockInfoCard
|
||||||
border="1px solid"
|
|
||||||
borderColor={FUI_THEME.border}
|
|
||||||
overflow="hidden"
|
|
||||||
boxShadow={`0 4px 20px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.05)`}
|
|
||||||
backdropFilter="blur(12px)"
|
|
||||||
transition="all 0.3s ease"
|
|
||||||
_hover={{
|
|
||||||
borderColor: FUI_THEME.borderHover,
|
|
||||||
boxShadow: `0 8px 32px rgba(0, 0, 0, 0.4), 0 0 20px ${FUI_THEME.goldLight}, inset 0 1px 0 rgba(255, 255, 255, 0.08)`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* FUI 角落装饰 */}
|
|
||||||
<CornerDecoration position="topLeft" />
|
|
||||||
<CornerDecoration position="topRight" />
|
|
||||||
<CornerDecoration position="bottomLeft" />
|
|
||||||
<CornerDecoration position="bottomRight" />
|
|
||||||
|
|
||||||
{/* 顶部光效线条 */}
|
|
||||||
<Box
|
|
||||||
position="absolute"
|
|
||||||
top={0}
|
|
||||||
left="20%"
|
|
||||||
right="20%"
|
|
||||||
height="1px"
|
|
||||||
bg={`linear-gradient(90deg, transparent, ${FUI_THEME.gold}, transparent)`}
|
|
||||||
opacity={0.6}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 内容区域 */}
|
|
||||||
<Box p={6}>
|
|
||||||
{/* FUI 标题 */}
|
|
||||||
<FUICardTitle>个股详情 · STOCK QUOTE</FUICardTitle>
|
|
||||||
|
|
||||||
{/* 顶部:股票名称 + 关注/分享按钮 + 更新时间 */}
|
|
||||||
<StockHeader
|
|
||||||
name={quoteData.name}
|
name={quoteData.name}
|
||||||
code={quoteData.code}
|
code={quoteData.code}
|
||||||
industryL1={quoteData.industryL1}
|
currentPrice={quoteData.currentPrice}
|
||||||
|
changePercent={quoteData.changePercent}
|
||||||
industry={quoteData.industry}
|
industry={quoteData.industry}
|
||||||
indexTags={quoteData.indexTags}
|
|
||||||
updateTime={quoteData.updateTime}
|
|
||||||
isInWatchlist={isInWatchlist}
|
|
||||||
isWatchlistLoading={isWatchlistLoading}
|
|
||||||
onWatchlistToggle={onWatchlistToggle}
|
|
||||||
isCompareLoading={isCompareLoading}
|
|
||||||
onCompare={handleCompare}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 股票对比弹窗 */}
|
{/* 卡片2: 交易热度 */}
|
||||||
<StockCompareModal
|
<MetricCard
|
||||||
isOpen={isCompareModalOpen}
|
icon={Activity}
|
||||||
onClose={handleCloseCompare}
|
iconColor={FUI.orange}
|
||||||
currentStock={quoteData.code}
|
title="交易热度"
|
||||||
currentStockInfo={currentStockInfo || null}
|
badge="流动性"
|
||||||
compareStock={compareStockInfo?.stock_code || ''}
|
mainValue={quoteData.marketCap || '-'}
|
||||||
compareStockInfo={compareStockInfo || null}
|
mainColor={FUI.orange}
|
||||||
isLoading={isCompareLoading}
|
subItems={[
|
||||||
|
{
|
||||||
|
label: '换手率',
|
||||||
|
value: quoteData.turnoverRate ? `${quoteData.turnoverRate.toFixed(2)}%` : '-',
|
||||||
|
color: (quoteData.turnoverRate || 0) > 5 ? FUI.orange : FUI.text,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '52周区间',
|
||||||
|
value: `${quoteData.week52Low?.toFixed(2) || '-'} - ${quoteData.week52High?.toFixed(2) || '-'}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 分隔线 */}
|
{/* 卡片3: 估值安全 */}
|
||||||
<Box
|
<MetricCard
|
||||||
my={4}
|
icon={DollarSign}
|
||||||
height="1px"
|
iconColor={FUI.cyan}
|
||||||
bg={`linear-gradient(90deg, transparent, ${FUI_THEME.border}, transparent)`}
|
title="估值 VS 安全"
|
||||||
|
badge="便宜否"
|
||||||
|
mainValue={quoteData.pe ? quoteData.pe.toFixed(2) : '-'}
|
||||||
|
mainColor={FUI.cyan}
|
||||||
|
mainUnit=""
|
||||||
|
subItems={[
|
||||||
|
{
|
||||||
|
label: '市盈率(PE)',
|
||||||
|
value: quoteData.pe ? (quoteData.pe > 50 ? '高估值' : quoteData.pe > 20 ? '合理' : '低估值') : '-',
|
||||||
|
color: quoteData.pe ? (quoteData.pe > 50 ? FUI.orange : quoteData.pe > 20 ? FUI.gold : FUI.green) : FUI.textMuted,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发行总股本',
|
||||||
|
value: quoteData.totalShares ? `${quoteData.totalShares}亿股` : '-',
|
||||||
|
},
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 1:2 布局 */}
|
{/* 卡片4: 股本结构 */}
|
||||||
<Flex gap={8}>
|
<MetricCard
|
||||||
{/* 左栏:价格信息 (flex=1) */}
|
icon={AlertTriangle}
|
||||||
<Box flex="1" minWidth="0">
|
iconColor={FUI.green}
|
||||||
<PriceDisplay
|
title="股本结构"
|
||||||
currentPrice={quoteData.currentPrice}
|
badge="资金面"
|
||||||
changePercent={quoteData.changePercent}
|
mainValue={quoteData.floatShares ? `${quoteData.floatShares}` : '-'}
|
||||||
/>
|
mainColor={FUI.green}
|
||||||
<SecondaryQuote
|
mainUnit="亿股"
|
||||||
todayOpen={quoteData.todayOpen}
|
subItems={[
|
||||||
yesterdayClose={quoteData.yesterdayClose}
|
{
|
||||||
todayHigh={quoteData.todayHigh}
|
label: '流通股本',
|
||||||
todayLow={quoteData.todayLow}
|
value: quoteData.floatShares ? `${quoteData.floatShares}亿股` : '-',
|
||||||
/>
|
},
|
||||||
</Box>
|
{
|
||||||
|
label: '行业',
|
||||||
|
value: quoteData.industry || '-',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
{/* 右栏:关键指标 + 主力动态 (flex=2) */}
|
{/* 股票对比弹窗 */}
|
||||||
<Flex
|
<StockCompareModal
|
||||||
flex="2"
|
isOpen={isCompareModalOpen}
|
||||||
minWidth="0"
|
onClose={handleCloseCompare}
|
||||||
gap={8}
|
currentStock={quoteData.code}
|
||||||
borderLeftWidth="1px"
|
currentStockInfo={currentStockInfo || null}
|
||||||
borderColor={FUI_THEME.border}
|
compareStock={compareStockInfo?.stock_code || ''}
|
||||||
pl={8}
|
compareStockInfo={compareStockInfo || null}
|
||||||
>
|
isLoading={isCompareLoading}
|
||||||
<KeyMetrics
|
|
||||||
pe={quoteData.pe}
|
|
||||||
marketCap={quoteData.marketCap}
|
|
||||||
totalShares={quoteData.totalShares}
|
|
||||||
floatShares={quoteData.floatShares}
|
|
||||||
turnoverRate={quoteData.turnoverRate}
|
|
||||||
week52Low={quoteData.week52Low}
|
|
||||||
week52High={quoteData.week52High}
|
|
||||||
/>
|
|
||||||
<MainForceInfo
|
|
||||||
mainNetInflow={quoteData.mainNetInflow}
|
|
||||||
institutionHolding={quoteData.institutionHolding}
|
|
||||||
buyRatio={quoteData.buyRatio}
|
|
||||||
sellRatio={quoteData.sellRatio}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
{/* 公司信息区块 */}
|
|
||||||
{basicInfo && (
|
|
||||||
<>
|
|
||||||
<Box
|
|
||||||
my={4}
|
|
||||||
height="1px"
|
|
||||||
bg={`linear-gradient(90deg, transparent, ${FUI_THEME.border}, transparent)`}
|
|
||||||
/>
|
|
||||||
<CompanyInfo basicInfo={basicInfo} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* 底部光效线条 */}
|
|
||||||
<Box
|
|
||||||
position="absolute"
|
|
||||||
bottom={0}
|
|
||||||
left="30%"
|
|
||||||
right="30%"
|
|
||||||
height="1px"
|
|
||||||
bg={`linear-gradient(90deg, transparent, ${FUI_THEME.goldGlow}, transparent)`}
|
|
||||||
opacity={0.4}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user