/** * 公司详情页面 - FUI 科幻风格 * * 特性: * - Ash Thorp 风格 FUI 设计 * - James Turrell 光影效果 * - Glassmorphism 毛玻璃卡片 * - Linear.app 风格微交互 * - HeroUI 现代组件风格 */ import React, { memo, useCallback, useRef, useEffect } from 'react'; // FUI 动画样式 import './theme/fui-animations.css'; import { useSearchParams } from 'react-router-dom'; import { Box } from '@chakra-ui/react'; import SubTabContainer from '@components/SubTabContainer'; import { useCompanyEvents } from './hooks/useCompanyEvents'; import { useCompanyData } from './hooks/useCompanyData'; import CompanyHeader from './components/CompanyHeader'; import StockQuoteCard from './components/StockQuoteCard'; import { THEME, TAB_CONFIG } from './config'; // ============================================ // 主内容区组件 - FUI 风格 // ============================================ interface CompanyContentProps { stockCode: string; isInWatchlist: boolean; watchlistLoading: boolean; onWatchlistToggle: () => void; onTabChange: (index: number, tabKey: string) => void; } const CompanyContent = memo(({ stockCode, isInWatchlist, watchlistLoading, onWatchlistToggle, onTabChange, }) => ( {/* 股票行情卡片 - 放在 Tab 切换器上方,始终可见 */} {/* Tab 内容区 */} {/* 角落装饰 - FUI 风格 */} )); CompanyContent.displayName = 'CompanyContent'; // ============================================ // 网页标题 Hook // ============================================ const useDocumentTitle = (stockCode: string, stockName?: string) => { useEffect(() => { const baseTitle = '价值前沿'; if (stockName) { document.title = `${stockName}(${stockCode}) - ${baseTitle}`; } else if (stockCode) { document.title = `${stockCode} - ${baseTitle}`; } else { document.title = baseTitle; } // 组件卸载时恢复默认标题 return () => { document.title = baseTitle; }; }, [stockCode, stockName]); }; // ============================================ // 主页面组件 // ============================================ const CompanyIndex: React.FC = () => { // URL 参数管理 const [searchParams, setSearchParams] = useSearchParams(); const stockCode = searchParams.get('scode') || '000001'; const prevStockCodeRef = useRef(stockCode); // 数据加载 Hook const { stockInfo, stockInfoLoading, isInWatchlist, watchlistLoading, toggleWatchlist, } = useCompanyData({ stockCode }); // 事件追踪 Hook const companyEvents = useCompanyEvents({ stockCode }) as { trackStockSearched: (newCode: string, oldCode: string | null) => void; trackTabChanged: (index: number, name: string, prevIndex: number) => void; trackWatchlistAdded: (code: string) => void; trackWatchlistRemoved: (code: string) => void; }; const { trackStockSearched, trackTabChanged, trackWatchlistAdded, trackWatchlistRemoved } = companyEvents; // 设置网页标题 useDocumentTitle(stockCode, stockInfo?.stock_name); // 股票代码变化追踪 useEffect(() => { if (stockCode !== prevStockCodeRef.current) { trackStockSearched(stockCode, prevStockCodeRef.current); prevStockCodeRef.current = stockCode; } }, [stockCode, trackStockSearched]); // 处理股票切换 const handleStockChange = useCallback((newCode: string) => { if (newCode && newCode !== stockCode) { trackStockSearched(newCode, stockCode); setSearchParams({ scode: newCode }); } }, [stockCode, setSearchParams, trackStockSearched]); // 处理自选股切换(带追踪) const handleWatchlistToggle = useCallback(async () => { const wasInWatchlist = isInWatchlist; await toggleWatchlist(); // 追踪事件(根据操作前的状态判断) if (wasInWatchlist) { trackWatchlistRemoved(stockCode); } else { trackWatchlistAdded(stockCode); } }, [stockCode, isInWatchlist, toggleWatchlist, trackWatchlistAdded, trackWatchlistRemoved]); // 处理 Tab 切换 const handleTabChange = useCallback((index: number, tabKey: string) => { const tabName = TAB_CONFIG[index]?.name || tabKey; trackTabChanged(index, tabName, index); }, [trackTabChanged]); return ( {/* 全局环境光效果 - James Turrell 风格 */} {/* 顶部搜索栏 */} {/* 主内容区 */} ); }; export default memo(CompanyIndex);