/** * 财务全景组件 * 重构后的主组件,使用模块化结构和 SubTabContainer 二级导航 */ import React, { useState, useMemo, useCallback } from 'react'; import { Box, Container, VStack, Card, CardBody, Text, Alert, AlertIcon, useDisclosure, } from '@chakra-ui/react'; import { BarChart3, DollarSign, TrendingUp, PieChart, Percent, TrendingDown, Activity, Shield, Receipt, Banknote, } from 'lucide-react'; // 通用组件 import SubTabContainer, { type SubTabConfig } from '@components/SubTabContainer'; import LoadingState from '../LoadingState'; // 内部模块导入 import { useFinancialData, type DataTypeKey } from './hooks'; import { COLORS } from './constants'; import { calculateYoYChange, getCellBackground } from './utils'; import { PeriodSelector, FinancialOverviewPanel, MainBusinessAnalysis, ComparisonAnalysis, MetricChartModal, } from './components'; import { BalanceSheetTab, IncomeStatementTab, CashflowTab, ProfitabilityTab, PerShareTab, GrowthTab, OperationalTab, SolvencyTab, ExpenseTab, CashflowMetricsTab, } from './tabs'; import type { FinancialPanoramaProps } from './types'; /** * 财务全景主组件 */ // Tab key 映射表(SubTabContainer index -> DataTypeKey) const TAB_KEY_MAP: DataTypeKey[] = [ 'profitability', 'perShare', 'growth', 'operational', 'solvency', 'expense', 'cashflowMetrics', 'balance', 'income', 'cashflow', ]; const FinancialPanorama: React.FC = ({ stockCode: propStockCode }) => { // 使用数据加载 Hook const { stockInfo, balanceSheet, incomeStatement, cashflow, financialMetrics, mainBusiness, comparison, loading, loadingTab, error, refetchByTab, selectedPeriods, setSelectedPeriods, setActiveTab, activeTab, } = useFinancialData({ stockCode: propStockCode }); // 处理 Tab 切换 const handleTabChange = useCallback((index: number, tabKey: string) => { const dataTypeKey = TAB_KEY_MAP[index] || (tabKey as DataTypeKey); setActiveTab(dataTypeKey); }, [setActiveTab]); // 处理刷新 - 只刷新当前 Tab const handleRefresh = useCallback(() => { refetchByTab(activeTab); }, [refetchByTab, activeTab]); // UI 状态 const { isOpen, onOpen, onClose } = useDisclosure(); const [modalProps, setModalProps] = useState<{ metricName: string; data: Array<{ period: string; [key: string]: unknown }>; dataPath: string; }>({ metricName: '', data: [], dataPath: '' }); // 点击指标行显示图表 const showMetricChart = useCallback(( metricName: string, _metricKey: string, data: Array<{ period: string; [key: string]: unknown }>, dataPath: string ) => { setModalProps({ metricName, data, dataPath }); onOpen(); }, [onOpen]); // Tab 配置 - 财务指标分类 + 三大财务报表 const tabConfigs: SubTabConfig[] = useMemo( () => [ // 财务指标分类(7个) { key: 'profitability', name: '盈利能力', icon: PieChart, component: ProfitabilityTab }, { key: 'perShare', name: '每股指标', icon: Percent, component: PerShareTab }, { key: 'growth', name: '成长能力', icon: TrendingUp, component: GrowthTab }, { key: 'operational', name: '运营效率', icon: Activity, component: OperationalTab }, { key: 'solvency', name: '偿债能力', icon: Shield, component: SolvencyTab }, { key: 'expense', name: '费用率', icon: Receipt, component: ExpenseTab }, { key: 'cashflowMetrics', name: '现金流指标', icon: Banknote, component: CashflowMetricsTab }, // 三大财务报表 { key: 'balance', name: '资产负债表', icon: BarChart3, component: BalanceSheetTab }, { key: 'income', name: '利润表', icon: DollarSign, component: IncomeStatementTab }, { key: 'cashflow', name: '现金流量表', icon: TrendingDown, component: CashflowTab }, ], [] ); // 传递给 Tab 组件的 props(颜色使用常量,不需要在依赖数组中) const componentProps = useMemo( () => ({ // 数据 balanceSheet, incomeStatement, cashflow, financialMetrics, // 加载状态 loading, loadingTab, // 工具函数 showMetricChart, calculateYoYChange, getCellBackground, // 颜色配置(使用常量) ...COLORS, }), [ balanceSheet, incomeStatement, cashflow, financialMetrics, loading, loadingTab, showMetricChart, ] ); return ( {/* 财务全景面板(三列布局:成长能力、盈利与回报、风险与运营) */} {loading ? ( ) : ( )} {/* 营收与利润趋势 */} {!loading && comparison && comparison.length > 0 && ( )} {/* 主营业务 */} {!loading && stockInfo && ( 主营业务 )} {/* 三大财务报表 - 使用 SubTabContainer 二级导航 */} } /> {/* 错误提示 */} {error && ( {error} )} {/* 指标图表弹窗 */} ); }; export default FinancialPanorama;