refactor(ForecastReport): 迁移至 TypeScript

This commit is contained in:
zdl
2025-12-16 20:28:58 +08:00
parent f186adafa8
commit 98683af429
11 changed files with 722 additions and 161 deletions

View File

@@ -0,0 +1,115 @@
/**
* 盈利预测报表视图 - 黑金主题
*/
import React, { useState, useEffect, useCallback } from 'react';
import { Box, SimpleGrid, HStack, Heading, Skeleton, IconButton } from '@chakra-ui/react';
import { RefreshCw } from 'lucide-react';
import { stockService } from '@services/eventService';
import {
IncomeProfitChart,
GrowthChart,
EpsChart,
PePegChart,
DetailTable,
ChartCard,
} from './components';
import { THEME, CHART_HEIGHT } from './constants';
import type { ForecastReportProps, ForecastData } from './types';
const ForecastReport: React.FC<ForecastReportProps> = ({ stockCode: propStockCode }) => {
const [code, setCode] = useState(propStockCode || '600000');
const [data, setData] = useState<ForecastData | null>(null);
const [loading, setLoading] = useState(false);
const load = useCallback(async () => {
if (!code) return;
setLoading(true);
try {
const resp = await stockService.getForecastReport(code);
if (resp && resp.success) {
setData(resp.data);
}
} finally {
setLoading(false);
}
}, [code]);
// 监听 props 中的 stockCode 变化
useEffect(() => {
if (propStockCode && propStockCode !== code) {
setCode(propStockCode);
}
}, [propStockCode, code]);
// 加载数据
useEffect(() => {
if (code) {
load();
}
}, [code, load]);
return (
<Box>
{/* 标题栏 */}
<HStack align="center" justify="space-between" mb={4}>
<Heading size="md" color={THEME.gold}>
</Heading>
<IconButton
icon={<RefreshCw size={14} className={loading ? 'spin' : ''} />}
onClick={load}
isLoading={loading}
variant="outline"
size="sm"
aria-label="刷新数据"
borderColor={THEME.goldBorder}
color={THEME.gold}
_hover={{
bg: THEME.goldLight,
borderColor: THEME.gold,
}}
/>
<style>{`
.spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`}</style>
</HStack>
{/* 加载骨架屏 */}
{loading && !data && (
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={4}>
{[1, 2, 3, 4].map((i) => (
<ChartCard key={i} title="加载中...">
<Skeleton height={`${CHART_HEIGHT}px`} />
</ChartCard>
))}
</SimpleGrid>
)}
{/* 图表区域 */}
{data && (
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={4}>
<IncomeProfitChart data={data.income_profit_trend} />
<GrowthChart data={data.growth_bars} />
<EpsChart data={data.eps_trend} />
<PePegChart data={data.pe_peg_axes} />
</SimpleGrid>
)}
{/* 详细数据表格 */}
{data && (
<Box mt={4}>
<DetailTable data={data.detail_table} />
</Box>
)}
</Box>
);
};
export default ForecastReport;