- 添加 BasicInfoTab/ 目录结构详情 - 补充各子组件功能注释: - LoadingState: 加载状态组件 - ShareholderPanel: 股权结构面板 - ManagementPanel: 管理团队面板 - AnnouncementsPanel: 公告信息面板 - BranchesPanel: 分支机构面板 - BusinessInfoPanel: 工商信息面板 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
22 KiB
22 KiB
Company 目录结构说明
最后更新:2025-12-10
目录结构
src/views/Company/
├── index.js # 页面入口(95行,纯组合层)
├── STRUCTURE.md # 本文档
│
├── components/ # UI 组件
│ ├── CompanyHeader/ # 页面头部
│ │ ├── index.js # 组合导出
│ │ ├── SearchBar.js # 股票搜索栏
│ │ └── WatchlistButton.js # 自选股按钮
│ │
│ ├── CompanyTabs/ # Tab 切换容器
│ │ ├── index.js # Tab 容器(状态管理 + 内容渲染)
│ │ └── TabNavigation.js # Tab 导航栏
│ │
│ ├── CompanyOverview/ # Tab: 公司概览(TypeScript 拆分)
│ │ ├── index.tsx # 主组件(组合层,约 50 行)
│ │ ├── CompanyHeaderCard.tsx # 头部卡片组件(黑金主题,约 200 行)
│ │ ├── BasicInfoTab/ # 基本信息 Tab(TypeScript 可配置化重构)
│ │ │ ├── index.tsx # 主组件(可配置,约 120 行)
│ │ │ ├── config.ts # Tab 配置 + 黑金主题(约 90 行)
│ │ │ ├── utils.ts # 格式化工具函数(约 50 行)
│ │ │ └── components/ # 子组件
│ │ │ ├── index.ts # 组件统一导出
│ │ │ ├── LoadingState.tsx # 加载状态组件(黑金主题 Spinner)
│ │ │ ├── ShareholderPanel.tsx # 股权结构面板(实控人、十大股东、股权集中度)
│ │ │ ├── ManagementPanel.tsx # 管理团队面板(高管列表表格)
│ │ │ ├── AnnouncementsPanel.tsx # 公告信息面板(公告列表 + 披露日程)
│ │ │ ├── BranchesPanel.tsx # 分支机构面板(分支列表表格)
│ │ │ └── BusinessInfoPanel.tsx # 工商信息面板(注册资本、成立日期等)
│ │ ├── DeepAnalysisTab.js # 深度分析 Tab
│ │ ├── NewsEventsTab.js # 新闻事件 Tab
│ │ ├── types.ts # 类型定义(约 120 行)
│ │ ├── utils.ts # 格式化工具(约 20 行)
│ │ └── hooks/
│ │ └── useCompanyOverviewData.ts # 数据 Hook(约 100 行)
│ │
│ ├── MarketDataView/ # Tab: 股票行情(TypeScript 拆分)
│ │ ├── index.tsx # 主组件入口(~1049 行)
│ │ ├── types.ts # 类型定义(~383 行)
│ │ ├── constants.ts # 主题配置、常量
│ │ ├── services/
│ │ │ └── marketService.ts # API 服务层
│ │ ├── hooks/
│ │ │ └── useMarketData.ts # 数据获取 Hook
│ │ ├── utils/
│ │ │ ├── formatUtils.ts # 格式化工具函数
│ │ │ └── chartOptions.ts # ECharts 图表配置生成器
│ │ └── components/
│ │ ├── index.ts # 组件导出
│ │ ├── ThemedCard.tsx # 主题化卡片
│ │ ├── MarkdownRenderer.tsx # Markdown 渲染
│ │ ├── StockSummaryCard.tsx # 股票概览卡片
│ │ └── AnalysisModal.tsx # 涨幅分析模态框
│ │
│ ├── FinancialPanorama/ # Tab: 财务全景(2153 行,待拆分)
│ │ └── index.js
│ │
│ └── ForecastReport/ # Tab: 盈利预测(161 行,待拆分)
│ └── index.js
│
├── hooks/ # 自定义 Hooks
│ ├── useCompanyStock.js # 股票代码管理(URL 同步)
│ ├── useCompanyWatchlist.js # 自选股管理(Redux 集成)
│ └── useCompanyEvents.js # PostHog 事件追踪
│
└── constants/ # 常量定义
└── index.js # Tab 配置、Toast 消息、默认值
文件职责说明
入口文件
index.js - 页面入口
- 职责:纯组合层,协调 Hooks 和 Components
- 代码行数:95 行
- 依赖:
useCompanyStock- 股票代码状态useCompanyWatchlist- 自选股状态useCompanyEvents- 事件追踪CompanyHeader- 页面头部CompanyTabs- Tab 切换区
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.js # 深度分析 Tab
├── 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 # 主组件入口(~1049 行)
├── 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 行)
文件职责说明:
| 文件 | 行数 | 职责 |
|---|---|---|
index.tsx |
~1049 | 主组件,包含 5 个 Tab 面板(交易数据、融资融券、大宗交易、龙虎榜、股权质押) |
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)可在其他模块使用