refactor: CompanyOverview 组件 TypeScript 拆分
- 新增 index.tsx: 主组件(组合层,50 行) - 新增 CompanyHeaderCard.tsx: 头部卡片组件(168 行) - 新增 hooks/useCompanyOverviewData.ts: 数据加载 Hook - 删除 index.js: 原 330 行代码精简 85% - 修复 Company/index.js: 恢复 CompanyTabs 渲染 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
// src/views/Company/components/CompanyOverview/hooks/useCompanyOverviewData.ts
|
||||
// 公司概览数据加载 Hook
|
||||
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { logger } from "@utils/logger";
|
||||
import { getApiBase } from "@utils/apiConfig";
|
||||
import type {
|
||||
BasicInfo,
|
||||
ActualControl,
|
||||
Concentration,
|
||||
Management,
|
||||
Shareholder,
|
||||
Branch,
|
||||
Announcement,
|
||||
DisclosureSchedule,
|
||||
CompanyOverviewData,
|
||||
} from "../types";
|
||||
|
||||
const API_BASE_URL = getApiBase();
|
||||
|
||||
interface ApiResponse<T> {
|
||||
success: boolean;
|
||||
data: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公司概览数据加载 Hook
|
||||
* @param propStockCode - 股票代码
|
||||
* @returns 公司概览数据
|
||||
*/
|
||||
export const useCompanyOverviewData = (propStockCode?: string): CompanyOverviewData => {
|
||||
const [stockCode, setStockCode] = useState(propStockCode || "000001");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [dataLoaded, setDataLoaded] = useState(false);
|
||||
|
||||
// 基本信息数据
|
||||
const [basicInfo, setBasicInfo] = useState<BasicInfo | null>(null);
|
||||
const [actualControl, setActualControl] = useState<ActualControl[]>([]);
|
||||
const [concentration, setConcentration] = useState<Concentration[]>([]);
|
||||
const [management, setManagement] = useState<Management[]>([]);
|
||||
const [topCirculationShareholders, setTopCirculationShareholders] = useState<Shareholder[]>([]);
|
||||
const [topShareholders, setTopShareholders] = useState<Shareholder[]>([]);
|
||||
const [branches, setBranches] = useState<Branch[]>([]);
|
||||
const [announcements, setAnnouncements] = useState<Announcement[]>([]);
|
||||
const [disclosureSchedule, setDisclosureSchedule] = useState<DisclosureSchedule[]>([]);
|
||||
|
||||
// 监听 props 中的 stockCode 变化
|
||||
useEffect(() => {
|
||||
if (propStockCode && propStockCode !== stockCode) {
|
||||
setStockCode(propStockCode);
|
||||
setDataLoaded(false);
|
||||
}
|
||||
}, [propStockCode, stockCode]);
|
||||
|
||||
// 加载基本信息数据(9个接口)
|
||||
const loadBasicInfoData = useCallback(async () => {
|
||||
if (dataLoaded) return;
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const [
|
||||
basicRes,
|
||||
actualRes,
|
||||
concentrationRes,
|
||||
managementRes,
|
||||
circulationRes,
|
||||
shareholdersRes,
|
||||
branchesRes,
|
||||
announcementsRes,
|
||||
disclosureRes,
|
||||
] = await Promise.all([
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/basic-info`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<BasicInfo>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/actual-control`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<ActualControl[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/concentration`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<Concentration[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/management?active_only=true`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<Management[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/top-circulation-shareholders?limit=10`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<Shareholder[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/top-shareholders?limit=10`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<Shareholder[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/branches`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<Branch[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/announcements?limit=20`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<Announcement[]>>,
|
||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/disclosure-schedule`).then((r) =>
|
||||
r.json()
|
||||
) as Promise<ApiResponse<DisclosureSchedule[]>>,
|
||||
]);
|
||||
|
||||
if (basicRes.success) setBasicInfo(basicRes.data);
|
||||
if (actualRes.success) setActualControl(actualRes.data);
|
||||
if (concentrationRes.success) setConcentration(concentrationRes.data);
|
||||
if (managementRes.success) setManagement(managementRes.data);
|
||||
if (circulationRes.success) setTopCirculationShareholders(circulationRes.data);
|
||||
if (shareholdersRes.success) setTopShareholders(shareholdersRes.data);
|
||||
if (branchesRes.success) setBranches(branchesRes.data);
|
||||
if (announcementsRes.success) setAnnouncements(announcementsRes.data);
|
||||
if (disclosureRes.success) setDisclosureSchedule(disclosureRes.data);
|
||||
|
||||
setDataLoaded(true);
|
||||
} catch (err) {
|
||||
logger.error("useCompanyOverviewData", "loadBasicInfoData", err, { stockCode });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [stockCode, dataLoaded]);
|
||||
|
||||
// 首次加载
|
||||
useEffect(() => {
|
||||
if (stockCode) {
|
||||
loadBasicInfoData();
|
||||
}
|
||||
}, [stockCode, loadBasicInfoData]);
|
||||
|
||||
return {
|
||||
basicInfo,
|
||||
actualControl,
|
||||
concentration,
|
||||
management,
|
||||
topCirculationShareholders,
|
||||
topShareholders,
|
||||
branches,
|
||||
announcements,
|
||||
disclosureSchedule,
|
||||
loading,
|
||||
dataLoaded,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user