- 梳理 Company 模块共 27 个 API 接口(去重后) - 分 6 大类:股票基础信息(8)、股东信息(4)、行情数据(8)、深度分析(5)、财务数据(1)、事件新闻(1) - 标注每个接口的方法类型和调用位置 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
57 KiB
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- 已下沉到 StockQuoteCarduseBasicInfo- 已下沉到 StockQuoteCard- 股票对比逻辑 - 已下沉到 StockQuoteCard
Hooks 目录
useCompanyStock.js - 股票代码管理
- 功能:
- 管理当前股票代码状态
- 双向同步 URL 参数(支持浏览器前进/后退)
- 处理搜索输入和提交
- 返回值:
{ stockCode, // 当前确认的股票代码 inputCode, // 输入框中的值(未确认) setInputCode, // 更新输入框 handleSearch, // 执行搜索 handleKeyPress, // 处理回车键 } - 依赖:
react-router-dom(useSearchParams)
useCompanyWatchlist.js - 自选股管理
- 功能:
- 检查当前股票是否在自选股中
- 提供添加/移除自选股功能
- 与 Redux stockSlice 同步
- 返回值:
{ isInWatchlist, // 是否在自选股中 isLoading, // 操作进行中 toggle, // 切换自选状态 } - 依赖:Redux (
stockSlice)、AuthContext、Chakra UI (useToast)
useCompanyEvents.js - 事件追踪
- 功能:
- 页面浏览追踪
- 股票搜索追踪
- Tab 切换追踪
- 自选股操作追踪
- 返回值:
{ trackStockSearched, // 追踪股票搜索 trackTabChanged, // 追踪 Tab 切换 trackWatchlistAdded, // 追踪添加自选 trackWatchlistRemoved, // 追踪移除自选 } - 依赖:PostHog (
usePostHogTrack)
Components 目录
CompanyHeader/ - 页面头部
| 文件 | 职责 |
|---|---|
index.js |
组合 SearchBar 和 WatchlistButton |
SearchBar.js |
股票代码搜索输入框 |
WatchlistButton.js |
自选股添加/移除按钮 |
Props 接口:
<CompanyHeader
stockCode={string} // 当前股票代码
inputCode={string} // 输入框值
onInputChange={func} // 输入变化回调
onSearch={func} // 搜索回调
onKeyPress={func} // 键盘事件回调
isInWatchlist={bool} // 是否在自选中
isWatchlistLoading={bool} // 自选操作加载中
onWatchlistToggle={func} // 自选切换回调
bgColor={string} // 背景色
/>
CompanyTabs/ - Tab 切换
| 文件 | 职责 |
|---|---|
index.js |
Tab 容器,管理切换状态,渲染 Tab 内容 |
TabNavigation.js |
Tab 导航栏(4个 Tab 按钮) |
Props 接口:
<CompanyTabs
stockCode={string} // 当前股票代码
onTabChange={func} // Tab 变更回调 (index, tabName, prevIndex)
bgColor={string} // 背景色
/>
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
修复的问题:
- 无限循环 Bug:
useCompanyWatchlist中使用useRef防止重复初始化 - Hook 调用顺序:确保
useCompanyEvents在useCompanyStock之后调用(依赖 stockCode) - 类型检查:
CompanyOverview.js中event.keywords渲染时添加类型检查,支持字符串和对象两种格式
设计原则:
- 关注点分离:每个 Hook 只负责单一职责
- 纯组合层:index.js 不包含业务逻辑,只负责组合
- Props 透传:通过 Props 将状态和回调传递给子组件
2025-12-09 文件夹化
改动概述:
- 所有 4 个 Tab 内容组件统一移动到
components/目录 CompanyOverview.js→components/CompanyOverview/index.jsMarketDataView.js→components/MarketDataView/index.jsFinancialPanorama.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):
{
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<number, RiseAnalysis>;
refetch: () => Promise<void>;
loadMinuteData: () => Promise<void>;
}
设计原则:
- 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- 主组件 PropsQualitativeAnalysis- 定性分析数据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):
{
// 数据状态
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<void>;
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):
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):
<StockQuoteCard
data={quoteData}
isLoading={isQuoteLoading}
basicInfo={basicInfo}
currentStockInfo={currentStockInfo}
compareStockInfo={compareStockInfo}
isCompareLoading={isCompareLoading}
onCompare={handleCompare}
onCloseCompare={handleCloseCompare}
isInWatchlist={isInWatchlist}
isWatchlistLoading={isWatchlistLoading}
onWatchlistToggle={handleWatchlistToggle}
/>
优化后(4 个 Props):
<StockQuoteCard
stockCode={stockCode}
isInWatchlist={isInWatchlist}
isWatchlistLoading={isWatchlistLoading}
onWatchlistToggle={handleWatchlistToggle}
/>
Hook 返回值:
useStockQuoteData(stockCode):
{
quoteData: StockQuoteCardData | null; // 行情数据
basicInfo: BasicInfo | null; // 基本信息
isLoading: boolean; // 加载状态
error: string | null; // 错误信息
refetch: () => void; // 手动刷新
}
useStockCompare(stockCode):
{
currentStockInfo: StockInfo | null; // 当前股票财务信息
compareStockInfo: StockInfo | null; // 对比股票财务信息
isCompareLoading: boolean; // 对比数据加载中
handleCompare: (code: string) => Promise<void>; // 触发对比
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 可独立在其他页面使用