// src/views/Community/index.js import React, { useEffect, useRef, lazy, Suspense } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; import { fetchPopularKeywords, fetchHotEvents } from '@/store/slices/communityDataSlice'; import { Box, Container, useColorModeValue, useBreakpointValue, Skeleton, } from '@chakra-ui/react'; // 导入组件 import DynamicNewsCard from './components/DynamicNewsCard'; import HotEventsSection from './components/HotEventsSection'; // ⚡ HeroPanel 懒加载:包含 ECharts (~600KB),首屏不需要立即渲染 const HeroPanel = lazy(() => import('./components/HeroPanel')); // 导入自定义 Hooks import { useEventData } from './hooks/useEventData'; import { useEventFilters } from './hooks/useEventFilters'; import { useCommunityEvents } from './hooks/useCommunityEvents'; import { logger } from '@/utils/logger'; import { useNotification } from '@/contexts/NotificationContext'; import { PROFESSIONAL_COLORS } from '@/constants/professionalTheme'; import { flushPendingEventsBeforeUnload } from '@/utils/trackingHelpers'; // 导航栏已由 MainLayout 提供,无需在此导入 const Community = () => { const navigate = useNavigate(); const location = useLocation(); // ⚡ 获取当前路由信息(用于判断是否在 /community 页面) const dispatch = useDispatch(); // Redux状态 const { popularKeywords, hotEvents } = useSelector(state => state.communityData); // 专业配色 - 深色主题 const bgColor = PROFESSIONAL_COLORS.background.primary; // Ref:用于首次滚动到内容区域 const containerRef = useRef(null); // 响应式容器宽度 const containerMaxW = useBreakpointValue({ base: '100%', // 移动端:全宽 sm: '100%', // 小屏:全宽 md: '100%', // 中屏:全宽 lg: '1200px', // 大屏:1200px xl: '1400px', // 超大屏:1400px }); // 响应式内边距 const containerPx = useBreakpointValue({ base: 2, // 移动端:最小内边距 sm: 3, md: 4, lg: 6, }); // ⚡ 通知权限引导 const { browserPermission, requestBrowserPermission, registerEventUpdateCallback } = useNotification(); // ⚡ DynamicNewsCard 的 ref(用于触发刷新) const dynamicNewsCardRef = useRef(null); // 🎯 初始化Community埋点Hook const communityEvents = useCommunityEvents({ navigate }); // 自定义 Hooks const { filters, updateFilters, handlePageChange, handleEventClick, handleViewDetail } = useEventFilters({ navigate }); const { events, pagination, loading, lastUpdateTime } = useEventData(filters); // 加载热门关键词和热点事件(动态新闻由 DynamicNewsCard 内部管理) useEffect(() => { dispatch(fetchPopularKeywords()); dispatch(fetchHotEvents()); }, [dispatch]); // ⚡ 页面卸载前刷新待发送的 PostHog 事件(性能优化) useEffect(() => { window.addEventListener('beforeunload', flushPendingEventsBeforeUnload); return () => { window.removeEventListener('beforeunload', flushPendingEventsBeforeUnload); }; }, []); // 🎯 追踪新闻列表查看(当事件列表加载完成后) useEffect(() => { if (events && events.length > 0 && !loading) { communityEvents.trackNewsListViewed({ totalCount: pagination?.total || events.length, sortBy: filters.sort, importance: filters.importance, dateRange: filters.date_range, industryFilter: filters.industry_code, }); } }, [events, loading, pagination, filters]); /** * ⚡ 【核心逻辑】注册 Socket 新事件回调 - 当收到新事件时智能刷新列表 * * 工作流程: * 1. Socket 收到 'new_event' 事件 → NotificationContext 触发所有注册的回调 * 2. 本回调被触发 → 检查当前路由是否为 /community * 3. 如果在 /community 页面 → 调用 DynamicNewsCard.refresh() 方法 * 4. DynamicNewsCard 根据模式和滚动位置决定是否刷新: * - 纵向模式 + 第1页 → 刷新列表 * - 纵向模式 + 其他页 → 不刷新(避免打断用户) * - 平铺模式 + 滚动在顶部 → 刷新列表 * - 平铺模式 + 滚动不在顶部 → 仅显示 Toast 提示 * * 设计要点: * - 使用 registerEventUpdateCallback 注册回调,返回的函数用于清理 * - 路由检查:只在 /community 页面触发刷新 * - 智能刷新:由 DynamicNewsCard 根据上下文决定刷新策略 * - 自动清理:组件卸载时自动注销回调 */ useEffect(() => { // 定义回调函数 const handleNewEvent = (eventData) => { console.log('[Community] 🔔 收到新事件通知', { currentPath: location.pathname, eventData, }); // 检查是否在 /community 页面 if (location.pathname === '/community') { console.log('[Community] ✅ 当前在事件中心页面,触发 DynamicNewsCard 刷新'); // 调用 DynamicNewsCard 的 refresh 方法(智能刷新) if (dynamicNewsCardRef.current) { dynamicNewsCardRef.current.refresh(); } else { console.warn('[Community] ⚠️ DynamicNewsCard ref 不可用,无法触发刷新'); } } else { console.log('[Community] ⏭️ 当前不在事件中心页面,跳过刷新', { currentPath: location.pathname, }); } }; // 注册回调(返回清理函数) const unregister = registerEventUpdateCallback(handleNewEvent); console.log('[Community] ✅ 已注册 Socket 事件更新回调'); // 组件卸载时清理 return () => { if (unregister) { unregister(); console.log('[Community] 🧹 已注销 Socket 事件更新回调'); } }; }, [location.pathname, registerEventUpdateCallback]); // 依赖路由变化重新注册 return ( {/* 主内容区域 */} {/* ⚡ 顶部说明面板(懒加载):产品介绍 + 沪深指数 + 热门概念词云 */} }> {/* 实时要闻·动态追踪 - 横向滚动 */} {/* 热点事件区域 - 移至底部 */} ); }; export default Community;