feat: feat: 实现事件详情子模块懒加载useEventStocks添加 autoLoad 参数和分离加载函数 │ │
│ │ - DynamicNewsDetailPanel实现子模块折叠和懒加载
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
// src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js
|
// 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 { useDispatch, useSelector } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -42,20 +42,28 @@ const DynamicNewsDetailPanel = ({ event }) => {
|
|||||||
const isFollowing = event?.id ? (eventFollowStatus[event.id]?.isFollowing || false) : false;
|
const isFollowing = event?.id ? (eventFollowStatus[event.id]?.isFollowing || false) : false;
|
||||||
const followerCount = event?.id ? (eventFollowStatus[event.id]?.followerCount || event.follower_count || 0) : 0;
|
const followerCount = event?.id ? (eventFollowStatus[event.id]?.followerCount || event.follower_count || 0) : 0;
|
||||||
|
|
||||||
// 使用 Hook 获取实时数据
|
// 使用 Hook 获取实时数据(禁用自动加载,改为手动触发)
|
||||||
const {
|
const {
|
||||||
stocks,
|
stocks,
|
||||||
quotes,
|
quotes,
|
||||||
eventDetail,
|
eventDetail,
|
||||||
historicalEvents,
|
historicalEvents,
|
||||||
expectationScore,
|
expectationScore,
|
||||||
loading
|
loading,
|
||||||
} = useEventStocks(event?.id, event?.created_at);
|
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 [isTransmissionOpen, setIsTransmissionOpen] = useState(false);
|
||||||
|
const [hasLoadedTransmission, setHasLoadedTransmission] = useState(false);
|
||||||
|
|
||||||
// 自选股管理(使用 localStorage)
|
// 自选股管理(使用 localStorage)
|
||||||
const [watchlistSet, setWatchlistSet] = useState(() => {
|
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 () => {
|
const handleToggleFollow = useCallback(async () => {
|
||||||
if (!event?.id) return;
|
if (!event?.id) return;
|
||||||
@@ -148,7 +203,13 @@ const DynamicNewsDetailPanel = ({ event }) => {
|
|||||||
eventTime={event.created_at}
|
eventTime={event.created_at}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 相关股票(可折叠) */}
|
{/* 相关股票(可折叠) - 懒加载 */}
|
||||||
|
<CollapsibleSection
|
||||||
|
title="相关股票"
|
||||||
|
isOpen={isStocksOpen}
|
||||||
|
onToggle={handleStocksToggle}
|
||||||
|
count={stocks?.length || 0}
|
||||||
|
>
|
||||||
{loading.stocks || loading.quotes ? (
|
{loading.stocks || loading.quotes ? (
|
||||||
<Center py={4}>
|
<Center py={4}>
|
||||||
<Spinner size="md" color="blue.500" />
|
<Spinner size="md" color="blue.500" />
|
||||||
@@ -160,17 +221,18 @@ const DynamicNewsDetailPanel = ({ event }) => {
|
|||||||
quotes={quotes}
|
quotes={quotes}
|
||||||
eventTime={event.created_at}
|
eventTime={event.created_at}
|
||||||
watchlistSet={watchlistSet}
|
watchlistSet={watchlistSet}
|
||||||
isOpen={isStocksOpen}
|
isOpen={true} // 内部始终展开
|
||||||
onToggle={() => setIsStocksOpen(!isStocksOpen)}
|
onToggle={() => {}} // 空函数
|
||||||
onWatchlistToggle={handleWatchlistToggle}
|
onWatchlistToggle={handleWatchlistToggle}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
</CollapsibleSection>
|
||||||
|
|
||||||
{/* 历史事件对比(可折叠) */}
|
{/* 历史事件对比(可折叠) - 懒加载 */}
|
||||||
<CollapsibleSection
|
<CollapsibleSection
|
||||||
title="历史事件对比"
|
title="历史事件对比"
|
||||||
isOpen={isHistoricalOpen}
|
isOpen={isHistoricalOpen}
|
||||||
onToggle={() => setIsHistoricalOpen(!isHistoricalOpen)}
|
onToggle={handleHistoricalToggle}
|
||||||
count={historicalEvents?.length || 0}
|
count={historicalEvents?.length || 0}
|
||||||
>
|
>
|
||||||
{loading.historicalEvents ? (
|
{loading.historicalEvents ? (
|
||||||
@@ -186,11 +248,11 @@ const DynamicNewsDetailPanel = ({ event }) => {
|
|||||||
)}
|
)}
|
||||||
</CollapsibleSection>
|
</CollapsibleSection>
|
||||||
|
|
||||||
{/* 传导链分析(可折叠) */}
|
{/* 传导链分析(可折叠) - 懒加载 */}
|
||||||
<CollapsibleSection
|
<CollapsibleSection
|
||||||
title="传导链分析"
|
title="传导链分析"
|
||||||
isOpen={isTransmissionOpen}
|
isOpen={isTransmissionOpen}
|
||||||
onToggle={() => setIsTransmissionOpen(!isTransmissionOpen)}
|
onToggle={handleTransmissionToggle}
|
||||||
>
|
>
|
||||||
<TransmissionChainAnalysis
|
<TransmissionChainAnalysis
|
||||||
eventId={event.id}
|
eventId={event.id}
|
||||||
|
|||||||
@@ -17,9 +17,11 @@ import { logger } from '../../../../../utils/logger';
|
|||||||
*
|
*
|
||||||
* @param {string} eventId - 事件ID
|
* @param {string} eventId - 事件ID
|
||||||
* @param {string} eventTime - 事件时间
|
* @param {string} eventTime - 事件时间
|
||||||
|
* @param {Object} options - 配置选项
|
||||||
|
* @param {boolean} options.autoLoad - 是否自动加载数据(默认true)
|
||||||
* @returns {Object} 事件数据和加载状态
|
* @returns {Object} 事件数据和加载状态
|
||||||
*/
|
*/
|
||||||
export const useEventStocks = (eventId, eventTime) => {
|
export const useEventStocks = (eventId, eventTime, { autoLoad = true } = {}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
// 从 Redux 获取数据
|
// 从 Redux 获取数据
|
||||||
@@ -45,22 +47,43 @@ export const useEventStocks = (eventId, eventTime) => {
|
|||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = useSelector(state => state.stock.loading, shallowEqual);
|
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(() => {
|
const loadAllData = useCallback(() => {
|
||||||
if (!eventId) {
|
if (!eventId) {
|
||||||
logger.warn('useEventStocks', 'eventId 为空,跳过数据加载');
|
logger.warn('useEventStocks', 'eventId 为空,跳过数据加载');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('useEventStocks', '开始加载事件数据', { eventId });
|
logger.debug('useEventStocks', '开始加载事件所有数据', { eventId });
|
||||||
|
|
||||||
// 并发加载所有数据
|
// 并发加载所有数据
|
||||||
dispatch(fetchEventStocks({ eventId }));
|
|
||||||
dispatch(fetchEventDetail({ eventId }));
|
dispatch(fetchEventDetail({ eventId }));
|
||||||
dispatch(fetchHistoricalEvents({ eventId }));
|
loadStocksData();
|
||||||
dispatch(fetchChainAnalysis({ eventId }));
|
loadHistoricalData();
|
||||||
dispatch(fetchExpectationScore({ eventId }));
|
loadChainAnalysis();
|
||||||
}, [dispatch, eventId]);
|
}, [dispatch, eventId, loadStocksData, loadHistoricalData, loadChainAnalysis]);
|
||||||
|
|
||||||
// 强制刷新所有数据
|
// 强制刷新所有数据
|
||||||
const refreshAllData = useCallback(() => {
|
const refreshAllData = useCallback(() => {
|
||||||
@@ -88,12 +111,16 @@ export const useEventStocks = (eventId, eventTime) => {
|
|||||||
dispatch(fetchStockQuotes({ codes, eventTime }));
|
dispatch(fetchStockQuotes({ codes, eventTime }));
|
||||||
}, [dispatch, stocks, eventTime]);
|
}, [dispatch, stocks, eventTime]);
|
||||||
|
|
||||||
// 自动加载事件数据
|
// 自动加载事件数据(可通过 autoLoad 参数控制)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (eventId) {
|
if (eventId && autoLoad) {
|
||||||
|
logger.debug('useEventStocks', '自动加载已启用,加载所有数据', { eventId, autoLoad });
|
||||||
loadAllData();
|
loadAllData();
|
||||||
|
} else if (eventId && !autoLoad) {
|
||||||
|
logger.debug('useEventStocks', '自动加载已禁用,等待手动触发', { eventId, autoLoad });
|
||||||
|
// 禁用自动加载时,不加载任何数据
|
||||||
}
|
}
|
||||||
}, [eventId]); // 修复:只依赖 eventId,避免无限循环
|
}, [eventId, autoLoad, loadAllData]); // 添加 loadAllData 依赖
|
||||||
|
|
||||||
// 自动加载行情数据
|
// 自动加载行情数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -131,6 +158,9 @@ export const useEventStocks = (eventId, eventTime) => {
|
|||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
loadAllData,
|
loadAllData,
|
||||||
|
loadStocksData, // 新增:加载股票数据
|
||||||
|
loadHistoricalData, // 新增:加载历史事件数据
|
||||||
|
loadChainAnalysis, // 新增:加载传导链数据(重命名避免冲突)
|
||||||
refreshAllData,
|
refreshAllData,
|
||||||
refreshQuotes
|
refreshQuotes
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user