refactor(Company): 统一所有 Tab 的 loading 状态组件

- 创建共享的 LoadingState 组件(黑金主题)
- DeepAnalysisTab: 使用统一 LoadingState 替换蓝色 Spinner
- FinancialPanorama: 使用 LoadingState 替换 Skeleton
- MarketDataView: 使用 LoadingState 替换自定义 Spinner
- ForecastReport: 使用 LoadingState 替换 Skeleton 骨架屏

所有一级 Tab 现在使用一致的金色 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-17 10:31:38 +08:00
parent 21e83ac1bc
commit ac7e627b2d
5 changed files with 55 additions and 32 deletions

View File

@@ -11,9 +11,10 @@
*/ */
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { Card, CardBody, Center, VStack, Spinner, Text } from '@chakra-ui/react'; import { Card, CardBody } from '@chakra-ui/react';
import { FaBrain, FaBuilding, FaLink, FaHistory } from 'react-icons/fa'; import { FaBrain, FaBuilding, FaLink, FaHistory } from 'react-icons/fa';
import SubTabContainer, { type SubTabConfig } from '@components/SubTabContainer'; import SubTabContainer, { type SubTabConfig } from '@components/SubTabContainer';
import LoadingState from '../../LoadingState';
import { StrategyTab, BusinessTab, ValueChainTab, DevelopmentTab } from './tabs'; import { StrategyTab, BusinessTab, ValueChainTab, DevelopmentTab } from './tabs';
import type { DeepAnalysisTabProps, DeepAnalysisTabKey } from './types'; import type { DeepAnalysisTabProps, DeepAnalysisTabKey } from './types';
@@ -75,12 +76,7 @@ const DeepAnalysisTab: React.FC<DeepAnalysisTabProps> = ({
componentProps={{}} componentProps={{}}
themePreset="blackGold" themePreset="blackGold"
/> />
<Center h="200px"> <LoadingState message="加载数据中..." height="200px" />
<VStack spacing={4}>
<Spinner size="xl" color="blue.500" />
<Text color="gray.400">...</Text>
</VStack>
</Center>
</CardBody> </CardBody>
</Card> </Card>
); );

View File

@@ -13,7 +13,6 @@ import {
Text, Text,
Alert, Alert,
AlertIcon, AlertIcon,
Skeleton,
Modal, Modal,
ModalOverlay, ModalOverlay,
ModalContent, ModalContent,
@@ -47,6 +46,7 @@ import { formatUtils } from '@services/financialService';
// 通用组件 // 通用组件
import SubTabContainer, { type SubTabConfig } from '@components/SubTabContainer'; import SubTabContainer, { type SubTabConfig } from '@components/SubTabContainer';
import LoadingState from '../LoadingState';
// 内部模块导入 // 内部模块导入
import { useFinancialData, type DataTypeKey } from './hooks'; import { useFinancialData, type DataTypeKey } from './hooks';
@@ -278,7 +278,7 @@ const FinancialPanorama: React.FC<FinancialPanoramaProps> = ({ stockCode: propSt
<VStack spacing={6} align="stretch"> <VStack spacing={6} align="stretch">
{/* 财务全景面板(三列布局:成长能力、盈利与回报、风险与运营) */} {/* 财务全景面板(三列布局:成长能力、盈利与回报、风险与运营) */}
{loading ? ( {loading ? (
<Skeleton height="100px" /> <LoadingState message="加载财务数据中..." height="300px" />
) : ( ) : (
<FinancialOverviewPanel <FinancialOverviewPanel
stockInfo={stockInfo} stockInfo={stockInfo}

View File

@@ -3,15 +3,15 @@
*/ */
import React, { useState, useEffect, useCallback } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import { Box, SimpleGrid, Skeleton } from '@chakra-ui/react'; import { Box, SimpleGrid } from '@chakra-ui/react';
import { stockService } from '@services/eventService'; import { stockService } from '@services/eventService';
import { import {
IncomeProfitGrowthChart, IncomeProfitGrowthChart,
EpsChart, EpsChart,
PePegChart, PePegChart,
DetailTable, DetailTable,
ChartCard,
} from './components'; } from './components';
import LoadingState from '../LoadingState';
import { CHART_HEIGHT } from './constants'; import { CHART_HEIGHT } from './constants';
import type { ForecastReportProps, ForecastData } from './types'; import type { ForecastReportProps, ForecastData } from './types';
@@ -49,15 +49,9 @@ const ForecastReport: React.FC<ForecastReportProps> = ({ stockCode: propStockCod
return ( return (
<Box> <Box>
{/* 加载骨架屏 */} {/* 加载状态 */}
{loading && !data && ( {loading && !data && (
<SimpleGrid columns={{ base: 1, md: 3 }} spacing={4}> <LoadingState message="加载盈利预测数据中..." height="300px" />
{[1, 2, 3].map((i) => (
<ChartCard key={i} title="加载中...">
<Skeleton height={`${CHART_HEIGHT}px`} />
</ChartCard>
))}
</SimpleGrid>
)} )}
{/* 图表区域 - 3列布局 */} {/* 图表区域 - 3列布局 */}

View File

@@ -0,0 +1,44 @@
// src/views/Company/components/LoadingState.tsx
// 统一的加载状态组件 - 黑金主题
import React from "react";
import { Center, VStack, Spinner, Text } from "@chakra-ui/react";
// 黑金主题配置
const THEME = {
gold: "#D4AF37",
textSecondary: "gray.400",
};
interface LoadingStateProps {
message?: string;
height?: string;
}
/**
* 统一的加载状态组件(黑金主题)
*
* 用于所有一级 Tab 的 loading 状态展示
*/
const LoadingState: React.FC<LoadingStateProps> = ({
message = "加载中...",
height = "300px",
}) => {
return (
<Center h={height}>
<VStack spacing={4}>
<Spinner
size="xl"
color={THEME.gold}
thickness="4px"
speed="0.65s"
/>
<Text fontSize="sm" color={THEME.textSecondary}>
{message}
</Text>
</VStack>
</Center>
);
};
export default LoadingState;

View File

@@ -6,7 +6,6 @@ import {
Box, Box,
Container, Container,
CardBody, CardBody,
Spinner,
Center, Center,
VStack, VStack,
Text, Text,
@@ -39,6 +38,7 @@ import {
UnusualPanel, UnusualPanel,
PledgePanel, PledgePanel,
} from './components/panels'; } from './components/panels';
import LoadingState from '../LoadingState';
import type { MarketDataViewProps, RiseAnalysis } from './types'; import type { MarketDataViewProps, RiseAnalysis } from './types';
/** /**
@@ -163,18 +163,7 @@ const MarketDataView: React.FC<MarketDataViewProps> = ({ stockCode: propStockCod
{loading ? ( {loading ? (
<ThemedCard theme={theme}> <ThemedCard theme={theme}>
<CardBody> <CardBody>
<Center h="400px"> <LoadingState message="数据加载中..." height="400px" />
<VStack spacing={4}>
<Spinner
thickness="4px"
speed="0.65s"
emptyColor={theme.bgDark}
color={theme.primary}
size="xl"
/>
<Text color={theme.textSecondary}>...</Text>
</VStack>
</Center>
</CardBody> </CardBody>
</ThemedCard> </ThemedCard>
) : ( ) : (