# Company 目录结构说明 > 最后更新:2025-12-17(API 接口清单梳理) ## 目录结构 ``` src/views/Company/ ├── index.js # 页面入口(纯组合层) ├── STRUCTURE.md # 本文档 │ ├── components/ # UI 组件 │ │ │ ├── LoadingState.tsx # 通用加载状态组件 │ │ │ ├── CompanyHeader/ # 页面头部 │ │ ├── index.js # 组合导出 │ │ └── SearchBar.js # 股票搜索栏 │ │ │ ├── CompanyTabs/ # Tab 切换容器 │ │ └── index.js # Tab 容器(状态管理 + 内容渲染) │ │ │ ├── StockQuoteCard/ # 股票行情卡片(TypeScript,数据已下沉) │ │ ├── index.tsx # 主组件(Props 从 11 个精简为 4 个) │ │ ├── types.ts # 类型定义 │ │ ├── mockData.ts # Mock 数据 │ │ ├── hooks/ # 内部数据 Hooks(2025-12-17 新增) │ │ │ ├── index.ts # hooks 导出索引 │ │ │ ├── useStockQuoteData.ts # 行情数据+基本信息获取 │ │ │ └── useStockCompare.ts # 股票对比逻辑 │ │ └── components/ # 子组件 │ │ ├── index.ts # 组件导出 │ │ ├── theme.ts # 主题配置 │ │ ├── formatters.ts # 格式化工具 │ │ ├── StockHeader.tsx # 股票头部(名称、代码、收藏按钮) │ │ ├── PriceDisplay.tsx # 价格显示组件 │ │ ├── CompanyInfo.tsx # 公司信息(行业、市值等) │ │ ├── KeyMetrics.tsx # 关键指标(PE、PB、换手率等) │ │ ├── MainForceInfo.tsx # 主力资金信息 │ │ ├── SecondaryQuote.tsx # 副行情(对比股票) │ │ ├── CompareStockInput.tsx # 对比股票输入 │ │ └── StockCompareModal.tsx # 股票对比弹窗 │ │ │ ├── CompanyOverview/ # Tab: 公司概览(TypeScript) │ │ ├── index.tsx # 主组件(组合层) │ │ ├── types.ts # 类型定义 │ │ ├── utils.ts # 格式化工具 │ │ ├── NewsEventsTab.js # 新闻事件 Tab │ │ │ │ │ ├── hooks/ # 数据 Hooks │ │ │ ├── useBasicInfo.ts # 基本信息 Hook │ │ │ ├── useShareholderData.ts # 股权结构 Hook(4 APIs) │ │ │ ├── useManagementData.ts # 管理团队 Hook │ │ │ ├── useAnnouncementsData.ts # 公告数据 Hook │ │ │ ├── useBranchesData.ts # 分支机构 Hook │ │ │ ├── useDisclosureData.ts # 披露日程 Hook │ │ │ └── useCompanyOverviewData.ts # [已废弃] 原合并 Hook │ │ │ │ │ ├── components/ # 股权结构子组件 │ │ │ └── shareholder/ │ │ │ ├── index.ts # 导出 │ │ │ ├── ActualControlCard.tsx # 实控人卡片 │ │ │ ├── ConcentrationCard.tsx # 股权集中度卡片 │ │ │ └── ShareholdersTable.tsx # 股东表格 │ │ │ │ │ ├── BasicInfoTab/ # 基本信息 Tab(可配置化) │ │ │ ├── index.tsx # 主组件(可配置) │ │ │ ├── config.ts # Tab 配置 + 黑金主题 │ │ │ ├── utils.ts # 格式化工具函数 │ │ │ └── components/ # 子组件 │ │ │ ├── index.ts # 组件统一导出 │ │ │ ├── LoadingState.tsx # 加载状态组件 │ │ │ ├── ShareholderPanel.tsx # 股权结构面板 │ │ │ ├── AnnouncementsPanel.tsx # 公告信息面板 │ │ │ ├── BranchesPanel.tsx # 分支机构面板 │ │ │ ├── BusinessInfoPanel.tsx # 工商信息面板 │ │ │ ├── DisclosureSchedulePanel.tsx # 披露日程面板 │ │ │ └── management/ # 管理团队模块 │ │ │ ├── index.ts # 模块导出 │ │ │ ├── types.ts # 类型定义 │ │ │ ├── ManagementPanel.tsx # 主组件(useMemo) │ │ │ ├── CategorySection.tsx # 分类区块(memo) │ │ │ └── ManagementCard.tsx # 人员卡片(memo) │ │ │ │ │ └── DeepAnalysisTab/ # 深度分析 Tab(原子设计模式) │ │ ├── index.tsx # 主入口组件 │ │ ├── types.ts # 类型定义 │ │ ├── atoms/ # 原子组件 │ │ │ ├── index.ts │ │ │ ├── DisclaimerBox.tsx # 免责声明 │ │ │ ├── ScoreBar.tsx # 评分进度条 │ │ │ ├── BusinessTreeItem.tsx # 业务树形项 │ │ │ ├── KeyFactorCard.tsx # 关键因素卡片 │ │ │ ├── ProcessNavigation.tsx # 流程导航 │ │ │ └── ValueChainFilterBar.tsx # 产业链筛选栏 │ │ ├── components/ # Card 组件 │ │ │ ├── index.ts │ │ │ ├── CorePositioningCard/ # 核心定位卡片(含 atoms) │ │ │ │ ├── index.tsx │ │ │ │ ├── theme.ts │ │ │ │ └── atoms/ │ │ │ ├── CompetitiveAnalysisCard.tsx │ │ │ ├── BusinessStructureCard.tsx │ │ │ ├── BusinessSegmentsCard.tsx │ │ │ ├── ValueChainCard.tsx │ │ │ ├── KeyFactorsCard.tsx │ │ │ ├── TimelineCard.tsx │ │ │ └── StrategyAnalysisCard.tsx │ │ ├── organisms/ # 复杂交互组件 │ │ │ ├── ValueChainNodeCard/ │ │ │ │ ├── index.tsx │ │ │ │ └── RelatedCompaniesModal.tsx │ │ │ └── TimelineComponent/ │ │ │ ├── index.tsx │ │ │ └── EventDetailModal.tsx │ │ ├── tabs/ # Tab 面板 │ │ │ ├── index.ts │ │ │ ├── BusinessTab.tsx │ │ │ ├── DevelopmentTab.tsx │ │ │ ├── StrategyTab.tsx │ │ │ └── ValueChainTab.tsx │ │ └── utils/ │ │ └── chartOptions.ts │ │ │ ├── MarketDataView/ # Tab: 股票行情(TypeScript) │ │ ├── index.tsx # 主组件入口 │ │ ├── types.ts # 类型定义 │ │ ├── constants.ts # 主题配置(含黑金主题 darkGoldTheme) │ │ ├── services/ │ │ │ └── marketService.ts # API 服务层 │ │ ├── hooks/ │ │ │ └── useMarketData.ts # 数据获取 Hook │ │ ├── utils/ │ │ │ ├── formatUtils.ts # 格式化工具函数 │ │ │ └── chartOptions.ts # ECharts 图表配置 │ │ └── components/ │ │ ├── index.ts # 组件导出 │ │ ├── ThemedCard.tsx # 主题化卡片 │ │ ├── MarkdownRenderer.tsx # Markdown 渲染 │ │ ├── AnalysisModal.tsx # 涨幅分析模态框 │ │ ├── StockSummaryCard/ # 股票概览卡片(黑金主题 4 列布局) │ │ │ ├── index.tsx │ │ │ ├── StockHeaderCard.tsx │ │ │ ├── MetricCard.tsx │ │ │ ├── utils.ts │ │ │ └── atoms/ │ │ │ ├── index.ts │ │ │ ├── DarkGoldCard.tsx │ │ │ ├── CardTitle.tsx │ │ │ ├── MetricValue.tsx │ │ │ ├── PriceDisplay.tsx │ │ │ └── StatusTag.tsx │ │ └── panels/ # Tab 面板组件 │ │ ├── index.ts │ │ ├── TradeDataPanel/ │ │ │ ├── index.tsx │ │ │ └── KLineModule.tsx │ │ ├── FundingPanel.tsx │ │ ├── BigDealPanel.tsx │ │ ├── UnusualPanel.tsx │ │ └── PledgePanel.tsx │ │ │ ├── DeepAnalysis/ # Tab: 深度分析(入口) │ │ └── index.js │ │ │ ├── DynamicTracking/ # Tab: 动态跟踪 │ │ ├── index.js # 主组件 │ │ └── components/ │ │ ├── index.js # 组件导出 │ │ ├── NewsPanel.js # 新闻面板 │ │ └── ForecastPanel.js # 业绩预告面板 │ │ │ ├── FinancialPanorama/ # Tab: 财务全景(TypeScript 模块化) │ │ ├── index.tsx # 主组件入口 │ │ ├── types.ts # TypeScript 类型定义 │ │ ├── constants.ts # 常量配置(颜色、指标定义) │ │ ├── hooks/ │ │ │ ├── index.ts │ │ │ └── useFinancialData.ts │ │ ├── utils/ │ │ │ ├── index.ts │ │ │ ├── calculations.ts │ │ │ └── chartOptions.ts │ │ ├── tabs/ # Tab 面板组件 │ │ │ ├── index.ts │ │ │ ├── BalanceSheetTab.tsx │ │ │ ├── CashflowTab.tsx │ │ │ ├── FinancialMetricsTab.tsx │ │ │ ├── IncomeStatementTab.tsx │ │ │ └── MetricsCategoryTab.tsx │ │ └── components/ │ │ ├── index.ts │ │ ├── StockInfoHeader.tsx │ │ ├── FinancialTable.tsx # 通用财务表格 │ │ ├── FinancialOverviewPanel.tsx # 财务概览面板 │ │ ├── KeyMetricsOverview.tsx # 关键指标概览 │ │ ├── PeriodSelector.tsx # 期数选择器 │ │ ├── BalanceSheetTable.tsx │ │ ├── IncomeStatementTable.tsx │ │ ├── CashflowTable.tsx │ │ ├── FinancialMetricsTable.tsx │ │ ├── MainBusinessAnalysis.tsx │ │ ├── IndustryRankingView.tsx │ │ ├── StockComparison.tsx │ │ └── ComparisonAnalysis.tsx │ │ │ └── ForecastReport/ # Tab: 盈利预测(TypeScript,已模块化) │ ├── index.tsx # 主组件入口 │ ├── types.ts # 类型定义 │ ├── constants.ts # 配色、图表配置常量 │ └── components/ │ ├── index.ts │ ├── ChartCard.tsx # 图表卡片容器 │ ├── IncomeProfitGrowthChart.tsx # 营收与利润趋势图 │ ├── IncomeProfitChart.tsx # 营收利润图(备用) │ ├── GrowthChart.tsx # 增长率图(备用) │ ├── EpsChart.tsx # EPS 趋势图 │ ├── PePegChart.tsx # PE/PEG 分析图 │ └── DetailTable.tsx # 详细数据表格 │ ├── hooks/ # 页面级 Hooks │ ├── useCompanyStock.js # 股票代码管理(URL 同步) │ ├── useCompanyWatchlist.js # 自选股管理(Redux 集成) │ └── useCompanyEvents.js # PostHog 事件追踪 │ # 注:useStockQuote.js 已下沉到 StockQuoteCard/hooks/useStockQuoteData.ts │ └── constants/ # 常量定义 └── index.js # Tab 配置、Toast 消息、默认值 ``` --- ## API 接口清单 Company 模块共使用 **27 个** API 接口(去重后)。 ### 一、股票基础信息 (8 个) | 接口 | 方法 | 调用位置 | |------|------|----------| | `/api/stock/${stockCode}/basic-info` | GET | useBasicInfo.ts, useStockQuoteData.ts, NewsPanel.js | | `/api/stock/${stockCode}/branches` | GET | useBranchesData.ts | | `/api/stock/${stockCode}/management?active_only=true` | GET | useManagementData.ts | | `/api/stock/${stockCode}/announcements?limit=20` | GET | useAnnouncementsData.ts | | `/api/stock/${stockCode}/disclosure-schedule` | GET | useDisclosureData.ts | | `/api/stock/${stockCode}/forecast` | GET | ForecastPanel.js | | `/api/stock/${stockCode}/forecast-report` | GET | ForecastReport/index.tsx | | `/api/stock/${stockCode}/latest-minute` | GET | marketService.ts | ### 二、股东信息 (4 个) | 接口 | 方法 | 调用位置 | |------|------|----------| | `/api/stock/${stockCode}/actual-control` | GET | useShareholderData.ts | | `/api/stock/${stockCode}/concentration` | GET | useShareholderData.ts | | `/api/stock/${stockCode}/top-shareholders?limit=10` | GET | useShareholderData.ts | | `/api/stock/${stockCode}/top-circulation-shareholders?limit=10` | GET | useShareholderData.ts | ### 三、行情数据 (8 个) | 接口 | 方法 | 调用位置 | |------|------|----------| | `/api/stock/quotes` | POST | stockService.getQuotes | | `/api/market/summary/${stockCode}` | GET | marketService.ts | | `/api/market/trade/${stockCode}?days=${days}` | GET | marketService.ts | | `/api/market/funding/${stockCode}?days=${days}` | GET | marketService.ts | | `/api/market/bigdeal/${stockCode}?days=${days}` | GET | marketService.ts | | `/api/market/unusual/${stockCode}?days=${days}` | GET | marketService.ts | | `/api/market/pledge/${stockCode}` | GET | marketService.ts | | `/api/market/rise-analysis/${stockCode}` | GET | marketService.ts | ### 四、深度分析 (5 个) | 接口 | 方法 | 调用位置 | |------|------|----------| | `/api/company/comprehensive-analysis/${stockCode}` | GET | DeepAnalysis/index.js | | `/api/company/value-chain-analysis/${stockCode}` | GET | DeepAnalysis/index.js | | `/api/company/key-factors-timeline/${stockCode}` | GET | DeepAnalysis/index.js | | `/api/company/value-chain/related-companies?node_name=...` | GET | ValueChainNodeCard/index.tsx | | `/api/financial/industry-rank/${stockCode}` | GET | DeepAnalysis/index.js | ### 五、财务数据 (1 个) | 接口 | 方法 | 调用位置 | |------|------|----------| | `/api/financial/financial-metrics/${stockCode}?limit=${limit}` | GET | financialService.getFinancialMetrics | ### 六、事件/新闻 (1 个) | 接口 | 方法 | 调用位置 | |------|------|----------| | `/api/events?q=${searchTerm}&page=${page}&per_page=10` | GET | NewsPanel.js | ### 统计汇总 | 分类 | 数量 | |------|------| | 股票基础信息 | 8 | | 股东信息 | 4 | | 行情数据 | 8 | | 深度分析 | 5 | | 财务数据 | 1 | | 事件/新闻 | 1 | | **去重后总计** | **27** | > 注:`/api/stock/${stockCode}/basic-info` 在 3 处调用,但只算 1 个接口。 --- ## 文件职责说明 ### 入口文件 #### `index.js` - 页面入口 - **职责**:纯组合层,协调 Hooks 和 Components - **代码行数**:~105 行(2025-12-17 优化后精简) - **依赖**: - `useCompanyStock` - 股票代码状态 - `useCompanyWatchlist` - 自选股状态 - `useCompanyEvents` - 事件追踪 - `CompanyHeader` - 页面头部 - `StockQuoteCard` - 股票行情卡片(内部自行获取数据) - `CompanyTabs` - Tab 切换区 - **已移除**(2025-12-17): - `useStockQuote` - 已下沉到 StockQuoteCard - `useBasicInfo` - 已下沉到 StockQuoteCard - 股票对比逻辑 - 已下沉到 StockQuoteCard --- ### Hooks 目录 #### `useCompanyStock.js` - 股票代码管理 - **功能**: - 管理当前股票代码状态 - 双向同步 URL 参数(支持浏览器前进/后退) - 处理搜索输入和提交 - **返回值**: ```js { stockCode, // 当前确认的股票代码 inputCode, // 输入框中的值(未确认) setInputCode, // 更新输入框 handleSearch, // 执行搜索 handleKeyPress, // 处理回车键 } ``` - **依赖**:`react-router-dom` (useSearchParams) #### `useCompanyWatchlist.js` - 自选股管理 - **功能**: - 检查当前股票是否在自选股中 - 提供添加/移除自选股功能 - 与 Redux stockSlice 同步 - **返回值**: ```js { isInWatchlist, // 是否在自选股中 isLoading, // 操作进行中 toggle, // 切换自选状态 } ``` - **依赖**:Redux (`stockSlice`)、`AuthContext`、Chakra UI (useToast) #### `useCompanyEvents.js` - 事件追踪 - **功能**: - 页面浏览追踪 - 股票搜索追踪 - Tab 切换追踪 - 自选股操作追踪 - **返回值**: ```js { trackStockSearched, // 追踪股票搜索 trackTabChanged, // 追踪 Tab 切换 trackWatchlistAdded, // 追踪添加自选 trackWatchlistRemoved, // 追踪移除自选 } ``` - **依赖**:PostHog (`usePostHogTrack`) --- ### Components 目录 #### `CompanyHeader/` - 页面头部 | 文件 | 职责 | |------|------| | `index.js` | 组合 SearchBar 和 WatchlistButton | | `SearchBar.js` | 股票代码搜索输入框 | | `WatchlistButton.js` | 自选股添加/移除按钮 | **Props 接口**: ```js ``` #### `CompanyTabs/` - Tab 切换 | 文件 | 职责 | |------|------| | `index.js` | Tab 容器,管理切换状态,渲染 Tab 内容 | | `TabNavigation.js` | Tab 导航栏(4个 Tab 按钮) | **Props 接口**: ```js ``` --- ### Constants 目录 #### `constants/index.js` - 常量配置 - `COMPANY_TABS` - Tab 配置数组(key, name, icon) - `TAB_SELECTED_STYLE` - Tab 选中样式 - `TOAST_MESSAGES` - Toast 消息配置 - `DEFAULT_STOCK_CODE` - 默认股票代码 ('000001') - `URL_PARAM_NAME` - URL 参数名 ('scode') - `getTabNameByIndex()` - 根据索引获取 Tab 名称 --- ### Tab 内容组件(`components/` 目录下) | 组件 | Tab 名称 | 职责 | 代码行数 | |------|----------|------|----------| | `CompanyOverview/` | 公司概览 | 公司基本信息、相关事件 | - | | `MarketDataView/` | 股票行情 | K线图、实时行情 | - | | `FinancialPanorama/` | 财务全景 | 财务报表、指标分析 | 2153 行 | | `ForecastReport/` | 盈利预测 | 分析师预测、目标价 | 161 行 | > 📌 所有 Tab 内容组件已文件夹化并统一放置在 `components/` 目录下 --- ## 数据流示意 ``` ┌─────────────────────────────────────────────────────────────┐ │ index.js (页面入口) │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │ │ │ useCompanyStock │ │useCompanyWatchlist│ │useCompanyEvents│ │ │ │ │ │ │ │ │ │ │ • stockCode │ │ • isInWatchlist │ │ • track* │ │ │ │ • inputCode │ │ • toggle │ │ functions │ │ │ │ • handleSearch │ │ │ │ │ │ │ └────────┬────────┘ └────────┬────────┘ └──────┬──────┘ │ │ │ │ │ │ │ └──────────┬─────────┴───────────────────┘ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────┐ │ │ │ CompanyHeader │ │ │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │ │ │ SearchBar │ │ WatchlistButton │ │ │ │ │ └─────────────┘ └──────────────────┘ │ │ │ └───────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────┐ │ │ │ CompanyTabs │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ TabNavigation │ │ │ │ │ │ [概览] [行情] [财务] [预测] │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ TabPanels │ │ │ │ │ │ • CompanyOverview │ │ │ │ │ │ • MarketDataView │ │ │ │ │ │ • FinancialPanorama │ │ │ │ │ │ • ForecastReport │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 重构记录 ### 2025-12-09 重构 **改动概述**: - `index.js` 从 **349 行** 精简至 **95 行**(减少 73%) - 提取 **3 个自定义 Hooks** - 提取 **2 个组件目录**(CompanyHeader、CompanyTabs) - 抽离常量到 `constants/index.js` **修复的问题**: 1. **无限循环 Bug**:`useCompanyWatchlist` 中使用 `useRef` 防止重复初始化 2. **Hook 调用顺序**:确保 `useCompanyEvents` 在 `useCompanyStock` 之后调用(依赖 stockCode) 3. **类型检查**:`CompanyOverview.js` 中 `event.keywords` 渲染时添加类型检查,支持字符串和对象两种格式 **设计原则**: - **关注点分离**:每个 Hook 只负责单一职责 - **纯组合层**:index.js 不包含业务逻辑,只负责组合 - **Props 透传**:通过 Props 将状态和回调传递给子组件 ### 2025-12-09 文件夹化 **改动概述**: - 所有 4 个 Tab 内容组件统一移动到 `components/` 目录 - `CompanyOverview.js` → `components/CompanyOverview/index.js` - `MarketDataView.js` → `components/MarketDataView/index.js` - `FinancialPanorama.js` → `components/FinancialPanorama/index.js`(2153 行) - `ForecastReport.js` → `components/ForecastReport/index.js`(161 行) - 更新 `CompanyTabs/index.js` 中的导入路径 **目的**: - 统一目录结构,所有组件都在 `components/` 下 - 为后期组件拆分做准备,便于添加子组件、hooks、utils 等 ### 2025-12-10 CompanyOverview 拆分(TypeScript) **改动概述**: - `CompanyOverview/index.js` 从 **330 行** 精简至 **50 行**(减少 85%) - 采用 **TypeScript** 进行拆分,提高类型安全性 - 提取 **1 个自定义 Hook**(`useCompanyOverviewData`) - 提取 **1 个子组件**(`CompanyHeaderCard`) - 抽离类型定义到 `types.ts` - 抽离工具函数到 `utils.ts` **拆分后文件结构**: ``` CompanyOverview/ ├── index.tsx # 主组件(组合层,约 60 行) ├── CompanyHeaderCard.tsx # 头部卡片组件(约 130 行) ├── BasicInfoTab.js # 基本信息 Tab(懒加载版本,约 994 行) ├── DeepAnalysisTab/ # 深度分析 Tab(21 个 TS 文件,见 2025-12-11 重构记录) ├── NewsEventsTab.js # 新闻事件 Tab ├── types.ts # 类型定义(约 50 行) ├── utils.ts # 格式化工具(约 20 行) └── hooks/ ├── useBasicInfo.ts # 基本信息 Hook(1 API) ├── useShareholderData.ts # 股权结构 Hook(4 APIs) ├── useManagementData.ts # 管理团队 Hook(1 API) ├── useAnnouncementsData.ts # 公告数据 Hook(1 API) ├── useBranchesData.ts # 分支机构 Hook(1 API) ├── useDisclosureData.ts # 披露日程 Hook(1 API) └── useCompanyOverviewData.ts # [已废弃] 原合并 Hook ``` **懒加载架构**(2025-12-10 优化): - `index.tsx` 只加载 `useBasicInfo`(1 个 API)用于头部卡片 - `BasicInfoTab.js` 使用 `isLazy` + 独立子组件实现懒加载 - 每个内层 Tab 使用独立 Hook,点击时才加载数据 **Hooks 说明**: | Hook | API 数量 | 用途 | |------|----------|------| | `useBasicInfo` | 1 | 公司基本信息(头部卡片 + 工商信息 Tab) | | `useShareholderData` | 4 | 实控人、股权集中度、十大股东、十大流通股东 | | `useManagementData` | 1 | 管理团队数据 | | `useAnnouncementsData` | 1 | 公司公告列表 | | `useBranchesData` | 1 | 分支机构列表 | | `useDisclosureData` | 1 | 财报披露日程 | **类型定义**(`types.ts`): - `BasicInfo` - 公司基本信息 - `ActualControl` - 实际控制人 - `Concentration` - 股权集中度 - `Management` - 管理层信息 - `Shareholder` - 股东信息 - `Branch` - 分支机构 - `Announcement` - 公告信息 - `DisclosureSchedule` - 披露计划 - `CompanyOverviewData` - Hook 返回值类型 - `CompanyOverviewProps` - 组件 Props 类型 - `CompanyHeaderCardProps` - 头部卡片 Props 类型 **工具函数**(`utils.ts`): - `formatRegisteredCapital(value)` - 格式化注册资本(万元/亿元) - `formatDate(dateString)` - 格式化日期 **设计原则**: - **渐进式 TypeScript 迁移**:新拆分的文件使用 TypeScript,旧文件暂保持 JS - **关注点分离**:数据加载逻辑提取到 Hook,UI 逻辑保留在组件 - **类型复用**:统一的类型定义便于在多个文件间共享 - **懒加载优化**:减少首屏 API 请求,按需加载数据 ### 2025-12-10 懒加载优化 **改动概述**: - 将 `useCompanyOverviewData`(9 个 API)拆分为 6 个独立 Hook - `CompanyOverview/index.tsx` 只加载 `useBasicInfo`(1 个 API) - `BasicInfoTab.js` 使用 5 个懒加载子组件,配合 `isLazy` 实现按需加载 - 页面初次加载从 **9 个 API** 减少到 **1 个 API** **懒加载子组件**(BasicInfoTab.js 内部): | 子组件 | Hook | 功能 | |--------|------|------| | `ShareholderTabPanel` | `useShareholderData` | 股权结构(4 APIs) | | `ManagementTabPanel` | `useManagementData` | 管理团队 | | `AnnouncementsTabPanel` | `useAnnouncementsData` + `useDisclosureData` | 公告 + 披露日程 | | `BranchesTabPanel` | `useBranchesData` | 分支机构 | | `BusinessInfoTabPanel` | - | 工商信息(使用父组件传入的 basicInfo) | **实现原理**: - Chakra UI `Tabs` 的 `isLazy` 属性延迟渲染 TabPanel - 每个 TabPanel 使用独立子组件,组件内调用 Hook - 子组件只在首次激活时渲染,此时 Hook 才执行并发起 API 请求 | Tab 模块 | 中文名称 | 功能说明 | |-------------------|------|----------------------------| | CompanyOverview | 公司概览 | 公司基本信息、股权结构、管理层、公告等(9个接口) | | DeepAnalysis | 深度分析 | 公司深度研究报告、投资逻辑分析 | | MarketDataView | 股票行情 | K线图、实时行情、技术指标 | | FinancialPanorama | 财务全景 | 财务报表(资产负债表、利润表、现金流)、财务指标分析 | | ForecastReport | 盈利预测 | 分析师预测、目标价、评级 | | DynamicTracking | 动态跟踪 | 相关事件、新闻动态、投资日历 | ### 2025-12-10 MarketDataView TypeScript 拆分 **改动概述**: - `MarketDataView/index.js` 从 **2060 行** 拆分为 **12 个 TypeScript 文件** - 采用 **TypeScript** 进行重构,提高类型安全性 - 提取 **1 个自定义 Hook**(`useMarketData`) - 提取 **4 个子组件**(ThemedCard、MarkdownRenderer、StockSummaryCard、AnalysisModal) - 抽离 API 服务到 `services/marketService.ts` - 抽离图表配置到 `utils/chartOptions.ts` **拆分后文件结构**: ``` MarketDataView/ ├── index.tsx # 主组件入口(~285 行,Tab 容器) ├── types.ts # 类型定义(~383 行) ├── constants.ts # 主题配置、常量(~49 行) ├── services/ │ └── marketService.ts # API 服务层(~173 行) ├── hooks/ │ └── useMarketData.ts # 数据获取 Hook(~193 行) ├── utils/ │ ├── formatUtils.ts # 格式化工具函数(~175 行) │ └── chartOptions.ts # ECharts 图表配置生成器(~698 行) └── components/ ├── index.ts # 组件导出(~8 行) ├── ThemedCard.tsx # 主题化卡片(~32 行) ├── MarkdownRenderer.tsx # Markdown 渲染(~65 行) ├── StockSummaryCard.tsx # 股票概览卡片(~133 行) ├── AnalysisModal.tsx # 涨幅分析模态框(~188 行) └── panels/ # Tab 面板组件(2025-12-12 拆分) ├── index.ts # 面板组件统一导出 ├── TradeDataPanel.tsx # 交易数据面板(~381 行) ├── FundingPanel.tsx # 融资融券面板(~113 行) ├── BigDealPanel.tsx # 大宗交易面板(~143 行) ├── UnusualPanel.tsx # 龙虎榜面板(~163 行) └── PledgePanel.tsx # 股权质押面板(~124 行) ``` **文件职责说明**: | 文件 | 行数 | 职责 | |------|------|------| | `index.tsx` | ~285 | 主组件,Tab 容器和状态管理,导入使用 5 个 Panel 组件 | | `types.ts` | ~383 | 所有 TypeScript 类型定义(Theme、TradeDayData、MinuteData、FundingData 等) | | `constants.ts` | ~49 | 主题配置(light/dark)、周期选项常量 | | `marketService.ts` | ~173 | API 服务封装(getMarketData、getMinuteData、getBigDealData 等) | | `useMarketData.ts` | ~193 | 数据获取 Hook,管理所有市场数据状态 | | `formatUtils.ts` | ~175 | 数字/日期/涨跌幅格式化工具 | | `chartOptions.ts` | ~698 | ECharts 配置生成器(K线图、分钟图、融资融券图、质押图) | | `ThemedCard.tsx` | ~32 | 主题化卡片容器组件 | | `MarkdownRenderer.tsx` | ~65 | Markdown 内容渲染组件 | | `StockSummaryCard.tsx` | ~133 | 股票概览卡片(价格、涨跌幅、成交量等) | | `AnalysisModal.tsx` | ~188 | 涨幅分析详情模态框 | **类型定义**(`types.ts`): - `Theme` - 主题配置类型 - `TradeDayData` - 日线交易数据 - `MinuteData` - 分钟线数据 - `FundingDayData` - 融资融券数据 - `BigDealData` / `BigDealDayStats` - 大宗交易数据 - `UnusualData` / `UnusualDayData` - 龙虎榜数据 - `PledgeData` - 股权质押数据 - `RiseAnalysis` - 涨幅分析数据 - `MarketSummary` - 市场概览数据 - `VerificationReport` - 验证报告数据 - 各组件 Props 类型 **Hook 返回值**(`useMarketData`): ```typescript { loading: boolean; summary: MarketSummary | null; tradeData: TradeDayData[]; minuteData: MinuteData | null; minuteLoading: boolean; fundingData: FundingDayData[]; bigDealData: BigDealData | null; unusualData: UnusualData | null; pledgeData: PledgeData | null; analysisMap: Record; refetch: () => Promise; loadMinuteData: () => Promise; } ``` **设计原则**: - **TypeScript 类型安全**:所有数据结构有完整类型定义 - **服务层分离**:API 调用统一在 `marketService.ts` 中管理 - **图表配置抽离**:复杂的 ECharts 配置集中在 `chartOptions.ts` - **组件复用**:通用组件(ThemedCard、MarkdownRenderer)可在其他模块使用 ### 2025-12-10 ManagementPanel 拆分重构 **改动概述**: - `ManagementPanel.tsx` 从 **180 行** 拆分为 **5 个 TypeScript 文件** - 创建 `management/` 子目录,模块化管理 - 添加性能优化(`useMemo`、`React.memo`) **拆分后文件结构**: ``` components/management/ ├── index.ts # 模块导出 ├── types.ts # 类型定义(~35 行) ├── ManagementPanel.tsx # 主组件(~105 行,useMemo 优化) ├── CategorySection.tsx # 分类区块组件(~65 行,memo) └── ManagementCard.tsx # 人员卡片组件(~100 行,memo) ``` **类型定义**(`types.ts`): - `ManagementPerson` - 管理人员信息 - `ManagementCategory` - 分类类型(高管/董事/监事/其他) - `CategorizedManagement` - 分类后的数据结构 - `CategoryConfig` - 分类配置(图标、颜色) **性能优化**: - `useMemo` - 缓存 `categorizeManagement()` 分类计算结果 - `React.memo` - `ManagementCard` 和 `CategorySection` 使用 memo 包装 - 常量提取 - `CATEGORY_CONFIG` 和 `CATEGORY_ORDER` 提取到组件外部 **设计原则**: - **职责分离**:卡片渲染、分类区块、数据处理各自独立 - **类型安全**:消除 `any` 类型,完整的 TypeScript 类型定义 - **可复用性**:`ManagementCard` 可独立使用 ### 2025-12-11 DeepAnalysisTab 模块化拆分(TypeScript) **改动概述**: - `DeepAnalysisTab.js` 从 **1,796 行** 拆分为 **21 个 TypeScript 文件** - 采用**原子设计模式**(atoms/components/organisms)组织代码 - 完整 TypeScript 类型定义 - 格式化工具合并到全局 `src/utils/priceFormatters.js` **拆分后文件结构**: ``` DeepAnalysisTab/ ├── index.tsx # 主入口组件,组合所有 Card 子组件 ├── types.ts # TypeScript 类型定义(接口、数据结构) ├── atoms/ # 原子组件(基础 UI 元素) │ ├── index.ts # 原子组件统一导出 │ ├── DisclaimerBox.tsx # 免责声明警告框(黄色 Alert,用 6 次) │ ├── ScoreBar.tsx # 评分进度条(带颜色渐变,用 8 次) │ ├── BusinessTreeItem.tsx # 业务结构树形项(递归组件) │ └── KeyFactorCard.tsx # 关键因素卡片(带影响方向图标) ├── components/ # Card 容器组件(页面区块) │ ├── index.ts # Card 组件统一导出 │ ├── CorePositioningCard.tsx # 核心定位卡片(行业地位、核心优势) │ ├── CompetitiveAnalysisCard.tsx # 竞争地位分析卡片(雷达图 + 评分条) │ ├── BusinessStructureCard.tsx # 业务结构分析卡片(树形展示) │ ├── ValueChainCard.tsx # 产业链分析卡片(Tabs: 上游/中游/下游) │ ├── KeyFactorsCard.tsx # 关键因素卡片(Accordion 折叠面板) │ ├── TimelineCard.tsx # 发展时间线卡片(正面/负面事件统计) │ ├── BusinessSegmentsCard.tsx # 业务板块详情卡片(可展开/折叠) │ └── StrategyAnalysisCard.tsx # 战略分析卡片(战略方向 + 战略举措) ├── organisms/ # 复杂组件(含状态管理和 API 调用) │ ├── ValueChainNodeCard/ # 产业链节点组件 │ │ ├── index.tsx # 产业链节点卡片(点击展开详情) │ │ └── RelatedCompaniesModal.tsx # 相关公司模态框(API 获取公司列表) │ └── TimelineComponent/ # 时间线组件 │ ├── index.tsx # 时间线主组件(事件列表渲染) │ └── EventDetailModal.tsx # 事件详情模态框(查看完整事件信息) └── utils/ └── chartOptions.ts # ECharts 图表配置(雷达图、桑基图) ``` **组件依赖关系**: ``` index.tsx ├── CorePositioningCard ├── CompetitiveAnalysisCard │ ├── ScoreBar (atom) │ ├── DisclaimerBox (atom) │ └── ReactECharts (雷达图) ├── BusinessStructureCard │ └── BusinessTreeItem (atom, 递归) ├── ValueChainCard │ └── ValueChainNodeCard (organism) │ └── RelatedCompaniesModal ├── KeyFactorsCard │ └── KeyFactorCard (atom) ├── TimelineCard │ └── TimelineComponent (organism) │ └── EventDetailModal ├── BusinessSegmentsCard └── StrategyAnalysisCard └── DisclaimerBox (atom) ``` **类型定义**(`types.ts`): - `DeepAnalysisTabProps` - 主组件 Props - `QualitativeAnalysis` - 定性分析数据 - `CompetitivePosition` - 竞争地位数据 - `BusinessStructureItem` - 业务结构项 - `ValueChainData` - 产业链数据 - `ValueChainNode` - 产业链节点 - `KeyFactor` - 关键因素 - `DevelopmentTimeline` - 发展时间线 - `TimelineEvent` - 时间线事件 - `BusinessSegment` - 业务板块 - `Strategy` - 战略分析 **工具函数位置**: | 函数 | 文件位置 | 说明 | |------|----------|------| | `formatCurrency` | `src/utils/priceFormatters.js` | 货币格式化 | | `formatBusinessRevenue` | `src/utils/priceFormatters.js` | 营收格式化(亿/万) | | `formatPercentage` | `src/utils/priceFormatters.js` | 百分比格式化 | | `getRadarChartOption` | `DeepAnalysisTab/utils/chartOptions.ts` | 雷达图 ECharts 配置 | | `getSankeyChartOption` | `DeepAnalysisTab/utils/chartOptions.ts` | 桑基图 ECharts 配置 | **优化效果**: | 指标 | 优化前 | 优化后 | 改善 | |------|--------|--------|------| | 主文件行数 | 1,796 | ~117 | -93% | | 文件数量 | 1 (.js) | 21 (.tsx/.ts) | 模块化 + TS | | 可复用组件 | 0 | 4 原子 + 2 复杂 | 提升 | | 类型安全 | 无 | 完整 | TypeScript | **设计原则**: - **原子设计模式**:atoms(基础元素)→ components(区块)→ organisms(复杂交互) - **TypeScript 类型安全**:完整的接口定义,消除 any 类型 - **职责分离**:UI 渲染与 API 调用分离,模态框独立管理 - **代码复用**:DisclaimerBox、ScoreBar 等原子组件多处复用 ### 2025-12-12 FinancialPanorama 模块化拆分(TypeScript) **改动概述**: - `FinancialPanorama/index.js` 从 **2,150 行** 拆分为 **21 个 TypeScript 文件** - 提取 **1 个自定义 Hook**(`useFinancialData`) - 提取 **9 个子组件**(表格组件 + 分析组件) - 抽离类型定义到 `types.ts` - 抽离常量配置到 `constants.ts` - 抽离工具函数到 `utils/` **拆分后文件结构**: ``` FinancialPanorama/ ├── index.tsx # 主入口组件(~400 行) ├── types.ts # TypeScript 类型定义(~441 行) ├── constants.ts # 常量配置(颜色、指标定义) ├── hooks/ │ ├── index.ts # Hook 统一导出 │ └── useFinancialData.ts # 财务数据加载 Hook(9 API 并行加载) ├── utils/ │ ├── index.ts # 工具函数统一导出 │ ├── calculations.ts # 计算工具(同比变化率、单元格背景色) │ └── chartOptions.ts # ECharts 图表配置生成器 └── components/ ├── index.ts # 组件统一导出 ├── StockInfoHeader.tsx # 股票信息头部(~95 行) ├── BalanceSheetTable.tsx # 资产负债表(~220 行,可展开分组) ├── IncomeStatementTable.tsx # 利润表(~205 行,可展开分组) ├── CashflowTable.tsx # 现金流量表(~140 行) ├── FinancialMetricsTable.tsx # 财务指标表(~260 行,7 分类切换) ├── MainBusinessAnalysis.tsx # 主营业务分析(~180 行,饼图 + 表格) ├── IndustryRankingView.tsx # 行业排名(~110 行) ├── StockComparison.tsx # 股票对比(~210 行,含独立数据加载) └── ComparisonAnalysis.tsx # 综合对比分析(~40 行) ``` **组件依赖关系**: ``` index.tsx ├── useFinancialData (hook) # 数据加载 ├── StockInfoHeader # 股票基本信息展示 ├── ComparisonAnalysis # 营收与利润趋势图 ├── FinancialMetricsTable # 财务指标表(7 分类) ├── BalanceSheetTable # 资产负债表(可展开) ├── IncomeStatementTable # 利润表(可展开) ├── CashflowTable # 现金流量表 ├── MainBusinessAnalysis # 主营业务(饼图) ├── IndustryRankingView # 行业排名 └── StockComparison # 股票对比(独立状态) ``` **类型定义**(`types.ts`): - `StockInfo` - 股票基本信息 - `BalanceSheetData` - 资产负债表数据 - `IncomeStatementData` - 利润表数据 - `CashflowData` - 现金流量表数据 - `FinancialMetricsData` - 财务指标数据(7 分类) - `ProductClassification` / `IndustryClassification` - 主营业务分类 - `IndustryRankData` - 行业排名数据 - `ForecastData` - 业绩预告数据 - `ComparisonData` - 对比数据 - `MetricConfig` / `MetricSectionConfig` - 指标配置类型 - 各组件 Props 类型 **常量配置**(`constants.ts`): - `COLORS` - 颜色配置(中国市场:红涨绿跌) - `CURRENT_ASSETS_METRICS` / `NON_CURRENT_ASSETS_METRICS` 等 - 资产负债表指标 - `INCOME_STATEMENT_SECTIONS` - 利润表分组配置 - `CASHFLOW_METRICS` - 现金流量表指标 - `FINANCIAL_METRICS_CATEGORIES` - 财务指标 7 大分类 - `RANKING_METRICS` / `COMPARE_METRICS` - 排名和对比指标 **工具函数**(`utils/`): | 函数 | 文件 | 说明 | |------|------|------| | `calculateYoYChange` | calculations.ts | 计算同比变化率和强度 | | `getCellBackground` | calculations.ts | 根据变化率返回单元格背景色 | | `getValueByPath` | calculations.ts | 从嵌套对象获取值 | | `isNegativeIndicator` | calculations.ts | 判断是否为负向指标 | | `getMetricChartOption` | chartOptions.ts | 指标趋势图配置 | | `getComparisonChartOption` | chartOptions.ts | 营收与利润对比图配置 | | `getMainBusinessPieOption` | chartOptions.ts | 主营业务饼图配置 | | `getCompareBarChartOption` | chartOptions.ts | 股票对比柱状图配置 | **Hook 返回值**(`useFinancialData`): ```typescript { // 数据状态 stockInfo: StockInfo | null; balanceSheet: BalanceSheetData[]; incomeStatement: IncomeStatementData[]; cashflow: CashflowData[]; financialMetrics: FinancialMetricsData[]; mainBusiness: MainBusinessData | null; forecast: ForecastData | null; industryRank: IndustryRankData[]; comparison: ComparisonData[]; // 加载状态 loading: boolean; error: string | null; // 操作方法 refetch: () => Promise; setStockCode: (code: string) => void; setSelectedPeriods: (periods: number) => void; // 当前参数 currentStockCode: string; selectedPeriods: number; } ``` **优化效果**: | 指标 | 优化前 | 优化后 | 改善 | |------|--------|--------|------| | 主文件行数 | 2,150 | ~400 | -81% | | 文件数量 | 1 (.js) | 21 (.tsx/.ts) | 模块化 + TS | | 可复用组件 | 0(内联) | 9 个独立组件 | 提升 | | 类型安全 | 无 | 完整 | TypeScript | **设计原则**: - **TypeScript 类型安全**:完整的接口定义,消除 any 类型 - **Hook 数据层**:`useFinancialData` 封装 9 个 API 并行加载 - **组件解耦**:每个表格/分析视图独立为组件 - **常量配置化**:指标定义可维护、可扩展 - **工具函数复用**:计算和图表配置统一管理 ### 2025-12-12 MarketDataView Panel 拆分 **改动概述**: - `MarketDataView/index.tsx` 从 **1,049 行** 精简至 **285 行**(减少 73%) - 将 5 个 TabPanel 拆分为独立的面板组件 - 创建 `components/panels/` 子目录 **拆分后文件结构**: ``` MarketDataView/components/panels/ ├── index.ts # 面板组件统一导出 ├── TradeDataPanel.tsx # 交易数据面板(~381 行) ├── FundingPanel.tsx # 融资融券面板(~113 行) ├── BigDealPanel.tsx # 大宗交易面板(~143 行) ├── UnusualPanel.tsx # 龙虎榜面板(~163 行) └── PledgePanel.tsx # 股权质押面板(~124 行) ``` **面板组件职责**: | 组件 | 行数 | 功能 | |------|------|------| | `TradeDataPanel` | ~381 | K线图、分钟K线图、交易明细表格 | | `FundingPanel` | ~113 | 融资融券图表和数据卡片 | | `BigDealPanel` | ~143 | 大宗交易记录表格 | | `UnusualPanel` | ~163 | 龙虎榜数据(买入/卖出前五) | | `PledgePanel` | ~124 | 股权质押图表和明细表格 | **优化效果**: | 指标 | 优化前 | 优化后 | 改善 | |------|--------|--------|------| | 主文件行数 | 1,049 | 285 | -73% | | 面板组件 | 内联 | 5 个独立文件 | 模块化 | | 可维护性 | 低 | 高 | 每个面板独立维护 | **设计原则**: - **职责分离**:主组件只负责 Tab 容器和状态管理 - **组件复用**:面板组件可独立测试和维护 - **类型安全**:每个面板组件有独立的 Props 类型定义 ### 2025-12-16 StockSummaryCard 黑金主题重构 **改动概述**: - `StockSummaryCard.tsx` 从单文件重构为**原子设计模式**的目录结构 - 布局从 **1+3**(头部+三卡片)改为 **4 列横向排列** - 新增**黑金主题**(`darkGoldTheme`) - 提取 **5 个原子组件** + **2 个业务组件** **拆分后文件结构**: ``` StockSummaryCard/ ├── index.tsx # 主组件(4 列 SimpleGrid 布局) ├── StockHeaderCard.tsx # 股票信息卡片(名称、价格、涨跌幅、走势) ├── MetricCard.tsx # 指标卡片模板组件 ├── utils.ts # 状态计算工具函数 └── atoms/ # 原子组件 ├── index.ts # 统一导出 ├── DarkGoldCard.tsx # 黑金主题卡片容器(渐变背景、金色边框) ├── CardTitle.tsx # 卡片标题(图标+标题+副标题) ├── MetricValue.tsx # 核心数值展示(标签+数值+后缀) ├── PriceDisplay.tsx # 价格显示(价格+涨跌箭头+百分比) └── StatusTag.tsx # 状态标签(活跃/健康/警惕等) ``` **4 列布局设计**: ``` ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 股票信息 │ │ 交易热度 │ │ 估值VS安全 │ │ 情绪与风险 │ │ 平安银行 │ │ (流动性) │ │ (便宜否) │ │ (资金面) │ │ (000001) │ │ │ │ │ │ │ │ 13.50 ↗+1.89%│ │ 成交额 46.79亿│ │ PE 4.96 │ │ 融资 58.23亿 │ │ 走势:小幅上涨 │ │ 成交量|换手率 │ │ 质押率(健康) │ │ 融券 1.26亿 │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ ``` **黑金主题配置**(`constants.ts`): ```typescript export const darkGoldTheme = { bgCard: 'linear-gradient(135deg, #1a1a2e 0%, #0f0f1a 100%)', border: 'rgba(212, 175, 55, 0.3)', gold: '#D4AF37', orange: '#FF9500', green: '#00C851', red: '#FF4444', textPrimary: '#FFFFFF', textMuted: 'rgba(255, 255, 255, 0.6)', }; ``` **状态计算工具**(`utils.ts`): | 函数 | 功能 | |------|------| | `getTrendDescription` | 根据涨跌幅返回走势描述(强势上涨/小幅下跌等) | | `getTurnoverStatus` | 换手率状态(≥3% 活跃, ≥1% 正常, <1% 冷清) | | `getPEStatus` | 市盈率估值评级(极低估值/合理/偏高/泡沫风险) | | `getPledgeStatus` | 质押率健康状态(<10% 健康, <30% 正常, <50% 偏高, ≥50% 警惕) | | `getPriceColor` | 根据涨跌返回颜色(红涨绿跌) | **原子组件说明**: | 组件 | 行数 | 用途 | 可复用场景 | |------|------|------|-----------| | `DarkGoldCard` | ~40 | 黑金主题卡片容器 | 任何需要黑金风格的卡片 | | `CardTitle` | ~30 | 卡片标题行 | 带图标的标题展示 | | `MetricValue` | ~45 | 核心数值展示 | 各种指标数值展示 | | `PriceDisplay` | ~55 | 价格+涨跌幅 | 股票价格展示 | | `StatusTag` | ~20 | 状态标签 | 各种状态文字标签 | **响应式断点**: - `lg` (≥992px): 4 列 - `md` (≥768px): 2 列 - `base` (<768px): 1 列 **类型定义更新**(`types.ts`): - `StockSummaryCardProps.theme` 改为可选参数,组件内置使用 `darkGoldTheme` **优化效果**: | 指标 | 优化前 | 优化后 | 改善 | |------|--------|--------|------| | 主文件行数 | ~350 | ~115 | -67% | | 文件数量 | 1 | 8 | 原子设计模式 | | 可复用组件 | 0 | 5 原子 + 2 业务 | 提升 | | 主题支持 | 依赖传入 | 内置黑金主题 | 独立 | **设计原则**: - **原子设计模式**:atoms(基础元素)→ 业务组件(MetricCard、StockHeaderCard)→ 页面组件(index.tsx) - **主题独立**:StockSummaryCard 使用内置黑金主题,不依赖外部传入 - **职责分离**:状态计算逻辑提取到 `utils.ts`,UI 与逻辑解耦 - **组件复用**:原子组件可在其他黑金主题场景复用 ### 2025-12-16 TradeDataPanel 原子设计模式拆分 **改动概述**: - `TradeDataPanel.tsx` 从 **382 行** 拆分为 **8 个 TypeScript 文件** - 采用**原子设计模式**组织代码 - 提取 **3 个原子组件** + **3 个业务组件** **拆分后文件结构**: ``` TradeDataPanel/ ├── index.tsx # 主入口组件(~50 行,组合 3 个子组件) ├── KLineChart.tsx # 日K线图组件(~40 行) ├── MinuteKLineSection.tsx # 分钟K线区域(~95 行,含加载/空状态处理) ├── TradeTable.tsx # 交易明细表格(~75 行) └── atoms/ # 原子组件 ├── index.ts # 统一导出 ├── MinuteStats.tsx # 分钟数据统计(~80 行,4 个 Stat 卡片) ├── TradeAnalysis.tsx # 成交分析(~65 行,活跃时段/平均价格等) └── EmptyState.tsx # 空状态组件(~35 行,可复用) ``` **组件依赖关系**: ``` index.tsx ├── KLineChart # 日K线图(ECharts) ├── MinuteKLineSection # 分钟K线区域 │ ├── MinuteStats (atom) # 开盘/当前/最高/最低价统计 │ ├── TradeAnalysis (atom) # 成交数据分析 │ └── EmptyState (atom) # 空状态提示 └── TradeTable # 交易明细表格(最近 10 天) ``` **组件职责**: | 组件 | 行数 | 功能 | |------|------|------| | `index.tsx` | ~50 | 主入口,组合 3 个子组件 | | `KLineChart` | ~40 | 日K线图渲染,支持图表点击事件 | | `MinuteKLineSection` | ~95 | 分钟K线区域,含加载状态、空状态、统计数据 | | `TradeTable` | ~75 | 最近 10 天交易明细表格 | | `MinuteStats` | ~80 | 分钟数据四宫格统计(开盘/当前/最高/最低价) | | `TradeAnalysis` | ~65 | 成交数据分析(活跃时段、平均价格、数据点数) | | `EmptyState` | ~35 | 通用空状态组件(可配置标题和描述) | **优化效果**: | 指标 | 优化前 | 优化后 | 改善 | |------|--------|--------|------| | 主文件行数 | 382 | ~50 | -87% | | 文件数量 | 1 | 8 | 原子设计模式 | | 可复用组件 | 0 | 3 原子 + 3 业务 | 提升 | **设计原则**: - **原子设计模式**:atoms(MinuteStats、TradeAnalysis、EmptyState)→ 业务组件(KLineChart、MinuteKLineSection、TradeTable)→ 主组件 - **职责分离**:图表、统计、表格各自独立 - **组件复用**:EmptyState 可在其他场景复用 - **类型安全**:完整的 Props 类型定义和导出 ### 2025-12-17 StockQuoteCard 数据下沉优化 **改动概述**: - StockQuoteCard Props 从 **11 个** 精简至 **4 个**(减少 64%) - 行情数据、基本信息、股票对比逻辑全部下沉到组件内部 - Company/index.js 移除约 **40 行** 数据获取代码 - 删除 `Company/hooks/useStockQuote.js` **创建的文件**: ``` StockQuoteCard/hooks/ ├── index.ts # hooks 导出索引 ├── useStockQuoteData.ts # 行情数据 + 基本信息获取(~152 行) └── useStockCompare.ts # 股票对比逻辑(~91 行) ``` **Props 对比**: **优化前(11 个 Props)**: ```tsx ``` **优化后(4 个 Props)**: ```tsx ``` **Hook 返回值**: `useStockQuoteData(stockCode)`: ```typescript { quoteData: StockQuoteCardData | null; // 行情数据 basicInfo: BasicInfo | null; // 基本信息 isLoading: boolean; // 加载状态 error: string | null; // 错误信息 refetch: () => void; // 手动刷新 } ``` `useStockCompare(stockCode)`: ```typescript { currentStockInfo: StockInfo | null; // 当前股票财务信息 compareStockInfo: StockInfo | null; // 对比股票财务信息 isCompareLoading: boolean; // 对比数据加载中 handleCompare: (code: string) => Promise; // 触发对比 clearCompare: () => void; // 清除对比 } ``` **修改的文件**: | 文件 | 操作 | 说明 | |------|------|------| | `StockQuoteCard/hooks/useStockQuoteData.ts` | 新建 | 合并行情+基本信息获取 | | `StockQuoteCard/hooks/useStockCompare.ts` | 新建 | 股票对比逻辑 | | `StockQuoteCard/hooks/index.ts` | 新建 | hooks 导出索引 | | `StockQuoteCard/index.tsx` | 修改 | 使用内部 hooks,减少 props | | `StockQuoteCard/types.ts` | 修改 | Props 从 11 个精简为 4 个 | | `Company/index.js` | 修改 | 移除下沉的数据获取逻辑 | | `Company/hooks/useStockQuote.js` | 删除 | 已移到 StockQuoteCard | **优化收益**: | 指标 | 优化前 | 优化后 | 改善 | |------|--------|--------|------| | Props 数量 | 11 | 4 | -64% | | Company/index.js 行数 | ~172 | ~105 | -39% | | 数据获取位置 | 页面层 | 组件内部 | 就近原则 | | 可复用性 | 依赖父组件 | 独立可用 | 提升 | **设计原则**: - **数据就近获取**:组件自己获取自己需要的数据 - **Props 最小化**:只传递真正需要外部控制的状态 - **职责清晰**:自选股状态保留在页面层(涉及 Redux 和事件追踪) - **可复用性**:StockQuoteCard 可独立在其他页面使用