diff --git a/src/views/Company/components/DynamicTracking/components/DynamicTrackingSkeleton.tsx b/src/views/Company/components/DynamicTracking/components/DynamicTrackingSkeleton.tsx new file mode 100644 index 00000000..335b0bba --- /dev/null +++ b/src/views/Company/components/DynamicTracking/components/DynamicTrackingSkeleton.tsx @@ -0,0 +1,101 @@ +/** + * 动态跟踪 Tab 骨架屏组件 + * 用于懒加载时显示,提供即时反馈 + */ + +import React from 'react'; +import { Box, VStack, HStack, Skeleton, SkeletonText, Card, CardBody } from '@chakra-ui/react'; + +/** + * 新闻动态骨架屏 + */ +export const NewsPanelSkeleton: React.FC = () => ( + + {[1, 2, 3, 4, 5].map((i) => ( + + + + + + + + + + + + ))} + +); + +/** + * 公告列表骨架屏 + */ +export const AnnouncementsSkeleton: React.FC = () => ( + + {[1, 2, 3, 4].map((i) => ( + + + + + + + + + + + + ))} + +); + +/** + * 财报披露日程骨架屏 + */ +export const DisclosureScheduleSkeleton: React.FC = () => ( + + + + {[1, 2, 3].map((i) => ( + + + + + ))} + + +); + +/** + * 业绩预告骨架屏 + */ +export const ForecastPanelSkeleton: React.FC = () => ( + + + + + + + + + + + + +); + +/** + * 通用内容骨架屏(默认 fallback) + */ +export const ContentSkeleton: React.FC = () => ( + + + +); + +export default { + NewsPanelSkeleton, + AnnouncementsSkeleton, + DisclosureScheduleSkeleton, + ForecastPanelSkeleton, + ContentSkeleton, +}; diff --git a/src/views/Company/components/DynamicTracking/components/index.js b/src/views/Company/components/DynamicTracking/components/index.js index 44bc24a1..5c37b1bd 100644 --- a/src/views/Company/components/DynamicTracking/components/index.js +++ b/src/views/Company/components/DynamicTracking/components/index.js @@ -2,3 +2,12 @@ export { default as NewsPanel } from './NewsPanel'; export { default as ForecastPanel } from './ForecastPanel'; + +// 骨架屏组件 +export { + NewsPanelSkeleton, + AnnouncementsSkeleton, + DisclosureScheduleSkeleton, + ForecastPanelSkeleton, + ContentSkeleton, +} from './DynamicTrackingSkeleton'; diff --git a/src/views/Company/components/DynamicTracking/index.js b/src/views/Company/components/DynamicTracking/index.js index 71b14540..3110220a 100644 --- a/src/views/Company/components/DynamicTracking/index.js +++ b/src/views/Company/components/DynamicTracking/index.js @@ -1,37 +1,73 @@ // src/views/Company/components/DynamicTracking/index.js // 动态跟踪 - 独立一级 Tab 组件(包含新闻动态等二级 Tab) +// 优化:子组件懒加载,骨架屏即时反馈 -import React, { useState, useEffect, useMemo } from 'react'; +import React, { useState, useEffect, useMemo, useCallback, memo, lazy } from 'react'; import { Box } from '@chakra-ui/react'; import { FaNewspaper, FaBullhorn, FaCalendarAlt, FaChartBar } from 'react-icons/fa'; import SubTabContainer from '@components/SubTabContainer'; -import AnnouncementsPanel from '../CompanyOverview/BasicInfoTab/components/AnnouncementsPanel'; -import DisclosureSchedulePanel from '../CompanyOverview/BasicInfoTab/components/DisclosureSchedulePanel'; -import { NewsPanel, ForecastPanel } from './components'; +import { + NewsPanelSkeleton, + AnnouncementsSkeleton, + DisclosureScheduleSkeleton, + ForecastPanelSkeleton, +} from './components/DynamicTrackingSkeleton'; -// 二级 Tab 配置 +// 懒加载子组件 +const NewsPanel = lazy(() => import('./components/NewsPanel')); +const ForecastPanel = lazy(() => import('./components/ForecastPanel')); +const AnnouncementsPanel = lazy(() => + import('../CompanyOverview/BasicInfoTab/components/AnnouncementsPanel') +); +const DisclosureSchedulePanel = lazy(() => + import('../CompanyOverview/BasicInfoTab/components/DisclosureSchedulePanel') +); + +// 二级 Tab 配置(带骨架屏 fallback) const TRACKING_TABS = [ - { key: 'news', name: '新闻动态', icon: FaNewspaper, component: NewsPanel }, - { key: 'announcements', name: '公司公告', icon: FaBullhorn, component: AnnouncementsPanel }, - { key: 'disclosure', name: '财报披露日程', icon: FaCalendarAlt, component: DisclosureSchedulePanel }, - { key: 'forecast', name: '业绩预告', icon: FaChartBar, component: ForecastPanel }, + { + key: 'news', + name: '新闻动态', + icon: FaNewspaper, + component: NewsPanel, + fallback: , + }, + { + key: 'announcements', + name: '公司公告', + icon: FaBullhorn, + component: AnnouncementsPanel, + fallback: , + }, + { + key: 'disclosure', + name: '财报披露日程', + icon: FaCalendarAlt, + component: DisclosureSchedulePanel, + fallback: , + }, + { + key: 'forecast', + name: '业绩预告', + icon: FaChartBar, + component: ForecastPanel, + fallback: , + }, ]; /** * 动态跟踪组件 * * 功能: - * - 使用 SubTabContainer 实现二级导航 - * - Tab1: 新闻动态 - * - Tab2: 公司公告 - * - Tab3: 财报披露日程 - * - Tab4: 业绩预告 + * - 使用 SubTabContainer 实现二级导航(同步渲染,无 loading) + * - 子组件懒加载,减少初始包体积 + * - 每个 Tab 有专属骨架屏,提供即时视觉反馈 * * @param {Object} props * @param {string} props.stockCode - 股票代码 */ -const DynamicTracking = ({ stockCode: propStockCode }) => { +const DynamicTracking = memo(({ stockCode: propStockCode }) => { const [stockCode, setStockCode] = useState(propStockCode || '000001'); const [activeTab, setActiveTab] = useState(0); @@ -50,6 +86,11 @@ const DynamicTracking = ({ stockCode: propStockCode }) => { [stockCode] ); + // Tab 切换回调 + const handleTabChange = useCallback((index) => { + setActiveTab(index); + }, []); + return ( { componentProps={componentProps} themePreset="blackGold" index={activeTab} - onTabChange={(index) => setActiveTab(index)} + onTabChange={handleTabChange} isLazy size="sm" /> ); -}; +}); + +DynamicTracking.displayName = 'DynamicTracking'; export default DynamicTracking;