diff --git a/src/views/Company/components/CompanyOverview/BasicInfoTab.js b/src/views/Company/components/CompanyOverview/BasicInfoTab.js index 2545c029..cbf2d82b 100644 --- a/src/views/Company/components/CompanyOverview/BasicInfoTab.js +++ b/src/views/Company/components/CompanyOverview/BasicInfoTab.js @@ -155,6 +155,7 @@ const BasicInfoTab = ({ branches = [], disclosureSchedule = [], cardBg, + loading = false, }) => { const { isOpen, onOpen, onClose } = useDisclosure(); const [selectedAnnouncement, setSelectedAnnouncement] = React.useState(null); diff --git a/src/views/Company/components/CompanyOverview/index.js b/src/views/Company/components/CompanyOverview/index.js index 7929a8bc..a5e3739f 100644 --- a/src/views/Company/components/CompanyOverview/index.js +++ b/src/views/Company/components/CompanyOverview/index.js @@ -79,12 +79,29 @@ const formatUtils = { // 主组件 const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { const [stockCode, setStockCode] = useState(propStockCode || "000001"); - const [loading, setLoading] = useState(false); - // 监听props中的stockCode变化 + // 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状态 useEffect(() => { if (propStockCode && propStockCode !== stockCode) { setStockCode(propStockCode); + // 重置 Tab 状态 + setTabsLoaded({ basicInfo: false, deepAnalysis: false, newsEvents: false }); + setActiveTabIndex(0); + // 清空深度分析和新闻数据 + setComprehensiveData(null); + setValueChainData(null); + setKeyFactorsData(null); + setNewsEvents([]); } }, [propStockCode, stockCode]); @@ -135,24 +152,15 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { })); }; - // 加载数据 - const loadData = async () => { - setLoading(true); + // 加载基本信息数据(9个接口)- 首次加载 + const loadBasicInfoData = async () => { + if (tabsLoaded.basicInfo) return; + + setBasicInfoLoading(true); setError(null); 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()), - // 股票概览数据 fetch(`${API_BASE_URL}/api/stock/${stockCode}/basic-info`).then((r) => r.json() ), @@ -183,9 +191,6 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { ]; const [ - comprehensiveRes, - valueChainRes, - keyFactorsRes, basicRes, actualRes, concentrationRes, @@ -197,11 +202,6 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { disclosureRes, ] = await Promise.all(requests); - // 设置深度分析数据 - if (comprehensiveRes.success) setComprehensiveData(comprehensiveRes.data); - if (valueChainRes.success) setValueChainData(valueChainRes.data); - if (keyFactorsRes.success) setKeyFactorsData(keyFactorsRes.data); - // 设置股票概览数据 if (basicRes.success) setBasicInfo(basicRes.data); if (actualRes.success) setActualControl(actualRes.data); @@ -213,21 +213,61 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { if (branchesRes.success) setBranches(branchesRes.data); if (announcementsRes.success) setAnnouncements(announcementsRes.data); if (disclosureRes.success) setDisclosureSchedule(disclosureRes.data); + + setTabsLoaded((prev) => ({ ...prev, basicInfo: true })); } catch (err) { setError(err.message); - logger.error("CompanyOverview", "loadData", err, { stockCode }); + logger.error("CompanyOverview", "loadBasicInfoData", err, { stockCode }); } finally { - setLoading(false); + setBasicInfoLoading(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) { - loadData(); + loadBasicInfoData(); } }, [stockCode]); - // 加载新闻事件 + // 加载新闻事件(1个接口)- Tab切换时加载 const loadNewsEvents = async (page = 1, searchQuery = "") => { setNewsLoading(true); try { @@ -261,6 +301,11 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { setNewsEvents(events); setNewsPagination(pagination); + + // 首次加载时标记为已加载 + if (page === 1 && !tabsLoaded.newsEvents) { + setTabsLoaded((prev) => ({ ...prev, newsEvents: true })); + } } catch (err) { logger.error("CompanyOverview", "loadNewsEvents", err, { stockCode, @@ -281,13 +326,6 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { } }; - // 当基本信息加载完成后,加载新闻事件 - useEffect(() => { - if (basicInfo) { - loadNewsEvents(1); - } - }, [basicInfo]); - // 处理新闻搜索 const handleNewsSearch = () => { loadNewsEvents(1, newsSearchQuery); @@ -298,7 +336,20 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { loadNewsEvents(newPage, newsSearchQuery); }; - if (loading) { + // 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) { return ( @@ -466,12 +517,13 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { )} - {/* 主要内容区 - 分为深度分析、基本信息和新闻动态 */} + {/* 主要内容区 - 分为基本信息、深度分析和新闻动态 */} { shadow="md" flexWrap="wrap" > - - - 深度分析 - 基本信息 + + + 深度分析 + 新闻动态 @@ -495,20 +547,7 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { - {/* 深度分析标签页 */} - - - - - {/* 基本信息标签页 */} + {/* 基本信息标签页 - 默认 Tab */} { branches={branches} disclosureSchedule={disclosureSchedule} cardBg={cardBg} + loading={basicInfoLoading} /> - {/* 新闻动态标签页 */} + {/* 深度分析标签页 - 切换时加载 */} + + + + + {/* 新闻动态标签页 - 切换时加载 */}