refactor: ManagementPanel 组件拆分重构
- 创建 management/ 子目录,模块化管理 - 拆分为 5 个 TypeScript 文件:types.ts、ManagementPanel.tsx、CategorySection.tsx、ManagementCard.tsx、index.ts - 添加 useMemo 缓存分类计算结果 - 使用 React.memo 优化 ManagementCard 和 CategorySection - 添加完整的 TypeScript 类型定义,消除 any - 更新 STRUCTURE.md 同步目录结构 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,12 @@ src/views/Company/
|
|||||||
│ │ │ ├── index.ts # 组件统一导出
|
│ │ │ ├── index.ts # 组件统一导出
|
||||||
│ │ │ ├── LoadingState.tsx # 加载状态组件(黑金主题 Spinner)
|
│ │ │ ├── LoadingState.tsx # 加载状态组件(黑金主题 Spinner)
|
||||||
│ │ │ ├── ShareholderPanel.tsx # 股权结构面板(实控人、十大股东、股权集中度)
|
│ │ │ ├── ShareholderPanel.tsx # 股权结构面板(实控人、十大股东、股权集中度)
|
||||||
│ │ │ ├── ManagementPanel.tsx # 管理团队面板(高管列表表格)
|
│ │ │ ├── management/ # 管理团队模块(拆分重构)
|
||||||
|
│ │ │ │ ├── index.ts # 模块导出
|
||||||
|
│ │ │ │ ├── types.ts # 类型定义(ManagementPerson 等)
|
||||||
|
│ │ │ │ ├── ManagementPanel.tsx # 主组件(useMemo 优化)
|
||||||
|
│ │ │ │ ├── CategorySection.tsx # 分类区块(memo 优化)
|
||||||
|
│ │ │ │ └── ManagementCard.tsx # 人员卡片(memo 优化)
|
||||||
│ │ │ ├── AnnouncementsPanel.tsx # 公告信息面板(公告列表 + 披露日程)
|
│ │ │ ├── AnnouncementsPanel.tsx # 公告信息面板(公告列表 + 披露日程)
|
||||||
│ │ │ ├── BranchesPanel.tsx # 分支机构面板(分支列表表格)
|
│ │ │ ├── BranchesPanel.tsx # 分支机构面板(分支列表表格)
|
||||||
│ │ │ └── BusinessInfoPanel.tsx # 工商信息面板(注册资本、成立日期等)
|
│ │ │ └── BusinessInfoPanel.tsx # 工商信息面板(注册资本、成立日期等)
|
||||||
@@ -469,3 +474,36 @@ MarketDataView/
|
|||||||
- **服务层分离**:API 调用统一在 `marketService.ts` 中管理
|
- **服务层分离**:API 调用统一在 `marketService.ts` 中管理
|
||||||
- **图表配置抽离**:复杂的 ECharts 配置集中在 `chartOptions.ts`
|
- **图表配置抽离**:复杂的 ECharts 配置集中在 `chartOptions.ts`
|
||||||
- **组件复用**:通用组件(ThemedCard、MarkdownRenderer)可在其他模块使用
|
- **组件复用**:通用组件(ThemedCard、MarkdownRenderer)可在其他模块使用
|
||||||
|
|
||||||
|
### 2025-12-10 ManagementPanel 拆分重构
|
||||||
|
|
||||||
|
**改动概述**:
|
||||||
|
- `ManagementPanel.tsx` 从 **180 行** 拆分为 **5 个 TypeScript 文件**
|
||||||
|
- 创建 `management/` 子目录,模块化管理
|
||||||
|
- 添加性能优化(`useMemo`、`React.memo`)
|
||||||
|
|
||||||
|
**拆分后文件结构**:
|
||||||
|
```
|
||||||
|
components/management/
|
||||||
|
├── index.ts # 模块导出
|
||||||
|
├── types.ts # 类型定义(~35 行)
|
||||||
|
├── ManagementPanel.tsx # 主组件(~105 行,useMemo 优化)
|
||||||
|
├── CategorySection.tsx # 分类区块组件(~65 行,memo)
|
||||||
|
└── ManagementCard.tsx # 人员卡片组件(~100 行,memo)
|
||||||
|
```
|
||||||
|
|
||||||
|
**类型定义**(`types.ts`):
|
||||||
|
- `ManagementPerson` - 管理人员信息
|
||||||
|
- `ManagementCategory` - 分类类型(高管/董事/监事/其他)
|
||||||
|
- `CategorizedManagement` - 分类后的数据结构
|
||||||
|
- `CategoryConfig` - 分类配置(图标、颜色)
|
||||||
|
|
||||||
|
**性能优化**:
|
||||||
|
- `useMemo` - 缓存 `categorizeManagement()` 分类计算结果
|
||||||
|
- `React.memo` - `ManagementCard` 和 `CategorySection` 使用 memo 包装
|
||||||
|
- 常量提取 - `CATEGORY_CONFIG` 和 `CATEGORY_ORDER` 提取到组件外部
|
||||||
|
|
||||||
|
**设计原则**:
|
||||||
|
- **职责分离**:卡片渲染、分类区块、数据处理各自独立
|
||||||
|
- **类型安全**:消除 `any` 类型,完整的 TypeScript 类型定义
|
||||||
|
- **可复用性**:`ManagementCard` 可独立使用
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
// src/views/Company/components/CompanyOverview/BasicInfoTab/components/ManagementPanel.tsx
|
|
||||||
// 管理团队 Tab Panel
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
VStack,
|
|
||||||
HStack,
|
|
||||||
Text,
|
|
||||||
Heading,
|
|
||||||
Badge,
|
|
||||||
Icon,
|
|
||||||
Card,
|
|
||||||
CardBody,
|
|
||||||
SimpleGrid,
|
|
||||||
Avatar,
|
|
||||||
Tag,
|
|
||||||
} from "@chakra-ui/react";
|
|
||||||
import {
|
|
||||||
FaUserTie,
|
|
||||||
FaCrown,
|
|
||||||
FaEye,
|
|
||||||
FaUsers,
|
|
||||||
FaVenusMars,
|
|
||||||
FaGraduationCap,
|
|
||||||
FaPassport,
|
|
||||||
} from "react-icons/fa";
|
|
||||||
|
|
||||||
import { useManagementData } from "../../hooks/useManagementData";
|
|
||||||
import { THEME } from "../config";
|
|
||||||
import { formatDate } from "../utils";
|
|
||||||
import LoadingState from "./LoadingState";
|
|
||||||
|
|
||||||
interface ManagementPanelProps {
|
|
||||||
stockCode: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ManagementPanel: React.FC<ManagementPanelProps> = ({ stockCode }) => {
|
|
||||||
const { management, loading } = useManagementData(stockCode);
|
|
||||||
|
|
||||||
// 管理层职位分类
|
|
||||||
const getManagementByCategory = () => {
|
|
||||||
const categories: Record<string, any[]> = {
|
|
||||||
高管: [],
|
|
||||||
董事: [],
|
|
||||||
监事: [],
|
|
||||||
其他: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
management.forEach((person: any) => {
|
|
||||||
if (
|
|
||||||
person.position_category === "高管" ||
|
|
||||||
person.position_name?.includes("总")
|
|
||||||
) {
|
|
||||||
categories["高管"].push(person);
|
|
||||||
} else if (
|
|
||||||
person.position_category === "董事" ||
|
|
||||||
person.position_name?.includes("董事")
|
|
||||||
) {
|
|
||||||
categories["董事"].push(person);
|
|
||||||
} else if (
|
|
||||||
person.position_category === "监事" ||
|
|
||||||
person.position_name?.includes("监事")
|
|
||||||
) {
|
|
||||||
categories["监事"].push(person);
|
|
||||||
} else {
|
|
||||||
categories["其他"].push(person);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return categories;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getCategoryIcon = (category: string) => {
|
|
||||||
switch (category) {
|
|
||||||
case "高管":
|
|
||||||
return FaUserTie;
|
|
||||||
case "董事":
|
|
||||||
return FaCrown;
|
|
||||||
case "监事":
|
|
||||||
return FaEye;
|
|
||||||
default:
|
|
||||||
return FaUsers;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getCategoryColor = (category: string) => {
|
|
||||||
switch (category) {
|
|
||||||
case "高管":
|
|
||||||
return THEME.gold;
|
|
||||||
case "董事":
|
|
||||||
return THEME.goldLight;
|
|
||||||
case "监事":
|
|
||||||
return "green.400";
|
|
||||||
default:
|
|
||||||
return THEME.textSecondary;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <LoadingState message="加载管理团队数据..." />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<VStack spacing={6} align="stretch">
|
|
||||||
{Object.entries(getManagementByCategory()).map(
|
|
||||||
([category, people]) =>
|
|
||||||
people.length > 0 && (
|
|
||||||
<Box key={category}>
|
|
||||||
<HStack mb={4}>
|
|
||||||
<Icon
|
|
||||||
as={getCategoryIcon(category)}
|
|
||||||
color={getCategoryColor(category)}
|
|
||||||
boxSize={5}
|
|
||||||
/>
|
|
||||||
<Heading size="sm" color={THEME.textPrimary}>{category}</Heading>
|
|
||||||
<Badge bg={THEME.gold} color="gray.900">{people.length}人</Badge>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={4}>
|
|
||||||
{people.map((person: any, idx: number) => (
|
|
||||||
<Card key={idx} bg={THEME.tableBg} border="1px solid" borderColor={THEME.border} size="sm">
|
|
||||||
<CardBody>
|
|
||||||
<HStack spacing={3} align="start">
|
|
||||||
<Avatar
|
|
||||||
name={person.name}
|
|
||||||
size="md"
|
|
||||||
bg={getCategoryColor(category)}
|
|
||||||
/>
|
|
||||||
<VStack align="start" spacing={1} flex={1}>
|
|
||||||
<HStack>
|
|
||||||
<Text fontWeight="bold" color={THEME.textPrimary}>{person.name}</Text>
|
|
||||||
{person.gender && (
|
|
||||||
<Icon
|
|
||||||
as={FaVenusMars}
|
|
||||||
color={person.gender === "男" ? "blue.400" : "pink.400"}
|
|
||||||
boxSize={3}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</HStack>
|
|
||||||
<Text fontSize="sm" color={THEME.goldLight}>
|
|
||||||
{person.position_name}
|
|
||||||
</Text>
|
|
||||||
<HStack spacing={2} flexWrap="wrap">
|
|
||||||
{person.education && (
|
|
||||||
<Tag size="sm" bg={THEME.tableHoverBg} color={THEME.textSecondary}>
|
|
||||||
<Icon as={FaGraduationCap} mr={1} boxSize={3} />
|
|
||||||
{person.education}
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
{person.birth_year && (
|
|
||||||
<Tag size="sm" bg={THEME.tableHoverBg} color={THEME.textSecondary}>
|
|
||||||
{new Date().getFullYear() - parseInt(person.birth_year)}岁
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
{person.nationality && person.nationality !== "中国" && (
|
|
||||||
<Tag size="sm" bg="orange.600" color="white">
|
|
||||||
<Icon as={FaPassport} mr={1} boxSize={3} />
|
|
||||||
{person.nationality}
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
</HStack>
|
|
||||||
<Text fontSize="xs" color={THEME.textSecondary}>
|
|
||||||
任职日期:{formatDate(person.start_date)}
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
</HStack>
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</VStack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ManagementPanel;
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
export { default as LoadingState } from "./LoadingState";
|
export { default as LoadingState } from "./LoadingState";
|
||||||
export { default as ShareholderPanel } from "./ShareholderPanel";
|
export { default as ShareholderPanel } from "./ShareholderPanel";
|
||||||
export { default as ManagementPanel } from "./ManagementPanel";
|
export { ManagementPanel } from "./management";
|
||||||
export { default as AnnouncementsPanel } from "./AnnouncementsPanel";
|
export { default as AnnouncementsPanel } from "./AnnouncementsPanel";
|
||||||
export { default as BranchesPanel } from "./BranchesPanel";
|
export { default as BranchesPanel } from "./BranchesPanel";
|
||||||
export { default as BusinessInfoPanel } from "./BusinessInfoPanel";
|
export { default as BusinessInfoPanel } from "./BusinessInfoPanel";
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// src/views/Company/components/CompanyOverview/BasicInfoTab/components/management/CategorySection.tsx
|
||||||
|
// 管理层分类区块组件
|
||||||
|
|
||||||
|
import React, { memo } from "react";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
HStack,
|
||||||
|
Heading,
|
||||||
|
Badge,
|
||||||
|
Icon,
|
||||||
|
SimpleGrid,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import type { IconType } from "react-icons";
|
||||||
|
|
||||||
|
import { THEME } from "../../config";
|
||||||
|
import ManagementCard from "./ManagementCard";
|
||||||
|
import type { ManagementPerson, ManagementCategory } from "./types";
|
||||||
|
|
||||||
|
interface CategorySectionProps {
|
||||||
|
category: ManagementCategory;
|
||||||
|
people: ManagementPerson[];
|
||||||
|
icon: IconType;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CategorySection: React.FC<CategorySectionProps> = ({
|
||||||
|
category,
|
||||||
|
people,
|
||||||
|
icon,
|
||||||
|
color,
|
||||||
|
}) => {
|
||||||
|
if (people.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
{/* 分类标题 */}
|
||||||
|
<HStack mb={4}>
|
||||||
|
<Icon as={icon} color={color} boxSize={5} />
|
||||||
|
<Heading size="sm" color={THEME.textPrimary}>
|
||||||
|
{category}
|
||||||
|
</Heading>
|
||||||
|
<Badge bg={THEME.gold} color="gray.900">
|
||||||
|
{people.length}人
|
||||||
|
</Badge>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 人员卡片网格 */}
|
||||||
|
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={4}>
|
||||||
|
{people.map((person, idx) => (
|
||||||
|
<ManagementCard
|
||||||
|
key={`${person.name}-${idx}`}
|
||||||
|
person={person}
|
||||||
|
categoryColor={color}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(CategorySection);
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
// src/views/Company/components/CompanyOverview/BasicInfoTab/components/management/ManagementCard.tsx
|
||||||
|
// 管理人员卡片组件
|
||||||
|
|
||||||
|
import React, { memo } from "react";
|
||||||
|
import {
|
||||||
|
HStack,
|
||||||
|
VStack,
|
||||||
|
Text,
|
||||||
|
Icon,
|
||||||
|
Card,
|
||||||
|
CardBody,
|
||||||
|
Avatar,
|
||||||
|
Tag,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import {
|
||||||
|
FaVenusMars,
|
||||||
|
FaGraduationCap,
|
||||||
|
FaPassport,
|
||||||
|
} from "react-icons/fa";
|
||||||
|
|
||||||
|
import { THEME } from "../../config";
|
||||||
|
import { formatDate } from "../../utils";
|
||||||
|
import type { ManagementPerson } from "./types";
|
||||||
|
|
||||||
|
interface ManagementCardProps {
|
||||||
|
person: ManagementPerson;
|
||||||
|
categoryColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ManagementCard: React.FC<ManagementCardProps> = ({ person, categoryColor }) => {
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
const age = person.birth_year ? currentYear - parseInt(person.birth_year, 10) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
bg={THEME.tableBg}
|
||||||
|
border="1px solid"
|
||||||
|
borderColor={THEME.border}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<CardBody>
|
||||||
|
<HStack spacing={3} align="start">
|
||||||
|
<Avatar
|
||||||
|
name={person.name}
|
||||||
|
size="md"
|
||||||
|
bg={categoryColor}
|
||||||
|
/>
|
||||||
|
<VStack align="start" spacing={1} flex={1}>
|
||||||
|
{/* 姓名和性别 */}
|
||||||
|
<HStack>
|
||||||
|
<Text fontWeight="bold" color={THEME.textPrimary}>
|
||||||
|
{person.name}
|
||||||
|
</Text>
|
||||||
|
{person.gender && (
|
||||||
|
<Icon
|
||||||
|
as={FaVenusMars}
|
||||||
|
color={person.gender === "男" ? "blue.400" : "pink.400"}
|
||||||
|
boxSize={3}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 职位 */}
|
||||||
|
<Text fontSize="sm" color={THEME.goldLight}>
|
||||||
|
{person.position_name}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{/* 标签:学历、年龄、国籍 */}
|
||||||
|
<HStack spacing={2} flexWrap="wrap">
|
||||||
|
{person.education && (
|
||||||
|
<Tag size="sm" bg={THEME.tableHoverBg} color={THEME.textSecondary}>
|
||||||
|
<Icon as={FaGraduationCap} mr={1} boxSize={3} />
|
||||||
|
{person.education}
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
{age && (
|
||||||
|
<Tag size="sm" bg={THEME.tableHoverBg} color={THEME.textSecondary}>
|
||||||
|
{age}岁
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
{person.nationality && person.nationality !== "中国" && (
|
||||||
|
<Tag size="sm" bg="orange.600" color="white">
|
||||||
|
<Icon as={FaPassport} mr={1} boxSize={3} />
|
||||||
|
{person.nationality}
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 任职日期 */}
|
||||||
|
<Text fontSize="xs" color={THEME.textSecondary}>
|
||||||
|
任职日期:{formatDate(person.start_date)}
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
</HStack>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ManagementCard);
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// src/views/Company/components/CompanyOverview/BasicInfoTab/components/management/ManagementPanel.tsx
|
||||||
|
// 管理团队 Tab Panel(重构版)
|
||||||
|
|
||||||
|
import React, { useMemo } from "react";
|
||||||
|
import { VStack } from "@chakra-ui/react";
|
||||||
|
import {
|
||||||
|
FaUserTie,
|
||||||
|
FaCrown,
|
||||||
|
FaEye,
|
||||||
|
FaUsers,
|
||||||
|
} from "react-icons/fa";
|
||||||
|
|
||||||
|
import { useManagementData } from "../../../hooks/useManagementData";
|
||||||
|
import { THEME } from "../../config";
|
||||||
|
import LoadingState from "../LoadingState";
|
||||||
|
import CategorySection from "./CategorySection";
|
||||||
|
import type {
|
||||||
|
ManagementPerson,
|
||||||
|
ManagementCategory,
|
||||||
|
CategorizedManagement,
|
||||||
|
CategoryConfig,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
interface ManagementPanelProps {
|
||||||
|
stockCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类配置映射
|
||||||
|
*/
|
||||||
|
const CATEGORY_CONFIG: Record<ManagementCategory, CategoryConfig> = {
|
||||||
|
高管: { icon: FaUserTie, color: THEME.gold },
|
||||||
|
董事: { icon: FaCrown, color: THEME.goldLight },
|
||||||
|
监事: { icon: FaEye, color: "green.400" },
|
||||||
|
其他: { icon: FaUsers, color: THEME.textSecondary },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类顺序
|
||||||
|
*/
|
||||||
|
const CATEGORY_ORDER: ManagementCategory[] = ["高管", "董事", "监事", "其他"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据职位信息对管理人员进行分类
|
||||||
|
*/
|
||||||
|
const categorizeManagement = (management: ManagementPerson[]): CategorizedManagement => {
|
||||||
|
const categories: CategorizedManagement = {
|
||||||
|
高管: [],
|
||||||
|
董事: [],
|
||||||
|
监事: [],
|
||||||
|
其他: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
management.forEach((person) => {
|
||||||
|
const positionCategory = person.position_category;
|
||||||
|
const positionName = person.position_name || "";
|
||||||
|
|
||||||
|
if (positionCategory === "高管" || positionName.includes("总")) {
|
||||||
|
categories["高管"].push(person);
|
||||||
|
} else if (positionCategory === "董事" || positionName.includes("董事")) {
|
||||||
|
categories["董事"].push(person);
|
||||||
|
} else if (positionCategory === "监事" || positionName.includes("监事")) {
|
||||||
|
categories["监事"].push(person);
|
||||||
|
} else {
|
||||||
|
categories["其他"].push(person);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return categories;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ManagementPanel: React.FC<ManagementPanelProps> = ({ stockCode }) => {
|
||||||
|
const { management, loading } = useManagementData(stockCode);
|
||||||
|
|
||||||
|
// 使用 useMemo 缓存分类计算结果
|
||||||
|
const categorizedManagement = useMemo(
|
||||||
|
() => categorizeManagement(management as ManagementPerson[]),
|
||||||
|
[management]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <LoadingState message="加载管理团队数据..." />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<VStack spacing={6} align="stretch">
|
||||||
|
{CATEGORY_ORDER.map((category) => {
|
||||||
|
const config = CATEGORY_CONFIG[category];
|
||||||
|
const people = categorizedManagement[category];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CategorySection
|
||||||
|
key={category}
|
||||||
|
category={category}
|
||||||
|
people={people}
|
||||||
|
icon={config.icon}
|
||||||
|
color={config.color}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</VStack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ManagementPanel;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// src/views/Company/components/CompanyOverview/BasicInfoTab/components/management/index.ts
|
||||||
|
// 管理团队组件导出
|
||||||
|
|
||||||
|
export { default as ManagementPanel } from "./ManagementPanel";
|
||||||
|
export { default as ManagementCard } from "./ManagementCard";
|
||||||
|
export { default as CategorySection } from "./CategorySection";
|
||||||
|
export * from "./types";
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// src/views/Company/components/CompanyOverview/BasicInfoTab/components/management/types.ts
|
||||||
|
// 管理团队相关类型定义
|
||||||
|
|
||||||
|
import type { IconType } from "react-icons";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理人员信息
|
||||||
|
*/
|
||||||
|
export interface ManagementPerson {
|
||||||
|
name: string;
|
||||||
|
position_name?: string;
|
||||||
|
position_category?: string;
|
||||||
|
gender?: "男" | "女";
|
||||||
|
education?: string;
|
||||||
|
birth_year?: string;
|
||||||
|
nationality?: string;
|
||||||
|
start_date?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理层分类
|
||||||
|
*/
|
||||||
|
export type ManagementCategory = "高管" | "董事" | "监事" | "其他";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类后的管理层数据
|
||||||
|
*/
|
||||||
|
export type CategorizedManagement = Record<ManagementCategory, ManagementPerson[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类配置项
|
||||||
|
*/
|
||||||
|
export interface CategoryConfig {
|
||||||
|
icon: IconType;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user