refactor: 抽取通用 Tab 容器组件,重构 BasicInfoTab 和 DeepAnalysisTab

新增组件:
- TabPanelContainer: 三级容器,统一 loading 状态 + VStack 布局 + 免责声明
- SubTabContainer: 二级导航容器,支持黑金/默认主题预设

重构:
- BasicInfoTab: 使用 SubTabContainer 替代原有 Tabs 实现
- DeepAnalysisTab: 拆分为 4 个子 Tab(战略分析/业务结构/产业链/发展历程)
- TabContainer: 样式调整,与 SubTabContainer 保持一致

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-12 11:55:50 +08:00
parent 96fe919164
commit b8cd520014
15 changed files with 572 additions and 234 deletions

View File

@@ -1,21 +1,11 @@
// src/views/Company/components/CompanyOverview/BasicInfoTab/index.tsx
// 基本信息 Tab 组件 - 可配置版本(黑金主题)
// 基本信息 Tab 组件 - 使用 SubTabContainer 通用组件
import React from "react";
import {
Card,
CardBody,
Tabs,
TabList,
TabPanels,
Tab,
TabPanel,
Icon,
HStack,
Text,
} from "@chakra-ui/react";
import React, { useMemo } from "react";
import { Card, CardBody } from "@chakra-ui/react";
import SubTabContainer, { type SubTabConfig } from "@components/SubTabContainer";
import { THEME, TAB_CONFIG, getEnabledTabs, type TabConfig } from "./config";
import { THEME, TAB_CONFIG, getEnabledTabs } from "./config";
import {
ShareholderPanel,
ManagementPanel,
@@ -44,13 +34,27 @@ const TAB_COMPONENTS: Record<string, React.FC<any>> = {
business: BusinessInfoPanel,
};
/**
* 构建 SubTabContainer 所需的 tabs 配置
*/
const buildTabsConfig = (enabledKeys?: string[]): SubTabConfig[] => {
const enabledTabs = getEnabledTabs(enabledKeys);
return enabledTabs.map((tab) => ({
key: tab.key,
name: tab.name,
icon: tab.icon,
component: TAB_COMPONENTS[tab.key],
}));
};
/**
* 基本信息 Tab 组件
*
* 特性:
* - 使用 SubTabContainer 通用组件
* - 可配置显示哪些 TabenabledTabs
* - 黑金主题
* - 懒加载isLazy
* - 懒加载
* - 支持 Tab 变更回调
*/
const BasicInfoTab: React.FC<BasicInfoTabProps> = ({
@@ -60,79 +64,19 @@ const BasicInfoTab: React.FC<BasicInfoTabProps> = ({
defaultTabIndex = 0,
onTabChange,
}) => {
// 获取启用的 Tab 配置
const tabs = getEnabledTabs(enabledTabs);
// 处理 Tab 变更
const handleTabChange = (index: number) => {
if (onTabChange && tabs[index]) {
onTabChange(index, tabs[index].key);
}
};
// 渲染单个 Tab 内容
const renderTabContent = (tab: TabConfig) => {
const Component = TAB_COMPONENTS[tab.key];
if (!Component) return null;
// business Tab 需要 basicInfo其他需要 stockCode
if (tab.key === "business") {
return <Component basicInfo={basicInfo} />;
}
return <Component stockCode={stockCode} />;
};
// 构建 tabs 配置(缓存避免重复计算)
const tabs = useMemo(() => buildTabsConfig(enabledTabs), [enabledTabs]);
return (
<Card bg={THEME.cardBg} shadow="md" border="1px solid" borderColor={THEME.border}>
<CardBody p={0}>
<Tabs
isLazy
variant="unstyled"
<SubTabContainer
tabs={tabs}
componentProps={{ stockCode, basicInfo }}
defaultIndex={defaultTabIndex}
onChange={handleTabChange}
>
<TabList
bg={THEME.bg}
borderBottom="1px solid"
borderColor={THEME.border}
px={4}
py={2}
flexWrap="wrap"
gap={2}
>
{tabs.map((tab) => (
<Tab
key={tab.key}
color={THEME.tabUnselected.color}
borderRadius="full"
px={4}
py={2}
fontSize="sm"
_selected={{
bg: THEME.tabSelected.bg,
color: THEME.tabSelected.color,
fontWeight: "bold",
}}
_hover={{
bg: THEME.tableHoverBg,
}}
>
<HStack spacing={2}>
<Icon as={tab.icon} boxSize={4} />
<Text>{tab.name}</Text>
</HStack>
</Tab>
))}
</TabList>
<TabPanels p={4}>
{tabs.map((tab) => (
<TabPanel key={tab.key} p={0}>
{renderTabContent(tab)}
</TabPanel>
))}
</TabPanels>
</Tabs>
onTabChange={onTabChange}
themePreset="blackGold"
/>
</CardBody>
</Card>
);