refactor(FinancialPanorama): 添加数据加载 Hook
useFinancialData Hook 功能: - 9个财务API并行加载(Promise.all) - 股票信息、资产负债表、利润表、现金流量表 - 财务指标、主营业务、业绩预告 - 行业排名、期间对比 - 支持期数选择(4/8/12/16期) - 自动响应 stockCode 变化重新加载 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Hooks 统一导出
|
||||
*/
|
||||
|
||||
export { useFinancialData } from './useFinancialData';
|
||||
export type { default as UseFinancialDataReturn } from './useFinancialData';
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 财务数据加载 Hook
|
||||
* 封装所有财务数据的加载逻辑
|
||||
*/
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { logger } from '@utils/logger';
|
||||
import { financialService } from '@services/financialService';
|
||||
import type {
|
||||
StockInfo,
|
||||
BalanceSheetData,
|
||||
IncomeStatementData,
|
||||
CashflowData,
|
||||
FinancialMetricsData,
|
||||
MainBusinessData,
|
||||
ForecastData,
|
||||
IndustryRankData,
|
||||
ComparisonData,
|
||||
} from '../types';
|
||||
|
||||
interface UseFinancialDataOptions {
|
||||
stockCode?: string;
|
||||
periods?: number;
|
||||
}
|
||||
|
||||
interface UseFinancialDataReturn {
|
||||
// 数据状态
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 财务数据加载 Hook
|
||||
* @param options - 配置选项
|
||||
* @returns 财务数据和操作方法
|
||||
*/
|
||||
export const useFinancialData = (
|
||||
options: UseFinancialDataOptions = {}
|
||||
): UseFinancialDataReturn => {
|
||||
const { stockCode: initialStockCode = '600000', periods: initialPeriods = 8 } = options;
|
||||
|
||||
// 参数状态
|
||||
const [stockCode, setStockCode] = useState(initialStockCode);
|
||||
const [selectedPeriods, setSelectedPeriods] = useState(initialPeriods);
|
||||
|
||||
// 加载状态
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// 财务数据状态
|
||||
const [stockInfo, setStockInfo] = useState<StockInfo | null>(null);
|
||||
const [balanceSheet, setBalanceSheet] = useState<BalanceSheetData[]>([]);
|
||||
const [incomeStatement, setIncomeStatement] = useState<IncomeStatementData[]>([]);
|
||||
const [cashflow, setCashflow] = useState<CashflowData[]>([]);
|
||||
const [financialMetrics, setFinancialMetrics] = useState<FinancialMetricsData[]>([]);
|
||||
const [mainBusiness, setMainBusiness] = useState<MainBusinessData | null>(null);
|
||||
const [forecast, setForecast] = useState<ForecastData | null>(null);
|
||||
const [industryRank, setIndustryRank] = useState<IndustryRankData[]>([]);
|
||||
const [comparison, setComparison] = useState<ComparisonData[]>([]);
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
// 加载所有财务数据
|
||||
const loadFinancialData = useCallback(async () => {
|
||||
if (!stockCode || stockCode.length !== 6) {
|
||||
logger.warn('useFinancialData', '无效的股票代码', { stockCode });
|
||||
toast({
|
||||
title: '请输入有效的6位股票代码',
|
||||
status: 'warning',
|
||||
duration: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug('useFinancialData', '开始加载财务数据', { stockCode, selectedPeriods });
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// 并行加载所有数据
|
||||
const [
|
||||
stockInfoRes,
|
||||
balanceRes,
|
||||
incomeRes,
|
||||
cashflowRes,
|
||||
metricsRes,
|
||||
businessRes,
|
||||
forecastRes,
|
||||
rankRes,
|
||||
comparisonRes,
|
||||
] = await Promise.all([
|
||||
financialService.getStockInfo(stockCode),
|
||||
financialService.getBalanceSheet(stockCode, selectedPeriods),
|
||||
financialService.getIncomeStatement(stockCode, selectedPeriods),
|
||||
financialService.getCashflow(stockCode, selectedPeriods),
|
||||
financialService.getFinancialMetrics(stockCode, selectedPeriods),
|
||||
financialService.getMainBusiness(stockCode, 4),
|
||||
financialService.getForecast(stockCode),
|
||||
financialService.getIndustryRank(stockCode, 4),
|
||||
financialService.getPeriodComparison(stockCode, selectedPeriods),
|
||||
]);
|
||||
|
||||
// 设置数据
|
||||
if (stockInfoRes.success) setStockInfo(stockInfoRes.data);
|
||||
if (balanceRes.success) setBalanceSheet(balanceRes.data);
|
||||
if (incomeRes.success) setIncomeStatement(incomeRes.data);
|
||||
if (cashflowRes.success) setCashflow(cashflowRes.data);
|
||||
if (metricsRes.success) setFinancialMetrics(metricsRes.data);
|
||||
if (businessRes.success) setMainBusiness(businessRes.data);
|
||||
if (forecastRes.success) setForecast(forecastRes.data);
|
||||
if (rankRes.success) setIndustryRank(rankRes.data);
|
||||
if (comparisonRes.success) setComparison(comparisonRes.data);
|
||||
|
||||
logger.info('useFinancialData', '财务数据加载成功', { stockCode });
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : '未知错误';
|
||||
setError(errorMessage);
|
||||
logger.error('useFinancialData', 'loadFinancialData', err, { stockCode, selectedPeriods });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [stockCode, selectedPeriods, toast]);
|
||||
|
||||
// 监听 props 中的 stockCode 变化
|
||||
useEffect(() => {
|
||||
if (initialStockCode && initialStockCode !== stockCode) {
|
||||
setStockCode(initialStockCode);
|
||||
}
|
||||
}, [initialStockCode]);
|
||||
|
||||
// 初始加载和参数变化时重新加载
|
||||
useEffect(() => {
|
||||
if (stockCode) {
|
||||
loadFinancialData();
|
||||
}
|
||||
}, [stockCode, selectedPeriods, loadFinancialData]);
|
||||
|
||||
return {
|
||||
// 数据状态
|
||||
stockInfo,
|
||||
balanceSheet,
|
||||
incomeStatement,
|
||||
cashflow,
|
||||
financialMetrics,
|
||||
mainBusiness,
|
||||
forecast,
|
||||
industryRank,
|
||||
comparison,
|
||||
|
||||
// 加载状态
|
||||
loading,
|
||||
error,
|
||||
|
||||
// 操作方法
|
||||
refetch: loadFinancialData,
|
||||
setStockCode,
|
||||
setSelectedPeriods,
|
||||
|
||||
// 当前参数
|
||||
currentStockCode: stockCode,
|
||||
selectedPeriods,
|
||||
};
|
||||
};
|
||||
|
||||
export default useFinancialData;
|
||||
Reference in New Issue
Block a user