diff --git a/src/views/Company/components/CompanyOverview/index.js b/src/views/Company/components/CompanyOverview/index.js
index a5e3739f..dc765678 100644
--- a/src/views/Company/components/CompanyOverview/index.js
+++ b/src/views/Company/components/CompanyOverview/index.js
@@ -1,5 +1,5 @@
// src/views/Company/components/CompanyOverview/index.js
-// 公司概览主组件 - 状态管理 + Tab 容器
+// 公司概览 - 头部卡片 + 基本信息
import React, { useState, useEffect } from "react";
import {
@@ -15,19 +15,12 @@ import {
Divider,
Spinner,
Center,
- Tabs,
- TabList,
- TabPanels,
- Tab,
- TabPanel,
- useColorModeValue,
Icon,
Grid,
GridItem,
Stat,
StatLabel,
StatNumber,
- Container,
Circle,
Link,
} from "@chakra-ui/react";
@@ -42,9 +35,6 @@ import {
FaEnvelope,
FaPhone,
FaCrown,
- FaBrain,
- FaInfoCircle,
- FaNewspaper,
} from "react-icons/fa";
import { ExternalLinkIcon } from "@chakra-ui/icons";
@@ -53,9 +43,7 @@ import { logger } from "@utils/logger";
import { getApiBase } from "@utils/apiConfig";
// 子组件
-import DeepAnalysisTab from "./DeepAnalysisTab";
import BasicInfoTab from "./BasicInfoTab";
-import NewsEventsTab from "./NewsEventsTab";
// API配置
const API_BASE_URL = getApiBase();
@@ -76,87 +64,47 @@ const formatUtils = {
},
};
-// 主组件
-const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => {
+/**
+ * 公司概览组件
+ *
+ * 功能:
+ * - 显示公司头部信息卡片
+ * - 显示基本信息(股权结构、管理层、公告等)
+ *
+ * @param {Object} props
+ * @param {string} props.stockCode - 股票代码
+ */
+const CompanyOverview = ({ stockCode: propStockCode }) => {
const [stockCode, setStockCode] = useState(propStockCode || "000001");
+ const [loading, setLoading] = useState(false);
+ const [dataLoaded, setDataLoaded] = useState(false);
- // Tab 懒加载状态追踪
- const [tabsLoaded, setTabsLoaded] = useState({
- basicInfo: false,
- deepAnalysis: false,
- newsEvents: false,
- });
- const [activeTabIndex, setActiveTabIndex] = useState(0);
- const [basicInfoLoading, setBasicInfoLoading] = useState(false);
- const [deepAnalysisLoading, setDeepAnalysisLoading] = useState(false);
-
- // 监听props中的stockCode变化 - 重置Tab状态
+ // 监听 props 中的 stockCode 变化
useEffect(() => {
if (propStockCode && propStockCode !== stockCode) {
setStockCode(propStockCode);
- // 重置 Tab 状态
- setTabsLoaded({ basicInfo: false, deepAnalysis: false, newsEvents: false });
- setActiveTabIndex(0);
- // 清空深度分析和新闻数据
- setComprehensiveData(null);
- setValueChainData(null);
- setKeyFactorsData(null);
- setNewsEvents([]);
+ setDataLoaded(false);
}
}, [propStockCode, stockCode]);
- // 企业深度分析数据
- const [comprehensiveData, setComprehensiveData] = useState(null);
- const [valueChainData, setValueChainData] = useState(null);
- const [keyFactorsData, setKeyFactorsData] = useState(null);
-
- // 股票概览数据
+ // 基本信息数据
const [basicInfo, setBasicInfo] = useState(null);
const [actualControl, setActualControl] = useState([]);
const [concentration, setConcentration] = useState([]);
const [management, setManagement] = useState([]);
- const [topCirculationShareholders, setTopCirculationShareholders] = useState(
- []
- );
+ const [topCirculationShareholders, setTopCirculationShareholders] = useState([]);
const [topShareholders, setTopShareholders] = useState([]);
const [branches, setBranches] = useState([]);
const [announcements, setAnnouncements] = useState([]);
const [disclosureSchedule, setDisclosureSchedule] = useState([]);
- // 新闻动态数据
- const [newsEvents, setNewsEvents] = useState([]);
- const [newsLoading, setNewsLoading] = useState(false);
- const [newsSearchQuery, setNewsSearchQuery] = useState("");
- const [newsPagination, setNewsPagination] = useState({
- page: 1,
- per_page: 10,
- total: 0,
- pages: 0,
- has_next: false,
- has_prev: false,
- });
-
const [_error, setError] = useState(null);
- const bgColor = useColorModeValue("gray.50", "gray.900");
- const cardBg = useColorModeValue("white", "gray.800");
-
- // 业务板块详情展开状态
- const [expandedSegments, setExpandedSegments] = useState({});
-
- // 切换业务板块展开状态
- const toggleSegmentExpansion = (segmentIndex) => {
- setExpandedSegments((prev) => ({
- ...prev,
- [segmentIndex]: !prev[segmentIndex],
- }));
- };
-
- // 加载基本信息数据(9个接口)- 首次加载
+ // 加载基本信息数据(9个接口)
const loadBasicInfoData = async () => {
- if (tabsLoaded.basicInfo) return;
+ if (dataLoaded) return;
- setBasicInfoLoading(true);
+ setLoading(true);
setError(null);
try {
@@ -202,7 +150,6 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => {
disclosureRes,
] = await Promise.all(requests);
- // 设置股票概览数据
if (basicRes.success) setBasicInfo(basicRes.data);
if (actualRes.success) setActualControl(actualRes.data);
if (concentrationRes.success) setConcentration(concentrationRes.data);
@@ -214,388 +161,169 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => {
if (announcementsRes.success) setAnnouncements(announcementsRes.data);
if (disclosureRes.success) setDisclosureSchedule(disclosureRes.data);
- setTabsLoaded((prev) => ({ ...prev, basicInfo: true }));
+ setDataLoaded(true);
} catch (err) {
setError(err.message);
logger.error("CompanyOverview", "loadBasicInfoData", err, { stockCode });
} finally {
- setBasicInfoLoading(false);
+ setLoading(false);
}
};
- // 加载深度分析数据(3个接口)- Tab切换时加载
- const loadDeepAnalysisData = async () => {
- if (tabsLoaded.deepAnalysis) return;
-
- setDeepAnalysisLoading(true);
-
- try {
- const requests = [
- fetch(
- `${API_BASE_URL}/api/company/comprehensive-analysis/${stockCode}`
- ).then((r) => r.json()),
- fetch(
- `${API_BASE_URL}/api/company/value-chain-analysis/${stockCode}`
- ).then((r) => r.json()),
- fetch(
- `${API_BASE_URL}/api/company/key-factors-timeline/${stockCode}`
- ).then((r) => r.json()),
- ];
-
- const [comprehensiveRes, valueChainRes, keyFactorsRes] =
- await Promise.all(requests);
-
- // 设置深度分析数据
- if (comprehensiveRes.success) setComprehensiveData(comprehensiveRes.data);
- if (valueChainRes.success) setValueChainData(valueChainRes.data);
- if (keyFactorsRes.success) setKeyFactorsData(keyFactorsRes.data);
-
- setTabsLoaded((prev) => ({ ...prev, deepAnalysis: true }));
- } catch (err) {
- logger.error("CompanyOverview", "loadDeepAnalysisData", err, {
- stockCode,
- });
- } finally {
- setDeepAnalysisLoading(false);
- }
- };
-
- // 首次加载 - 只加载基本信息
+ // 首次加载
useEffect(() => {
if (stockCode) {
loadBasicInfoData();
}
}, [stockCode]);
- // 加载新闻事件(1个接口)- Tab切换时加载
- const loadNewsEvents = async (page = 1, searchQuery = "") => {
- setNewsLoading(true);
- try {
- const params = new URLSearchParams({
- page: page.toString(),
- per_page: "10",
- sort: "new",
- include_creator: "true",
- include_stats: "true",
- });
-
- const queryText = searchQuery || basicInfo?.SECNAME || "";
- if (queryText) {
- params.append("q", queryText);
- }
-
- const response = await fetch(
- `${API_BASE_URL}/api/events?${params.toString()}`
- );
- const data = await response.json();
-
- const events = data.data?.events || data.events || [];
- const pagination = data.data?.pagination || {
- page: 1,
- per_page: 10,
- total: 0,
- pages: 0,
- has_next: false,
- has_prev: false,
- };
-
- setNewsEvents(events);
- setNewsPagination(pagination);
-
- // 首次加载时标记为已加载
- if (page === 1 && !tabsLoaded.newsEvents) {
- setTabsLoaded((prev) => ({ ...prev, newsEvents: true }));
- }
- } catch (err) {
- logger.error("CompanyOverview", "loadNewsEvents", err, {
- stockCode,
- searchQuery,
- page,
- });
- setNewsEvents([]);
- setNewsPagination({
- page: 1,
- per_page: 10,
- total: 0,
- pages: 0,
- has_next: false,
- has_prev: false,
- });
- } finally {
- setNewsLoading(false);
- }
- };
-
- // 处理新闻搜索
- const handleNewsSearch = () => {
- loadNewsEvents(1, newsSearchQuery);
- };
-
- // 处理新闻分页
- const handleNewsPageChange = (newPage) => {
- loadNewsEvents(newPage, newsSearchQuery);
- };
-
- // Tab 切换处理 - 懒加载
- const handleTabChange = (index) => {
- setActiveTabIndex(index);
- // index 0: 基本信息 - 已首次加载
- // index 1: 深度分析 - 切换时加载
- // index 2: 新闻动态 - 切换时加载
- if (index === 1 && !tabsLoaded.deepAnalysis) {
- loadDeepAnalysisData();
- } else if (index === 2 && !tabsLoaded.newsEvents && basicInfo) {
- loadNewsEvents(1);
- }
- };
-
- if (basicInfoLoading && !basicInfo) {
+ if (loading && !basicInfo) {
return (
-