feat: feat: 实现事件详情子模块懒加载useEventStocks添加 autoLoad 参数和分离加载函数 │ │

│ │   - DynamicNewsDetailPanel实现子模块折叠和懒加载
This commit is contained in:
zdl
2025-11-05 08:29:44 +08:00
parent e0cfa6fab2
commit e7c495a8b1
2 changed files with 131 additions and 39 deletions

View File

@@ -1,7 +1,7 @@
// src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js
// 动态新闻详情面板主组件(组装所有子组件)
import React, { useState, useCallback } from 'react';
import React, { useState, useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
Card,
@@ -42,20 +42,28 @@ const DynamicNewsDetailPanel = ({ event }) => {
const isFollowing = event?.id ? (eventFollowStatus[event.id]?.isFollowing || false) : false;
const followerCount = event?.id ? (eventFollowStatus[event.id]?.followerCount || event.follower_count || 0) : 0;
// 使用 Hook 获取实时数据
// 使用 Hook 获取实时数据(禁用自动加载,改为手动触发)
const {
stocks,
quotes,
eventDetail,
historicalEvents,
expectationScore,
loading
} = useEventStocks(event?.id, event?.created_at);
loading,
loadStocksData,
loadHistoricalData,
loadChainAnalysis
} = useEventStocks(event?.id, event?.created_at, { autoLoad: false });
// 子区块折叠状态管理(默认折叠)+ 加载追踪
const [isStocksOpen, setIsStocksOpen] = useState(false);
const [hasLoadedStocks, setHasLoadedStocks] = useState(false);
const [isHistoricalOpen, setIsHistoricalOpen] = useState(false);
const [hasLoadedHistorical, setHasLoadedHistorical] = useState(false);
// 折叠状态管理
const [isStocksOpen, setIsStocksOpen] = useState(true);
const [isHistoricalOpen, setIsHistoricalOpen] = useState(true);
const [isTransmissionOpen, setIsTransmissionOpen] = useState(false);
const [hasLoadedTransmission, setHasLoadedTransmission] = useState(false);
// 自选股管理(使用 localStorage
const [watchlistSet, setWatchlistSet] = useState(() => {
@@ -67,6 +75,53 @@ const DynamicNewsDetailPanel = ({ event }) => {
}
});
// 相关股票 - 展开时加载
const handleStocksToggle = useCallback(() => {
const newState = !isStocksOpen;
setIsStocksOpen(newState);
if (newState && !hasLoadedStocks) {
console.log('%c📊 [相关股票] 首次展开,加载股票数据', 'color: #10B981; font-weight: bold;', { eventId: event?.id });
loadStocksData();
setHasLoadedStocks(true);
}
}, [isStocksOpen, hasLoadedStocks, loadStocksData, event?.id]);
// 历史事件对比 - 展开时加载
const handleHistoricalToggle = useCallback(() => {
const newState = !isHistoricalOpen;
setIsHistoricalOpen(newState);
if (newState && !hasLoadedHistorical) {
console.log('%c📜 [历史事件] 首次展开,加载历史事件数据', 'color: #3B82F6; font-weight: bold;', { eventId: event?.id });
loadHistoricalData();
setHasLoadedHistorical(true);
}
}, [isHistoricalOpen, hasLoadedHistorical, loadHistoricalData, event?.id]);
// 传导链分析 - 展开时加载
const handleTransmissionToggle = useCallback(() => {
const newState = !isTransmissionOpen;
setIsTransmissionOpen(newState);
if (newState && !hasLoadedTransmission) {
console.log('%c🔗 [传导链] 首次展开,加载传导链数据', 'color: #8B5CF6; font-weight: bold;', { eventId: event?.id });
loadChainAnalysis();
setHasLoadedTransmission(true);
}
}, [isTransmissionOpen, hasLoadedTransmission, loadChainAnalysis, event?.id]);
// 事件切换时重置所有子模块状态
useEffect(() => {
console.log('%c🔄 [事件切换] 重置所有子模块状态', 'color: #F59E0B; font-weight: bold;', { eventId: event?.id });
setIsStocksOpen(false);
setHasLoadedStocks(false);
setIsHistoricalOpen(false);
setHasLoadedHistorical(false);
setIsTransmissionOpen(false);
setHasLoadedTransmission(false);
}, [event?.id]);
// 切换关注状态
const handleToggleFollow = useCallback(async () => {
if (!event?.id) return;
@@ -148,7 +203,13 @@ const DynamicNewsDetailPanel = ({ event }) => {
eventTime={event.created_at}
/>
{/* 相关股票(可折叠) */}
{/* 相关股票(可折叠) - 懒加载 */}
<CollapsibleSection
title="相关股票"
isOpen={isStocksOpen}
onToggle={handleStocksToggle}
count={stocks?.length || 0}
>
{loading.stocks || loading.quotes ? (
<Center py={4}>
<Spinner size="md" color="blue.500" />
@@ -160,17 +221,18 @@ const DynamicNewsDetailPanel = ({ event }) => {
quotes={quotes}
eventTime={event.created_at}
watchlistSet={watchlistSet}
isOpen={isStocksOpen}
onToggle={() => setIsStocksOpen(!isStocksOpen)}
isOpen={true} // 内部始终展开
onToggle={() => {}} // 空函数
onWatchlistToggle={handleWatchlistToggle}
/>
)}
</CollapsibleSection>
{/* 历史事件对比(可折叠) */}
{/* 历史事件对比(可折叠) - 懒加载 */}
<CollapsibleSection
title="历史事件对比"
isOpen={isHistoricalOpen}
onToggle={() => setIsHistoricalOpen(!isHistoricalOpen)}
onToggle={handleHistoricalToggle}
count={historicalEvents?.length || 0}
>
{loading.historicalEvents ? (
@@ -186,11 +248,11 @@ const DynamicNewsDetailPanel = ({ event }) => {
)}
</CollapsibleSection>
{/* 传导链分析(可折叠) */}
{/* 传导链分析(可折叠) - 懒加载 */}
<CollapsibleSection
title="传导链分析"
isOpen={isTransmissionOpen}
onToggle={() => setIsTransmissionOpen(!isTransmissionOpen)}
onToggle={handleTransmissionToggle}
>
<TransmissionChainAnalysis
eventId={event.id}

View File

@@ -17,9 +17,11 @@ import { logger } from '../../../../../utils/logger';
*
* @param {string} eventId - 事件ID
* @param {string} eventTime - 事件时间
* @param {Object} options - 配置选项
* @param {boolean} options.autoLoad - 是否自动加载数据默认true
* @returns {Object} 事件数据和加载状态
*/
export const useEventStocks = (eventId, eventTime) => {
export const useEventStocks = (eventId, eventTime, { autoLoad = true } = {}) => {
const dispatch = useDispatch();
// 从 Redux 获取数据
@@ -45,22 +47,43 @@ export const useEventStocks = (eventId, eventTime) => {
// 加载状态
const loading = useSelector(state => state.stock.loading, shallowEqual);
// 加载所有数据
// 拆分加载函数 - 相关股票数据
const loadStocksData = useCallback(() => {
if (!eventId) return;
logger.debug('useEventStocks', '加载股票数据', { eventId });
dispatch(fetchEventStocks({ eventId }));
}, [dispatch, eventId]);
// 拆分加载函数 - 历史事件数据
const loadHistoricalData = useCallback(() => {
if (!eventId) return;
logger.debug('useEventStocks', '加载历史事件数据', { eventId });
dispatch(fetchHistoricalEvents({ eventId }));
dispatch(fetchExpectationScore({ eventId }));
}, [dispatch, eventId]);
// 拆分加载函数 - 传导链分析数据
const loadChainAnalysis = useCallback(() => {
if (!eventId) return;
logger.debug('useEventStocks', '加载传导链数据', { eventId });
dispatch(fetchChainAnalysis({ eventId }));
}, [dispatch, eventId]);
// 加载所有数据(保留用于兼容性)
const loadAllData = useCallback(() => {
if (!eventId) {
logger.warn('useEventStocks', 'eventId 为空,跳过数据加载');
return;
}
logger.debug('useEventStocks', '开始加载事件数据', { eventId });
logger.debug('useEventStocks', '开始加载事件所有数据', { eventId });
// 并发加载所有数据
dispatch(fetchEventStocks({ eventId }));
dispatch(fetchEventDetail({ eventId }));
dispatch(fetchHistoricalEvents({ eventId }));
dispatch(fetchChainAnalysis({ eventId }));
dispatch(fetchExpectationScore({ eventId }));
}, [dispatch, eventId]);
loadStocksData();
loadHistoricalData();
loadChainAnalysis();
}, [dispatch, eventId, loadStocksData, loadHistoricalData, loadChainAnalysis]);
// 强制刷新所有数据
const refreshAllData = useCallback(() => {
@@ -88,12 +111,16 @@ export const useEventStocks = (eventId, eventTime) => {
dispatch(fetchStockQuotes({ codes, eventTime }));
}, [dispatch, stocks, eventTime]);
// 自动加载事件数据
// 自动加载事件数据(可通过 autoLoad 参数控制)
useEffect(() => {
if (eventId) {
if (eventId && autoLoad) {
logger.debug('useEventStocks', '自动加载已启用,加载所有数据', { eventId, autoLoad });
loadAllData();
} else if (eventId && !autoLoad) {
logger.debug('useEventStocks', '自动加载已禁用,等待手动触发', { eventId, autoLoad });
// 禁用自动加载时,不加载任何数据
}
}, [eventId]); // 修复:只依赖 eventId避免无限循环
}, [eventId, autoLoad, loadAllData]); // 添加 loadAllData 依赖
// 自动加载行情数据
useEffect(() => {
@@ -131,6 +158,9 @@ export const useEventStocks = (eventId, eventTime) => {
// 方法
loadAllData,
loadStocksData, // 新增:加载股票数据
loadHistoricalData, // 新增:加载历史事件数据
loadChainAnalysis, // 新增:加载传导链数据(重命名避免冲突)
refreshAllData,
refreshQuotes
};