perf(MarketDataView): 优化加载状态,使用骨架屏避免布局跳动

- useMarketData: 新增 hasLoaded 状态,优化首次加载 loading 逻辑
- 导出 SummaryCardSkeleton 组件用于概览卡片占位
- MarketDataView: 使用骨架屏替代空白占位
- DeepAnalysisTab: 使用 skeleton 变体替代 spinner

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-22 12:15:39 +08:00
parent 88b836e75a
commit 9e271747da
5 changed files with 26 additions and 20 deletions

View File

@@ -22,6 +22,7 @@ import { useMarketData } from './hooks/useMarketData';
import {
ThemedCard,
StockSummaryCard,
SummaryCardSkeleton,
AnalysisModal,
AnalysisContent,
} from './components';
@@ -89,13 +90,12 @@ const MarketDataView: React.FC<MarketDataViewProps> = ({ stockCode: propStockCod
}
}, [propStockCode, stockCode]);
// 首次渲染时加载默认 Tab融资融券的数据
// 首次挂载时加载默认 Tab融资融券的数据
// 注意SubTabContainer 的 onChange 只在切换时触发,首次渲染不会触发
useEffect(() => {
// 默认 Tab 是融资融券index 0
if (activeTab === 0) {
loadDataByType('funding');
}
}, [loadDataByType, activeTab]);
loadDataByType('funding');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // 只在首次挂载时执行
// 处理图表点击事件
const handleChartClick = useCallback(
@@ -137,8 +137,8 @@ const MarketDataView: React.FC<MarketDataViewProps> = ({ stockCode: propStockCod
<Box bg={'#1A202C'} minH="100vh" color={theme.textPrimary}>
<Container maxW="container.xl" py={4}>
<VStack align="stretch" spacing={4}>
{/* 股票概览 */}
{summary && <StockSummaryCard summary={summary} theme={theme} />}
{/* 股票概览 - 未加载时显示骨架屏占位,避免布局跳动 */}
{summary ? <StockSummaryCard summary={summary} theme={theme} /> : <SummaryCardSkeleton />}
{/* 交易数据 - 日K/分钟K线独立显示在 Tab 上方) */}
<TradeDataPanel