// src/views/Company/components/DeepAnalysis/index.js // 深度分析 - 独立一级 Tab 组件(懒加载版本) import React, { useState, useEffect, useCallback, useRef } from "react"; import { logger } from "@utils/logger"; import { getApiBase } from "@utils/apiConfig"; // 复用原有的展示组件 import DeepAnalysisTab from "../CompanyOverview/DeepAnalysisTab"; const API_BASE_URL = getApiBase(); /** * Tab 与 API 接口映射 * - strategy 和 business 共用 comprehensive 接口 */ const TAB_API_MAP = { strategy: "comprehensive", business: "comprehensive", valueChain: "valueChain", development: "keyFactors", }; /** * 深度分析组件 * * 功能: * - 按 Tab 懒加载数据(默认只加载战略分析) * - 已加载的数据缓存,切换 Tab 不重复请求 * - 管理展开状态 * * @param {Object} props * @param {string} props.stockCode - 股票代码 */ const DeepAnalysis = ({ stockCode }) => { // 当前 Tab const [activeTab, setActiveTab] = useState("strategy"); // 数据状态 const [comprehensiveData, setComprehensiveData] = useState(null); const [valueChainData, setValueChainData] = useState(null); const [keyFactorsData, setKeyFactorsData] = useState(null); const [industryRankData, setIndustryRankData] = useState(null); // 各接口独立的 loading 状态 const [comprehensiveLoading, setComprehensiveLoading] = useState(false); const [valueChainLoading, setValueChainLoading] = useState(false); const [keyFactorsLoading, setKeyFactorsLoading] = useState(false); const [industryRankLoading, setIndustryRankLoading] = useState(false); // 已加载的接口记录(用于缓存判断) const loadedApisRef = useRef({ comprehensive: false, valueChain: false, keyFactors: false, industryRank: false, }); // 业务板块展开状态 const [expandedSegments, setExpandedSegments] = useState({}); // 用于追踪当前 stockCode,避免竞态条件 const currentStockCodeRef = useRef(stockCode); // 切换业务板块展开状态 const toggleSegmentExpansion = (segmentIndex) => { setExpandedSegments((prev) => ({ ...prev, [segmentIndex]: !prev[segmentIndex], })); }; /** * 加载指定接口的数据 */ const loadApiData = useCallback( async (apiKey) => { if (!stockCode) return; // 已加载则跳过 if (loadedApisRef.current[apiKey]) return; try { switch (apiKey) { case "comprehensive": setComprehensiveLoading(true); const comprehensiveRes = await fetch( `${API_BASE_URL}/api/company/comprehensive-analysis/${stockCode}` ).then((r) => r.json()); // 检查 stockCode 是否已变更(防止竞态) if (currentStockCodeRef.current === stockCode) { if (comprehensiveRes.success) setComprehensiveData(comprehensiveRes.data); loadedApisRef.current.comprehensive = true; } break; case "valueChain": setValueChainLoading(true); const valueChainRes = await fetch( `${API_BASE_URL}/api/company/value-chain-analysis/${stockCode}` ).then((r) => r.json()); if (currentStockCodeRef.current === stockCode) { if (valueChainRes.success) setValueChainData(valueChainRes.data); loadedApisRef.current.valueChain = true; } break; case "keyFactors": setKeyFactorsLoading(true); const keyFactorsRes = await fetch( `${API_BASE_URL}/api/company/key-factors-timeline/${stockCode}` ).then((r) => r.json()); if (currentStockCodeRef.current === stockCode) { if (keyFactorsRes.success) setKeyFactorsData(keyFactorsRes.data); loadedApisRef.current.keyFactors = true; } break; case "industryRank": setIndustryRankLoading(true); const industryRankRes = await fetch( `${API_BASE_URL}/api/financial/industry-rank/${stockCode}` ).then((r) => r.json()); if (currentStockCodeRef.current === stockCode) { if (industryRankRes.success) setIndustryRankData(industryRankRes.data); loadedApisRef.current.industryRank = true; } break; default: break; } } catch (err) { logger.error("DeepAnalysis", `loadApiData:${apiKey}`, err, { stockCode, }); } finally { // 清除 loading 状态 if (apiKey === "comprehensive") setComprehensiveLoading(false); if (apiKey === "valueChain") setValueChainLoading(false); if (apiKey === "keyFactors") setKeyFactorsLoading(false); if (apiKey === "industryRank") setIndustryRankLoading(false); } }, [stockCode] ); /** * 根据 Tab 加载对应的数据 */ const loadTabData = useCallback( (tabKey) => { const apiKey = TAB_API_MAP[tabKey]; if (apiKey) { loadApiData(apiKey); } }, [loadApiData] ); /** * Tab 切换回调 */ const handleTabChange = useCallback( (index, tabKey) => { setActiveTab(tabKey); loadTabData(tabKey); }, [loadTabData] ); // stockCode 变更时重置并加载默认 Tab 数据 useEffect(() => { if (stockCode) { // 更新 ref currentStockCodeRef.current = stockCode; // 重置所有数据和状态 setComprehensiveData(null); setValueChainData(null); setKeyFactorsData(null); setIndustryRankData(null); setExpandedSegments({}); loadedApisRef.current = { comprehensive: false, valueChain: false, keyFactors: false, industryRank: false, }; // 重置为默认 Tab 并加载数据 setActiveTab("strategy"); // 加载默认 Tab 的数据(战略分析需要 comprehensive 和 industryRank) loadApiData("comprehensive"); loadApiData("industryRank"); } }, [stockCode, loadApiData]); // 计算当前 Tab 的 loading 状态 const getCurrentLoading = () => { const apiKey = TAB_API_MAP[activeTab]; switch (apiKey) { case "comprehensive": return comprehensiveLoading; case "valueChain": return valueChainLoading; case "keyFactors": return keyFactorsLoading; default: return false; } }; return ( ); }; export default DeepAnalysis;