diff --git a/src/views/Company/components/StockQuoteCard/components/MetricRow.tsx b/src/views/Company/components/StockQuoteCard/components/MetricRow.tsx new file mode 100644 index 00000000..b5e70a20 --- /dev/null +++ b/src/views/Company/components/StockQuoteCard/components/MetricRow.tsx @@ -0,0 +1,48 @@ +/** + * MetricRow - 指标行原子组件 + * + * 用于数据区块内的单行指标展示 + * 支持普通和高亮两种模式 + */ + +import React, { memo } from 'react'; +import { HStack, Text } from '@chakra-ui/react'; +import { DEEP_SPACE_THEME as T } from './theme'; + +export interface MetricRowProps { + /** 指标标签 */ + label: string; + /** 指标值 */ + value: string | number; + /** 值的颜色(默认白色) */ + valueColor?: string; + /** 是否高亮显示(加粗 + 发光) */ + highlight?: boolean; +} + +/** + * 指标行组件 + * + * 布局:左侧标签 + 右侧值 + * 高亮模式:更大字号 + 发光效果 + */ +export const MetricRow: React.FC = memo(({ + label, + value, + valueColor = T.textWhite, + highlight = false, +}) => ( + + {label} + + {value} + + +)); + +MetricRow.displayName = 'MetricRow'; diff --git a/src/views/Company/components/StockQuoteCard/components/PriceDisplay.tsx b/src/views/Company/components/StockQuoteCard/components/PriceDisplay.tsx index 23baf6d7..9fc2f86b 100644 --- a/src/views/Company/components/StockQuoteCard/components/PriceDisplay.tsx +++ b/src/views/Company/components/StockQuoteCard/components/PriceDisplay.tsx @@ -1,38 +1,67 @@ /** * PriceDisplay - 价格显示原子组件 - * 显示当前价格和涨跌幅 Badge + * + * 深空 FUI 设计风格: + * - 大号价格数字,带涨跌色发光 + * - Badge 使用半透明背景 + 边框发光 */ -import React, { memo } from 'react'; +import React, { memo, useMemo } from 'react'; import { HStack, Text, Badge } from '@chakra-ui/react'; import { formatPrice, formatChangePercent } from './formatters'; -import { STOCK_CARD_THEME } from './theme'; +import { DEEP_SPACE_THEME as T } from './theme'; export interface PriceDisplayProps { + /** 当前价格 */ currentPrice: number; + /** 涨跌幅(百分比) */ changePercent: number; } +/** + * 价格显示组件 + * + * 使用发光效果突出涨跌状态: + * - 涨:红色 (#FF4757) + 红色光晕 + * - 跌:绿色 (#00D984) + 绿色光晕 + */ export const PriceDisplay: React.FC = memo(({ currentPrice, changePercent, }) => { - const { upColor, downColor } = STOCK_CARD_THEME; - const priceColor = changePercent >= 0 ? upColor : downColor; + // 根据涨跌计算颜色和发光效果 + const { priceColor, priceGlow, priceBg } = useMemo(() => { + const isUp = changePercent >= 0; + return { + priceColor: isUp ? T.upColor : T.downColor, + priceGlow: isUp ? T.upGlow : T.downGlow, + priceBg: isUp ? T.upColorMuted : T.downColorMuted, + }; + }, [changePercent]); return ( - - + + {/* 主价格 - 大号字体 + 发光 */} + {formatPrice(currentPrice)} + + {/* 涨跌幅 Badge - 半透明背景 + 边框发光 */} = 0 ? upColor : downColor} - color="#FFFFFF" - fontSize="20px" + bg={priceBg} + color={priceColor} + fontSize="18px" fontWeight="bold" px={3} - py={1} - borderRadius="md" + py={1.5} + borderRadius={T.radiusMD} + boxShadow={priceGlow} > {formatChangePercent(changePercent)} diff --git a/src/views/Company/components/StockQuoteCard/components/StockHeader.tsx b/src/views/Company/components/StockQuoteCard/components/StockHeader.tsx index 779c4866..268ba91d 100644 --- a/src/views/Company/components/StockQuoteCard/components/StockHeader.tsx +++ b/src/views/Company/components/StockQuoteCard/components/StockHeader.tsx @@ -1,6 +1,10 @@ /** * StockHeader - 股票头部原子组件 - * 显示股票名称、代码、行业标签、指数标签、操作按钮 + * + * 深空 FUI 设计风格: + * - 股票名称带金色发光 + * - 行业标签使用金色边框 + * - 操作按钮悬停态有玻璃效果 */ import React, { memo } from 'react'; @@ -8,14 +12,20 @@ import { Flex, HStack, Text, Badge, IconButton, Tooltip } from '@chakra-ui/react import { Share2 } from 'lucide-react'; import FavoriteButton from '@components/FavoriteButton'; import CompareStockInput from './CompareStockInput'; -import { STOCK_CARD_THEME } from './theme'; +import { DEEP_SPACE_THEME as T } from './theme'; export interface StockHeaderProps { + /** 股票名称 */ name: string; + /** 股票代码 */ code: string; + /** 一级行业 */ industryL1?: string; + /** 二级行业 */ industry?: string; + /** 指数标签(沪深300、中证500等) */ indexTags?: string[]; + /** 更新时间 */ updateTime?: string; // 关注相关 isInWatchlist?: boolean; @@ -28,6 +38,13 @@ export interface StockHeaderProps { onCompare?: (stockCode: string) => void; } +/** + * 股票头部组件 + * + * 包含: + * - 左侧:股票名称、代码、行业标签、指数标签 + * - 右侧:对比输入、关注按钮、分享按钮、更新时间 + */ export const StockHeader: React.FC = memo(({ name, code, @@ -42,32 +59,35 @@ export const StockHeader: React.FC = memo(({ isCompareLoading = false, onCompare, }) => { - const { labelColor, valueColor, borderColor } = STOCK_CARD_THEME; - return ( - + {/* 左侧:股票名称 + 行业标签 + 指数标签 */} - - {/* 股票名称 - 突出显示 */} - + + {/* 股票名称 - 金色发光效果 */} + {name} - + ({code}) - {/* 行业标签 */} + {/* 行业标签 - 金色边框 */} {(industryL1 || industry) && ( {industryL1 && industry ? `${industryL1} · ${industry}` @@ -77,7 +97,7 @@ export const StockHeader: React.FC = memo(({ {/* 指数标签 */} {indexTags && indexTags.length > 0 && ( - + {indexTags.join('、')} )} @@ -103,13 +123,14 @@ export const StockHeader: React.FC = memo(({ aria-label="分享" icon={} variant="ghost" - color={labelColor} + color={T.textSecondary} size="sm" + borderRadius={T.radiusSM} onClick={onShare} - _hover={{ bg: 'whiteAlpha.100' }} + _hover={{ bg: T.borderGlass, color: T.textPrimary }} /> - + {updateTime?.split(' ')[1] || '--:--'} diff --git a/src/views/Company/components/StockQuoteCard/components/index.ts b/src/views/Company/components/StockQuoteCard/components/index.ts index d55c031e..03530d01 100644 --- a/src/views/Company/components/StockQuoteCard/components/index.ts +++ b/src/views/Company/components/StockQuoteCard/components/index.ts @@ -17,6 +17,7 @@ export { KeyMetrics } from './KeyMetrics'; export { MainForceInfo } from './MainForceInfo'; export { CompanyInfo } from './CompanyInfo'; export { StockHeader } from './StockHeader'; +export { MetricRow } from './MetricRow'; // ============================================ // 容器组件 - 布局 @@ -50,4 +51,5 @@ export type { KeyMetricsProps } from './KeyMetrics'; export type { MainForceInfoProps } from './MainForceInfo'; export type { CompanyInfoProps, CompanyBasicInfo } from './CompanyInfo'; export type { StockHeaderProps } from './StockHeader'; +export type { MetricRowProps } from './MetricRow'; export type { GlassSectionProps } from './GlassSection'; diff --git a/src/views/Company/components/StockQuoteCard/index.tsx b/src/views/Company/components/StockQuoteCard/index.tsx index 1ca542ef..85a66b84 100644 --- a/src/views/Company/components/StockQuoteCard/index.tsx +++ b/src/views/Company/components/StockQuoteCard/index.tsx @@ -6,97 +6,44 @@ * - 光影深度,弥散背景光 * - 极致圆角,科幻数据终端感 * - * 功能模块: - * - 股票头部:名称、代码、行业标签、操作按钮(对比、关注、分享) - * - 价格展示:当前价格、涨跌幅 Badge - * - 次要行情:今开、昨收、最高、最低(SecondaryQuote 组件) - * - 数据区块:估值指标、市值股本、主力动态(三列 GlassSection 布局) - * * 组件结构: - * - GlowDecorations:装饰性光效(背景层) - * - LoadingSkeleton:加载骨架屏 - * - GlassSection:玻璃容器(包装数据区块) - * - SecondaryQuote:次要行情展示 - * - KeyMetrics:关键指标(估值 + 市值) + * - StockHeader:股票名称、代码、行业标签、操作按钮 + * - PriceDisplay:当前价格、涨跌幅 Badge + * - SecondaryQuote:今开、昨收、最高、最低 + * - GlassSection + MetricRow:估值指标、市值股本 * - MainForceInfo:主力动态 */ import React, { memo } from 'react'; -import { - Box, - Flex, - HStack, - VStack, - Text, - Badge, - IconButton, - Tooltip, - useDisclosure, -} from '@chakra-ui/react'; -import { Share2 } from 'lucide-react'; -import FavoriteButton from '@components/FavoriteButton'; +import { Box, Flex, VStack, useDisclosure } from '@chakra-ui/react'; import { CardGlow } from '@components/FUI'; // 子组件导入 import { StockCompareModal, - CompareStockInput, LoadingSkeleton, GlassSection, + StockHeader, + PriceDisplay, SecondaryQuote, + MetricRow, MainForceInfo, + DEEP_SPACE_THEME as T, + formatPrice, } from './components'; +import { glassCardStyle } from './components/theme'; -// Hooks 和工具 +// Hooks import { useStockQuoteData, useStockCompare } from './hooks'; -import { DEEP_SPACE_THEME, glassCardStyle } from './components/theme'; -import { formatPrice, formatChangePercent } from './components/formatters'; import type { StockQuoteCardProps } from './types'; -/** 主题常量简写 */ -const T = DEEP_SPACE_THEME; - -/** - * 指标行组件 - 用于数据区块内的单行指标展示 - * - * @param label - 指标标签 - * @param value - 指标值 - * @param valueColor - 值的颜色(默认白色) - * @param highlight - 是否高亮显示(加粗 + 发光) - */ -interface MetricRowProps { - label: string; - value: string | number; - valueColor?: string; - highlight?: boolean; -} - -const MetricRow: React.FC = ({ - label, - value, - valueColor = T.textWhite, - highlight = false, -}) => ( - - {label} - - {value} - - -); - const StockQuoteCard: React.FC = ({ stockCode, isInWatchlist = false, isWatchlistLoading = false, onWatchlistToggle, }) => { - const { quoteData, basicInfo, isLoading } = useStockQuoteData(stockCode); + const { quoteData, isLoading } = useStockQuoteData(stockCode); const { currentStockInfo, compareStockInfo, @@ -122,121 +69,33 @@ const StockQuoteCard: React.FC = ({ return ; } - // 涨跌判断(用于价格颜色) - const isUp = quoteData.changePercent >= 0; - const priceColor = isUp ? T.upColor : T.downColor; - const priceGlow = isUp ? T.upGlow : T.downGlow; - const priceBg = isUp ? T.upColorMuted : T.downColorMuted; - return ( <> - + {/* 内容区域(在装饰层之上)*/} - {/* ========== 头部区域 ========== */} - - {/* 左侧:股票名称 + 代码 + 行业 */} - - - {quoteData.name} - - - ({quoteData.code}) - - - {/* 行业标签 */} - {(quoteData.industryL1 || quoteData.industry) && ( - - {quoteData.industryL1 && quoteData.industry - ? `${quoteData.industryL1} · ${quoteData.industry}` - : quoteData.industry || quoteData.industryL1} - - )} - - {/* 指数标签 */} - {quoteData.indexTags && quoteData.indexTags.length > 0 && ( - - {quoteData.indexTags.join('、')} - - )} - - - {/* 右侧:操作按钮 */} - - - {})} - colorScheme="gold" - size="sm" - /> - - } - variant="ghost" - color={T.textSecondary} - size="sm" - borderRadius={T.radiusSM} - _hover={{ bg: T.borderGlass, color: T.textPrimary }} - /> - - - {quoteData.updateTime?.split(' ')[1] || '--:--'} - - - + {/* ========== 价格区域 ========== */} - - - {formatPrice(quoteData.currentPrice)} - - - {formatChangePercent(quoteData.changePercent)} - - + {/* ========== 次要行情 ========== */}