From 0214052965d92009c26331f0b4766a42d485abae Mon Sep 17 00:00:00 2001 From: zzlgreat Date: Wed, 17 Dec 2025 22:30:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0Company=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=9A=84UI=E4=B8=BAFUI=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SubTabContainer/index.tsx | 4 +- .../components/StockQuoteCard/index.tsx | 532 +++++++++++------- 2 files changed, 319 insertions(+), 217 deletions(-) diff --git a/src/components/SubTabContainer/index.tsx b/src/components/SubTabContainer/index.tsx index 16b8eb61..9a413f44 100644 --- a/src/components/SubTabContainer/index.tsx +++ b/src/components/SubTabContainer/index.tsx @@ -64,8 +64,8 @@ const THEME_PRESETS: Record = { 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%)', tabSelectedColor: '#0A0A14', - tabUnselectedColor: 'rgba(212, 175, 55, 0.75)', - tabHoverBg: 'rgba(212, 175, 55, 0.12)', + tabUnselectedColor: 'rgba(255, 255, 255, 0.85)', // 调亮:白色更清晰 + tabHoverBg: 'rgba(212, 175, 55, 0.15)', }, default: { bg: 'white', diff --git a/src/views/Company/components/StockQuoteCard/index.tsx b/src/views/Company/components/StockQuoteCard/index.tsx index f2902848..acc2b986 100644 --- a/src/views/Company/components/StockQuoteCard/index.tsx +++ b/src/views/Company/components/StockQuoteCard/index.tsx @@ -1,103 +1,254 @@ /** * StockQuoteCard - 股票行情卡片组件 * - * 展示股票的实时行情、关键指标和主力动态 - * 采用 FUI 科幻风格设计 - Ash Thorp / Linear.app 风格 - * - * 优化:数据获取已下沉到组件内部,Props 从 11 个精简为 4 个 + * 采用四卡片布局 FUI 风格设计 + * 参考:交易热度、估值安全、情绪风险等分区展示 */ import React from 'react'; import { Box, Flex, + Grid, VStack, + HStack, Skeleton, Text, + Badge, + Icon, useDisclosure, } from '@chakra-ui/react'; +import { TrendingUp, Activity, DollarSign, AlertTriangle } from 'lucide-react'; -import { - StockHeader, - PriceDisplay, - SecondaryQuote, - KeyMetrics, - MainForceInfo, - CompanyInfo, - StockCompareModal, -} from './components'; +import { StockCompareModal } from './components'; import { useStockQuoteData, useStockCompare } from './hooks'; import type { StockQuoteCardProps } from './types'; // FUI 主题色彩 -const FUI_THEME = { +const FUI = { gold: '#D4AF37', - goldLight: 'rgba(212, 175, 55, 0.15)', - goldGlow: 'rgba(212, 175, 55, 0.4)', - bgCard: 'linear-gradient(145deg, rgba(26, 26, 46, 0.95) 0%, rgba(15, 15, 26, 0.98) 100%)', - border: 'rgba(212, 175, 55, 0.2)', - borderHover: 'rgba(212, 175, 55, 0.4)', - textPrimary: 'rgba(255, 255, 255, 0.95)', - textSecondary: 'rgba(255, 255, 255, 0.7)', + orange: '#FF6B35', + green: '#00D984', + red: '#FF4757', + cyan: '#00D4FF', + purple: '#A855F7', + bgCard: 'rgba(20, 20, 30, 0.95)', + 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 }) => { - const positionStyles = { - topLeft: { top: '8px', left: '8px', borderTop: '2px solid', borderLeft: '2px solid' }, - topRight: { top: '8px', right: '8px', borderTop: '2px solid', borderRight: '2px solid' }, - bottomLeft: { bottom: '8px', left: '8px', borderBottom: '2px solid', borderLeft: '2px solid' }, - bottomRight: { bottom: '8px', right: '8px', borderBottom: '2px solid', borderRight: '2px solid' }, - }; +// 单个指标卡片组件 +interface MetricCardProps { + icon: React.ElementType; + iconColor: string; + title: string; + badge?: string; + 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 = ({ + icon: IconComponent, + iconColor, + title, + badge, + badgeColor = FUI.textMuted, + mainValue, + mainColor = FUI.orange, + mainUnit, + subItems, + rightIcon, +}) => ( + + {/* 左上角光条 */} + + + {/* 顶部:图标 + 标题 + 标签 */} + + + + {title} + + {badge && ( + + {badge} + + )} + {rightIcon && ( + + {rightIcon} + + )} + + + {/* 主数值 */} + + {mainValue} + {mainUnit && ( + + {mainUnit} + + )} + + + {/* 子项目 */} + + {subItems.map((item, idx) => ( + + {item.label} + + {item.value} + + + ))} + + +); + +// 股票信息卡片(第一个) +interface StockInfoCardProps { + name: string; + code: string; + currentPrice: number; + changePercent: number; + industry?: string; +} + +const StockInfoCard: React.FC = ({ + name, + code, + currentPrice, + changePercent, + industry, +}) => { + const isUp = changePercent >= 0; + const priceColor = isUp ? FUI.red : FUI.green; + const trendText = isUp ? '强势上涨' : '震荡下跌'; return ( + 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}`, + }} + > + {/* 左上角光条 */} + + + {/* 股票名称和代码 */} + + + {name} + + + {code} + + + + {/* 价格和涨跌幅 */} + + + {currentPrice.toFixed(2)} + + + {isUp ? '↗' : '↘'} {isUp ? '+' : ''}{changePercent.toFixed(2)}% + + + + {/* 走势标签 */} + + + 走势: + {trendText} + + ); }; -// FUI 卡片标题组件 -const FUICardTitle: React.FC<{ children: React.ReactNode }> = ({ children }) => ( - - {children} - -); - const StockQuoteCard: React.FC = ({ stockCode, isInWatchlist = false, isWatchlistLoading = false, onWatchlistToggle, }) => { - // 内部获取行情数据和基本信息 const { quoteData, basicInfo, isLoading } = useStockQuoteData(stockCode); - - // 内部管理股票对比逻辑 const { currentStockInfo, compareStockInfo, @@ -106,185 +257,136 @@ const StockQuoteCard: React.FC = ({ clearCompare, } = useStockCompare(stockCode); - // 对比弹窗控制 const { isOpen: isCompareModalOpen, onOpen: openCompareModal, onClose: closeCompareModal } = useDisclosure(); - // 处理对比按钮点击 const handleCompare = (compareCode: string) => { triggerCompare(compareCode); openCompareModal(); }; - // 处理关闭对比弹窗 const handleCloseCompare = () => { closeCompareModal(); clearCompare(); }; - // 加载中或无数据时显示 FUI 风格骨架屏 + // 加载中骨架屏 if (isLoading || !quoteData) { return ( - - - - - - - - - - - + + {[1, 2, 3, 4].map((i) => ( + + + + + + ))} + ); } + // 格式化数值 + 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 ( - - {/* FUI 角落装饰 */} - - - - - - {/* 顶部光效线条 */} - - - {/* 内容区域 */} - - {/* FUI 标题 */} - 个股详情 · STOCK QUOTE - - {/* 顶部:股票名称 + 关注/分享按钮 + 更新时间 */} - + + {/* 卡片1: 股票基本信息 */} + - {/* 股票对比弹窗 */} - 5 ? FUI.orange : FUI.text, + }, + { + label: '52周区间', + value: `${quoteData.week52Low?.toFixed(2) || '-'} - ${quoteData.week52High?.toFixed(2) || '-'}`, + }, + ]} /> - {/* 分隔线 */} - 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 布局 */} - - {/* 左栏:价格信息 (flex=1) */} - - - - + {/* 卡片4: 股本结构 */} + + - {/* 右栏:关键指标 + 主力动态 (flex=2) */} - - - - - - - {/* 公司信息区块 */} - {basicInfo && ( - <> - - - - )} - - - {/* 底部光效线条 */} - - + ); };