refactor: 抽取 TabPanelContainer 通用容器组件
- 新增 TabPanelContainer 组件,统一处理 loading 状态和 VStack 布局 - ShareholderPanel 使用 TabPanelContainer 替代原有 loading 判断和 VStack - ManagementPanel 使用 TabPanelContainer 替代原有 loading 判断和 VStack - 组件使用 React.memo 优化渲染性能 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
// 股权结构 Tab Panel - 使用拆分后的子组件
|
||||
|
||||
import React from "react";
|
||||
import { VStack, SimpleGrid, Box } from "@chakra-ui/react";
|
||||
import { SimpleGrid, Box } from "@chakra-ui/react";
|
||||
|
||||
import { useShareholderData } from "../../hooks/useShareholderData";
|
||||
import {
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
ConcentrationCard,
|
||||
ShareholdersTable,
|
||||
} from "../../components/shareholder";
|
||||
import LoadingState from "./LoadingState";
|
||||
import TabPanelContainer from "./TabPanelContainer";
|
||||
|
||||
interface ShareholderPanelProps {
|
||||
stockCode: string;
|
||||
@@ -32,12 +32,8 @@ const ShareholderPanel: React.FC<ShareholderPanelProps> = ({ stockCode }) => {
|
||||
loading,
|
||||
} = useShareholderData(stockCode);
|
||||
|
||||
if (loading) {
|
||||
return <LoadingState message="加载股权结构数据..." />;
|
||||
}
|
||||
|
||||
return (
|
||||
<VStack spacing={6} align="stretch">
|
||||
<TabPanelContainer loading={loading} loadingMessage="加载股权结构数据...">
|
||||
{/* 实际控制人 + 股权集中度 左右分布 */}
|
||||
<SimpleGrid columns={{ base: 1, lg: 2 }} spacing={6}>
|
||||
<Box>
|
||||
@@ -57,7 +53,7 @@ const ShareholderPanel: React.FC<ShareholderPanelProps> = ({ stockCode }) => {
|
||||
<ShareholdersTable type="circulation" shareholders={topCirculationShareholders} />
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</VStack>
|
||||
</TabPanelContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Tab 面板通用容器组件
|
||||
*
|
||||
* 提供统一的 loading 状态处理和布局包裹
|
||||
* 用于 ShareholderPanel、ManagementPanel 等 Tab 面板
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { VStack } from '@chakra-ui/react';
|
||||
import LoadingState from './LoadingState';
|
||||
|
||||
interface TabPanelContainerProps {
|
||||
/** 是否处于加载状态 */
|
||||
loading?: boolean;
|
||||
/** 加载状态显示的文案 */
|
||||
loadingMessage?: string;
|
||||
/** 子组件间距,默认 6 */
|
||||
spacing?: number;
|
||||
/** 子组件 */
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab 面板通用容器
|
||||
*
|
||||
* 功能:
|
||||
* 1. 统一处理 loading 状态,显示 LoadingState 组件
|
||||
* 2. 提供 VStack 布局包裹,统一 spacing 和 align
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <TabPanelContainer loading={loading} loadingMessage="加载数据...">
|
||||
* <YourContent />
|
||||
* </TabPanelContainer>
|
||||
* ```
|
||||
*/
|
||||
const TabPanelContainer: React.FC<TabPanelContainerProps> = memo(({
|
||||
loading = false,
|
||||
loadingMessage = '加载中...',
|
||||
spacing = 6,
|
||||
children,
|
||||
}) => {
|
||||
if (loading) {
|
||||
return <LoadingState message={loadingMessage} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<VStack spacing={spacing} align="stretch">
|
||||
{children}
|
||||
</VStack>
|
||||
);
|
||||
});
|
||||
|
||||
TabPanelContainer.displayName = 'TabPanelContainer';
|
||||
|
||||
export default TabPanelContainer;
|
||||
@@ -2,6 +2,7 @@
|
||||
// 组件导出
|
||||
|
||||
export { default as LoadingState } from "./LoadingState";
|
||||
export { default as TabPanelContainer } from "./TabPanelContainer";
|
||||
export { default as ShareholderPanel } from "./ShareholderPanel";
|
||||
export { ManagementPanel } from "./management";
|
||||
export { default as AnnouncementsPanel } from "./AnnouncementsPanel";
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// 管理团队 Tab Panel(重构版)
|
||||
|
||||
import React, { useMemo } from "react";
|
||||
import { VStack } from "@chakra-ui/react";
|
||||
import {
|
||||
FaUserTie,
|
||||
FaCrown,
|
||||
@@ -12,7 +11,7 @@ import {
|
||||
|
||||
import { useManagementData } from "../../../hooks/useManagementData";
|
||||
import { THEME } from "../../config";
|
||||
import LoadingState from "../LoadingState";
|
||||
import TabPanelContainer from "../TabPanelContainer";
|
||||
import CategorySection from "./CategorySection";
|
||||
import type {
|
||||
ManagementPerson,
|
||||
@@ -78,12 +77,8 @@ const ManagementPanel: React.FC<ManagementPanelProps> = ({ stockCode }) => {
|
||||
[management]
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return <LoadingState message="加载管理团队数据..." />;
|
||||
}
|
||||
|
||||
return (
|
||||
<VStack spacing={6} align="stretch">
|
||||
<TabPanelContainer loading={loading} loadingMessage="加载管理团队数据...">
|
||||
{CATEGORY_ORDER.map((category) => {
|
||||
const config = CATEGORY_CONFIG[category];
|
||||
const people = categorizedManagement[category];
|
||||
@@ -98,7 +93,7 @@ const ManagementPanel: React.FC<ManagementPanelProps> = ({ stockCode }) => {
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</VStack>
|
||||
</TabPanelContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user