fix(FinancialPanorama): 优化 loading 状态,Tabs 立即显示
- 移除 SubTabContainer 的 loading 条件渲染,Tabs 始终可见 - 各 Tab 组件内部处理 loading 状态,显示 Spinner - 传递 loading 和 loadingTab 到 componentProps - 修改 BalanceSheetTab、IncomeStatementTab、CashflowTab、 FinancialMetricsTab、MetricsCategoryTab 支持 loading 属性 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -250,6 +250,9 @@ const FinancialPanorama: React.FC<FinancialPanoramaProps> = ({ stockCode: propSt
|
|||||||
incomeStatement,
|
incomeStatement,
|
||||||
cashflow,
|
cashflow,
|
||||||
financialMetrics,
|
financialMetrics,
|
||||||
|
// 加载状态
|
||||||
|
loading,
|
||||||
|
loadingTab,
|
||||||
// 工具函数
|
// 工具函数
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
@@ -265,6 +268,8 @@ const FinancialPanorama: React.FC<FinancialPanoramaProps> = ({ stockCode: propSt
|
|||||||
incomeStatement,
|
incomeStatement,
|
||||||
cashflow,
|
cashflow,
|
||||||
financialMetrics,
|
financialMetrics,
|
||||||
|
loading,
|
||||||
|
loadingTab,
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
positiveColor,
|
positiveColor,
|
||||||
negativeColor,
|
negativeColor,
|
||||||
@@ -302,27 +307,25 @@ const FinancialPanorama: React.FC<FinancialPanoramaProps> = ({ stockCode: propSt
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 三大财务报表 - 使用 SubTabContainer 二级导航 */}
|
{/* 三大财务报表 - 使用 SubTabContainer 二级导航 */}
|
||||||
{!loading && stockInfo && (
|
<Card bg="gray.900" shadow="md" border="1px solid" borderColor="rgba(212, 175, 55, 0.3)">
|
||||||
<Card bg="gray.900" shadow="md" border="1px solid" borderColor="rgba(212, 175, 55, 0.3)">
|
<CardBody p={0}>
|
||||||
<CardBody p={0}>
|
<SubTabContainer
|
||||||
<SubTabContainer
|
tabs={tabConfigs}
|
||||||
tabs={tabConfigs}
|
componentProps={componentProps}
|
||||||
componentProps={componentProps}
|
themePreset="blackGold"
|
||||||
themePreset="blackGold"
|
isLazy
|
||||||
isLazy
|
onTabChange={handleTabChange}
|
||||||
onTabChange={handleTabChange}
|
rightElement={
|
||||||
rightElement={
|
<PeriodSelector
|
||||||
<PeriodSelector
|
selectedPeriods={selectedPeriods}
|
||||||
selectedPeriods={selectedPeriods}
|
onPeriodsChange={setSelectedPeriods}
|
||||||
onPeriodsChange={setSelectedPeriods}
|
onRefresh={handleRefresh}
|
||||||
onRefresh={handleRefresh}
|
isLoading={loadingTab !== null || loading}
|
||||||
isLoading={loadingTab !== null}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
/>
|
||||||
/>
|
</CardBody>
|
||||||
</CardBody>
|
</Card>
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 错误提示 */}
|
{/* 错误提示 */}
|
||||||
{error && (
|
{error && (
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, VStack, HStack, Heading, Badge, Text } from '@chakra-ui/react';
|
import { Box, VStack, HStack, Heading, Badge, Text, Spinner, Center } from '@chakra-ui/react';
|
||||||
import { BalanceSheetTable } from '../components';
|
import { BalanceSheetTable } from '../components';
|
||||||
import type { BalanceSheetData } from '../types';
|
import type { BalanceSheetData } from '../types';
|
||||||
|
|
||||||
export interface BalanceSheetTabProps {
|
export interface BalanceSheetTabProps {
|
||||||
balanceSheet: BalanceSheetData[];
|
balanceSheet: BalanceSheetData[];
|
||||||
|
loading?: boolean;
|
||||||
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
||||||
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
||||||
getCellBackground: (change: number, intensity: number) => string;
|
getCellBackground: (change: number, intensity: number) => string;
|
||||||
@@ -20,6 +21,7 @@ export interface BalanceSheetTabProps {
|
|||||||
|
|
||||||
const BalanceSheetTab: React.FC<BalanceSheetTabProps> = ({
|
const BalanceSheetTab: React.FC<BalanceSheetTabProps> = ({
|
||||||
balanceSheet,
|
balanceSheet,
|
||||||
|
loading,
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
getCellBackground,
|
getCellBackground,
|
||||||
@@ -28,6 +30,15 @@ const BalanceSheetTab: React.FC<BalanceSheetTabProps> = ({
|
|||||||
bgColor,
|
bgColor,
|
||||||
hoverBg,
|
hoverBg,
|
||||||
}) => {
|
}) => {
|
||||||
|
// 加载中状态
|
||||||
|
if (loading && (!Array.isArray(balanceSheet) || balanceSheet.length === 0)) {
|
||||||
|
return (
|
||||||
|
<Center py={12}>
|
||||||
|
<Spinner size="lg" color="#D4AF37" thickness="3px" />
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const tableProps = {
|
const tableProps = {
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, VStack, HStack, Heading, Badge, Text } from '@chakra-ui/react';
|
import { Box, VStack, HStack, Heading, Badge, Text, Spinner, Center } from '@chakra-ui/react';
|
||||||
import { CashflowTable } from '../components';
|
import { CashflowTable } from '../components';
|
||||||
import type { CashflowData } from '../types';
|
import type { CashflowData } from '../types';
|
||||||
|
|
||||||
export interface CashflowTabProps {
|
export interface CashflowTabProps {
|
||||||
cashflow: CashflowData[];
|
cashflow: CashflowData[];
|
||||||
|
loading?: boolean;
|
||||||
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
||||||
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
||||||
getCellBackground: (change: number, intensity: number) => string;
|
getCellBackground: (change: number, intensity: number) => string;
|
||||||
@@ -20,6 +21,7 @@ export interface CashflowTabProps {
|
|||||||
|
|
||||||
const CashflowTab: React.FC<CashflowTabProps> = ({
|
const CashflowTab: React.FC<CashflowTabProps> = ({
|
||||||
cashflow,
|
cashflow,
|
||||||
|
loading,
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
getCellBackground,
|
getCellBackground,
|
||||||
@@ -28,6 +30,15 @@ const CashflowTab: React.FC<CashflowTabProps> = ({
|
|||||||
bgColor,
|
bgColor,
|
||||||
hoverBg,
|
hoverBg,
|
||||||
}) => {
|
}) => {
|
||||||
|
// 加载中状态
|
||||||
|
if (loading && (!Array.isArray(cashflow) || cashflow.length === 0)) {
|
||||||
|
return (
|
||||||
|
<Center py={12}>
|
||||||
|
<Spinner size="lg" color="#D4AF37" thickness="3px" />
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const tableProps = {
|
const tableProps = {
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
|
|||||||
@@ -3,11 +3,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Spinner, Center } from '@chakra-ui/react';
|
||||||
import { FinancialMetricsTable } from '../components';
|
import { FinancialMetricsTable } from '../components';
|
||||||
import type { FinancialMetricsData } from '../types';
|
import type { FinancialMetricsData } from '../types';
|
||||||
|
|
||||||
export interface FinancialMetricsTabProps {
|
export interface FinancialMetricsTabProps {
|
||||||
financialMetrics: FinancialMetricsData[];
|
financialMetrics: FinancialMetricsData[];
|
||||||
|
loading?: boolean;
|
||||||
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
||||||
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
||||||
getCellBackground: (change: number, intensity: number) => string;
|
getCellBackground: (change: number, intensity: number) => string;
|
||||||
@@ -19,6 +21,7 @@ export interface FinancialMetricsTabProps {
|
|||||||
|
|
||||||
const FinancialMetricsTab: React.FC<FinancialMetricsTabProps> = ({
|
const FinancialMetricsTab: React.FC<FinancialMetricsTabProps> = ({
|
||||||
financialMetrics,
|
financialMetrics,
|
||||||
|
loading,
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
getCellBackground,
|
getCellBackground,
|
||||||
@@ -27,6 +30,15 @@ const FinancialMetricsTab: React.FC<FinancialMetricsTabProps> = ({
|
|||||||
bgColor,
|
bgColor,
|
||||||
hoverBg,
|
hoverBg,
|
||||||
}) => {
|
}) => {
|
||||||
|
// 加载中状态
|
||||||
|
if (loading && (!Array.isArray(financialMetrics) || financialMetrics.length === 0)) {
|
||||||
|
return (
|
||||||
|
<Center py={12}>
|
||||||
|
<Spinner size="lg" color="#D4AF37" thickness="3px" />
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const tableProps = {
|
const tableProps = {
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, VStack, HStack, Heading, Badge, Text } from '@chakra-ui/react';
|
import { Box, VStack, HStack, Heading, Badge, Text, Spinner, Center } from '@chakra-ui/react';
|
||||||
import { IncomeStatementTable } from '../components';
|
import { IncomeStatementTable } from '../components';
|
||||||
import type { IncomeStatementData } from '../types';
|
import type { IncomeStatementData } from '../types';
|
||||||
|
|
||||||
export interface IncomeStatementTabProps {
|
export interface IncomeStatementTabProps {
|
||||||
incomeStatement: IncomeStatementData[];
|
incomeStatement: IncomeStatementData[];
|
||||||
|
loading?: boolean;
|
||||||
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
||||||
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
||||||
getCellBackground: (change: number, intensity: number) => string;
|
getCellBackground: (change: number, intensity: number) => string;
|
||||||
@@ -20,6 +21,7 @@ export interface IncomeStatementTabProps {
|
|||||||
|
|
||||||
const IncomeStatementTab: React.FC<IncomeStatementTabProps> = ({
|
const IncomeStatementTab: React.FC<IncomeStatementTabProps> = ({
|
||||||
incomeStatement,
|
incomeStatement,
|
||||||
|
loading,
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
getCellBackground,
|
getCellBackground,
|
||||||
@@ -28,6 +30,15 @@ const IncomeStatementTab: React.FC<IncomeStatementTabProps> = ({
|
|||||||
bgColor,
|
bgColor,
|
||||||
hoverBg,
|
hoverBg,
|
||||||
}) => {
|
}) => {
|
||||||
|
// 加载中状态
|
||||||
|
if (loading && (!Array.isArray(incomeStatement) || incomeStatement.length === 0)) {
|
||||||
|
return (
|
||||||
|
<Center py={12}>
|
||||||
|
<Spinner size="lg" color="#D4AF37" thickness="3px" />
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const tableProps = {
|
const tableProps = {
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Text, HStack, Badge as ChakraBadge } from '@chakra-ui/react';
|
import { Box, Text, HStack, Badge as ChakraBadge, Spinner, Center } from '@chakra-ui/react';
|
||||||
import { Table, ConfigProvider, Tooltip } from 'antd';
|
import { Table, ConfigProvider, Tooltip } from 'antd';
|
||||||
import type { ColumnsType } from 'antd/es/table';
|
import type { ColumnsType } from 'antd/es/table';
|
||||||
import { Eye } from 'lucide-react';
|
import { Eye } from 'lucide-react';
|
||||||
@@ -86,6 +86,7 @@ const tableStyles = `
|
|||||||
export interface MetricsCategoryTabProps {
|
export interface MetricsCategoryTabProps {
|
||||||
categoryKey: CategoryKey;
|
categoryKey: CategoryKey;
|
||||||
financialMetrics: FinancialMetricsData[];
|
financialMetrics: FinancialMetricsData[];
|
||||||
|
loading?: boolean;
|
||||||
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
showMetricChart: (name: string, key: string, data: unknown[], path: string) => void;
|
||||||
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
calculateYoYChange: (value: number, period: string, data: unknown[], path: string) => { change: number; intensity: number };
|
||||||
getCellBackground: (change: number, intensity: number) => string;
|
getCellBackground: (change: number, intensity: number) => string;
|
||||||
@@ -107,9 +108,19 @@ interface TableRowData {
|
|||||||
const MetricsCategoryTab: React.FC<MetricsCategoryTabProps> = ({
|
const MetricsCategoryTab: React.FC<MetricsCategoryTabProps> = ({
|
||||||
categoryKey,
|
categoryKey,
|
||||||
financialMetrics,
|
financialMetrics,
|
||||||
|
loading,
|
||||||
showMetricChart,
|
showMetricChart,
|
||||||
calculateYoYChange,
|
calculateYoYChange,
|
||||||
}) => {
|
}) => {
|
||||||
|
// 加载中状态
|
||||||
|
if (loading && (!Array.isArray(financialMetrics) || financialMetrics.length === 0)) {
|
||||||
|
return (
|
||||||
|
<Center py={12}>
|
||||||
|
<Spinner size="lg" color="#D4AF37" thickness="3px" />
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 数组安全检查
|
// 数组安全检查
|
||||||
if (!Array.isArray(financialMetrics) || financialMetrics.length === 0) {
|
if (!Array.isArray(financialMetrics) || financialMetrics.length === 0) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user