/** * InvestmentPlanningCenter - 投资规划中心主组件 (TypeScript 重构版) * * 性能优化: * - 使用 React.lazy() 懒加载子面板,减少初始加载时间 * - 从 1421 行拆分为 5 个独立模块,提升可维护性 * - 使用 TypeScript 提供类型安全 * * 组件架构: * - InvestmentPlanningCenter (主组件,~200 行) * - CalendarPanel (日历面板,懒加载) * - PlansPanel (计划面板,懒加载) * - ReviewsPanel (复盘面板,懒加载) * - PlanningContext (数据共享层) */ import React, { useState, useEffect, useCallback, Suspense, lazy } from 'react'; import { Box, Card, CardHeader, CardBody, Heading, HStack, Flex, Icon, useColorModeValue, useToast, Tabs, TabList, TabPanels, Tab, TabPanel, Spinner, Center, } from '@chakra-ui/react'; import { FiCalendar, FiTarget, FiFileText, } from 'react-icons/fi'; import { PlanningDataProvider } from './PlanningContext'; import type { InvestmentEvent, PlanningContextValue } from '@/types'; import { logger } from '@/utils/logger'; import { getApiBase } from '@/utils/apiConfig'; import './InvestmentCalendar.css'; // 懒加载子面板组件(实现代码分割) const CalendarPanel = lazy(() => import('./CalendarPanel').then(module => ({ default: module.CalendarPanel })) ); const PlansPanel = lazy(() => import('./PlansPanel').then(module => ({ default: module.PlansPanel })) ); const ReviewsPanel = lazy(() => import('./ReviewsPanel').then(module => ({ default: module.ReviewsPanel })) ); /** * 面板加载占位符 */ const PanelLoadingFallback: React.FC = () => (
); /** * InvestmentPlanningCenter 主组件 */ const InvestmentPlanningCenter: React.FC = () => { const toast = useToast(); // 颜色主题 const bgColor = useColorModeValue('white', 'gray.800'); const borderColor = useColorModeValue('gray.200', 'gray.600'); const textColor = useColorModeValue('gray.700', 'white'); const secondaryText = useColorModeValue('gray.600', 'gray.400'); const cardBg = useColorModeValue('gray.50', 'gray.700'); // 全局数据状态 const [allEvents, setAllEvents] = useState([]); const [loading, setLoading] = useState(false); const [activeTab, setActiveTab] = useState(0); /** * 加载所有事件数据(日历事件 + 计划 + 复盘) */ const loadAllData = useCallback(async (): Promise => { try { setLoading(true); const base = getApiBase(); const response = await fetch(base + '/api/account/calendar/events', { credentials: 'include' }); if (response.ok) { const data = await response.json(); if (data.success) { setAllEvents(data.data || []); logger.debug('InvestmentPlanningCenter', '数据加载成功', { count: data.data?.length || 0 }); } } } catch (error) { logger.error('InvestmentPlanningCenter', 'loadAllData', error); } finally { setLoading(false); } }, []); // 组件挂载时加载数据 useEffect(() => { loadAllData(); }, [loadAllData]); // 提供给子组件的 Context 值 const contextValue: PlanningContextValue = { allEvents, setAllEvents, loadAllData, loading, setLoading, activeTab, setActiveTab, toast, bgColor, borderColor, textColor, secondaryText, cardBg, }; // 计算各类型事件数量 const planCount = allEvents.filter(e => e.type === 'plan').length; const reviewCount = allEvents.filter(e => e.type === 'review').length; return ( 投资规划中心 日历视图 我的计划 ({planCount}) 我的复盘 ({reviewCount}) {/* 日历视图面板 */} }> {/* 计划列表面板 */} }> {/* 复盘列表面板 */} }> ); }; export default InvestmentPlanningCenter;