From 3adff8999566eaf937f28cd92b12ab7f825e6376 Mon Sep 17 00:00:00 2001 From: zzlgreat Date: Wed, 17 Dec 2025 22:22:44 +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 --- app.py | 15 +- src/components/SubTabContainer/index.tsx | 62 ++++-- .../StockQuoteCard/components/KeyMetrics.tsx | 34 ++-- .../StockQuoteCard/hooks/useStockQuoteData.ts | 3 +- .../components/StockQuoteCard/index.tsx | 182 +++++++++++++++--- .../components/StockQuoteCard/types.ts | 3 +- 6 files changed, 228 insertions(+), 71 deletions(-) diff --git a/app.py b/app.py index 6d466d62..02d251d2 100755 --- a/app.py +++ b/app.py @@ -8734,6 +8734,9 @@ def get_stock_quote_detail(stock_code): if trade_result: row = row_to_dict(trade_result) + # 调试日志:打印所有字段 + app.logger.info(f"[quote-detail] stock={base_code}, row keys={list(row.keys())}") + app.logger.info(f"[quote-detail] total_shares={row.get('total_shares')}, float_shares={row.get('float_shares')}, pe_ratio={row.get('pe_ratio')}") result_data['name'] = row.get('SECNAME') or '' result_data['current_price'] = float(row.get('close_price') or 0) result_data['change_percent'] = float(row.get('change_pct') or 0) @@ -8741,17 +8744,19 @@ def get_stock_quote_detail(stock_code): result_data['yesterday_close'] = float(row.get('pre_close') or 0) result_data['today_high'] = float(row.get('high') or 0) result_data['today_low'] = float(row.get('low') or 0) - result_data['pe'] = float(row.get('pe_ratio') or 0) if row.get('pe_ratio') else None + pe_value = row.get('pe_ratio') or row.get('F026N') + result_data['pe'] = float(pe_value) if pe_value else None result_data['turnover_rate'] = float(row.get('turnover_rate') or 0) result_data['sw_industry_l1'] = row.get('sw_industry_l1') or '' result_data['sw_industry_l2'] = row.get('sw_industry_l2') or '' result_data['industry_l1'] = row.get('industry_l1') or '' result_data['industry'] = row.get('sw_industry_l2') or row.get('sw_industry_l1') or '' - # 计算股本和市值 - total_shares = float(row.get('total_shares') or 0) - float_shares = float(row.get('float_shares') or 0) - close_price = float(row.get('close_price') or 0) + # 计算股本和市值(兼容别名和原始字段名) + total_shares = float(row.get('total_shares') or row.get('F020N') or 0) + float_shares = float(row.get('float_shares') or row.get('F021N') or 0) + close_price = float(row.get('close_price') or row.get('F007N') or 0) + app.logger.info(f"[quote-detail] calculated: total_shares={total_shares}, float_shares={float_shares}") # 发行总股本(亿股) if total_shares > 0: diff --git a/src/components/SubTabContainer/index.tsx b/src/components/SubTabContainer/index.tsx index 658280f3..16b8eb61 100644 --- a/src/components/SubTabContainer/index.tsx +++ b/src/components/SubTabContainer/index.tsx @@ -61,11 +61,11 @@ export interface SubTabTheme { const THEME_PRESETS: Record = { blackGold: { bg: 'transparent', - borderColor: 'rgba(212, 175, 55, 0.2)', - tabSelectedBg: 'linear-gradient(135deg, #D4AF37 0%, #B8960C 100%)', + 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.8)', - tabHoverBg: 'rgba(212, 175, 55, 0.1)', + tabUnselectedColor: 'rgba(212, 175, 55, 0.75)', + tabHoverBg: 'rgba(212, 175, 55, 0.12)', }, default: { bg: 'white', @@ -162,11 +162,11 @@ const SubTabContainer: React.FC = memo(({ bg={theme.bg} borderBottom="1px solid" borderColor={theme.borderColor} - pl={0} - pr={2} - py={1.5} + pl={2} + pr={4} + py={3} flexWrap="nowrap" - gap={1} + gap={2} alignItems="center" overflowX="auto" css={{ @@ -178,29 +178,51 @@ const SubTabContainer: React.FC = memo(({ - - {tab.icon && } - {tab.name} + + {tab.icon && } + {tab.name} ))} diff --git a/src/views/Company/components/StockQuoteCard/components/KeyMetrics.tsx b/src/views/Company/components/StockQuoteCard/components/KeyMetrics.tsx index f32b9d34..a725f88d 100644 --- a/src/views/Company/components/StockQuoteCard/components/KeyMetrics.tsx +++ b/src/views/Company/components/StockQuoteCard/components/KeyMetrics.tsx @@ -10,22 +10,20 @@ import { STOCK_CARD_THEME } from './theme'; export interface KeyMetricsProps { pe: number; - eps?: number; - pb: number; marketCap: string; totalShares?: number; // 发行总股本(亿股) floatShares?: number; // 流通股本(亿股) + turnoverRate?: number; // 换手率(%) week52Low: number; week52High: number; } export const KeyMetrics: React.FC = memo(({ pe, - eps, - pb, marketCap, totalShares, floatShares, + turnoverRate, week52Low, week52High, }) => { @@ -45,25 +43,13 @@ export const KeyMetrics: React.FC = memo(({ 市盈率(PE): - {pe.toFixed(2)} - - - - 每股收益(EPS): - - {eps?.toFixed(3) || '-'} - - - - 市净率(PB): - - {pb.toFixed(2)} + {pe ? pe.toFixed(2) : '-'} 流通市值: - {marketCap} + {marketCap || '-'} @@ -72,6 +58,18 @@ export const KeyMetrics: React.FC = memo(({ {totalShares ? `${totalShares}亿股` : '-'} + + 流通股本: + + {floatShares ? `${floatShares}亿股` : '-'} + + + + 换手率: + + {turnoverRate !== undefined ? `${turnoverRate.toFixed(2)}%` : '-'} + + 52周波动: diff --git a/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts b/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts index 6ee9fc26..dd33e001 100644 --- a/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts +++ b/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts @@ -35,11 +35,10 @@ const transformQuoteData = (apiData: any, stockCode: string): StockQuoteCardData // 关键指标 pe: apiData.pe || apiData.pe_ttm || 0, - eps: apiData.eps || apiData.basic_eps || undefined, - pb: apiData.pb || apiData.pb_mrq || 0, marketCap: apiData.market_cap || apiData.marketCap || apiData.circ_mv || '0', totalShares: apiData.total_shares || apiData.totalShares || undefined, floatShares: apiData.float_shares || apiData.floatShares || undefined, + turnoverRate: apiData.turnover_rate || apiData.turnoverRate || undefined, week52Low: apiData.week52_low || apiData.week52Low || 0, week52High: apiData.week52_high || apiData.week52High || 0, diff --git a/src/views/Company/components/StockQuoteCard/index.tsx b/src/views/Company/components/StockQuoteCard/index.tsx index ceac98cb..f2902848 100644 --- a/src/views/Company/components/StockQuoteCard/index.tsx +++ b/src/views/Company/components/StockQuoteCard/index.tsx @@ -2,7 +2,7 @@ * StockQuoteCard - 股票行情卡片组件 * * 展示股票的实时行情、关键指标和主力动态 - * 采用原子组件拆分,提高可维护性和复用性 + * 采用 FUI 科幻风格设计 - Ash Thorp / Linear.app 风格 * * 优化:数据获取已下沉到组件内部,Props 从 11 个精简为 4 个 */ @@ -10,11 +10,10 @@ import React from 'react'; import { Box, - Card, - CardBody, Flex, VStack, Skeleton, + Text, useDisclosure, } from '@chakra-ui/react'; @@ -26,11 +25,69 @@ import { MainForceInfo, CompanyInfo, StockCompareModal, - STOCK_CARD_THEME, } from './components'; import { useStockQuoteData, useStockCompare } from './hooks'; import type { StockQuoteCardProps } from './types'; +// FUI 主题色彩 +const FUI_THEME = { + 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)', +}; + +// 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' }, + }; + + return ( + + ); +}; + +// FUI 卡片标题组件 +const FUICardTitle: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + + {children} + +); + const StockQuoteCard: React.FC = ({ stockCode, isInWatchlist = false, @@ -64,26 +121,70 @@ const StockQuoteCard: React.FC = ({ clearCompare(); }; - const { cardBg, borderColor } = STOCK_CARD_THEME; - - // 加载中或无数据时显示骨架屏 + // 加载中或无数据时显示 FUI 风格骨架屏 if (isLoading || !quoteData) { return ( - - - - - - - - - + + + + + + + + + + + ); } return ( - - + + {/* FUI 角落装饰 */} + + + + + + {/* 顶部光效线条 */} + + + {/* 内容区域 */} + + {/* FUI 标题 */} + 个股详情 · STOCK QUOTE + {/* 顶部:股票名称 + 关注/分享按钮 + 更新时间 */} = ({ isLoading={isCompareLoading} /> + {/* 分隔线 */} + + {/* 1:2 布局 */} {/* 左栏:价格信息 (flex=1) */} @@ -127,14 +235,20 @@ const StockQuoteCard: React.FC = ({ {/* 右栏:关键指标 + 主力动态 (flex=2) */} - + @@ -148,9 +262,29 @@ const StockQuoteCard: React.FC = ({ {/* 公司信息区块 */} - {basicInfo && } - - + {basicInfo && ( + <> + + + + )} + + + {/* 底部光效线条 */} + + ); }; diff --git a/src/views/Company/components/StockQuoteCard/types.ts b/src/views/Company/components/StockQuoteCard/types.ts index 29c525f4..12ceab04 100644 --- a/src/views/Company/components/StockQuoteCard/types.ts +++ b/src/views/Company/components/StockQuoteCard/types.ts @@ -26,11 +26,10 @@ export interface StockQuoteCardData { // 关键指标 pe: number; // 市盈率 - eps?: number; // 每股收益 - pb: number; // 市净率 marketCap: string; // 流通市值(已格式化,如 "2.73万亿") totalShares?: number; // 发行总股本(亿股) floatShares?: number; // 流通股本(亿股) + turnoverRate?: number; // 换手率(%) week52Low: number; // 52周最低 week52High: number; // 52周最高