168 lines
5.5 KiB
JavaScript
168 lines
5.5 KiB
JavaScript
// src/views/Community/components/StockDetailPanel/hooks/useEventStocks.js
|
||
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||
import { useEffect, useCallback, useMemo } from 'react';
|
||
import {
|
||
fetchEventStocks,
|
||
fetchStockQuotes,
|
||
fetchEventDetail,
|
||
fetchHistoricalEvents,
|
||
fetchChainAnalysis,
|
||
fetchExpectationScore
|
||
} from '../../../../../store/slices/stockSlice';
|
||
import { logger } from '../../../../../utils/logger';
|
||
|
||
/**
|
||
* 事件股票数据 Hook
|
||
* 封装事件相关的所有数据加载逻辑
|
||
*
|
||
* @param {string} eventId - 事件ID
|
||
* @param {string} eventTime - 事件时间
|
||
* @param {Object} options - 配置选项
|
||
* @param {boolean} options.autoLoad - 是否自动加载数据(默认true)
|
||
* @returns {Object} 事件数据和加载状态
|
||
*/
|
||
export const useEventStocks = (eventId, eventTime, { autoLoad = true } = {}) => {
|
||
const dispatch = useDispatch();
|
||
|
||
// 从 Redux 获取数据
|
||
const stocks = useSelector(state =>
|
||
eventId ? (state.stock.eventStocksCache[eventId] || []) : [],
|
||
shallowEqual // 防止不必要的引用变化
|
||
);
|
||
const quotes = useSelector(state => state.stock.quotes, shallowEqual);
|
||
const eventDetail = useSelector(state =>
|
||
eventId ? state.stock.eventDetailsCache[eventId] : null
|
||
);
|
||
const historicalEvents = useSelector(state =>
|
||
eventId ? (state.stock.historicalEventsCache[eventId] || []) : [],
|
||
shallowEqual // 防止不必要的引用变化
|
||
);
|
||
const chainAnalysis = useSelector(state =>
|
||
eventId ? state.stock.chainAnalysisCache[eventId] : null
|
||
);
|
||
const expectationScore = useSelector(state =>
|
||
eventId ? state.stock.expectationScores[eventId] : null
|
||
);
|
||
|
||
// 加载状态
|
||
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 });
|
||
|
||
// 并发加载所有数据
|
||
dispatch(fetchEventDetail({ eventId }));
|
||
loadStocksData();
|
||
loadHistoricalData();
|
||
loadChainAnalysis();
|
||
}, [dispatch, eventId, loadStocksData, loadHistoricalData, loadChainAnalysis]);
|
||
|
||
// 强制刷新所有数据
|
||
const refreshAllData = useCallback(() => {
|
||
if (!eventId) return;
|
||
|
||
logger.debug('useEventStocks', '强制刷新事件数据', { eventId });
|
||
|
||
dispatch(fetchEventStocks({ eventId, forceRefresh: true }));
|
||
dispatch(fetchEventDetail({ eventId, forceRefresh: true }));
|
||
dispatch(fetchHistoricalEvents({ eventId, forceRefresh: true }));
|
||
dispatch(fetchChainAnalysis({ eventId, forceRefresh: true }));
|
||
dispatch(fetchExpectationScore({ eventId }));
|
||
}, [dispatch, eventId]);
|
||
|
||
// 只刷新行情数据
|
||
const refreshQuotes = useCallback(() => {
|
||
if (stocks.length === 0) return;
|
||
|
||
const codes = stocks.map(s => s.stock_code);
|
||
logger.debug('useEventStocks', '刷新行情数据', {
|
||
stockCount: codes.length,
|
||
eventTime
|
||
});
|
||
|
||
dispatch(fetchStockQuotes({ codes, eventTime }));
|
||
}, [dispatch, stocks, eventTime]);
|
||
|
||
// 自动加载事件数据(可通过 autoLoad 参数控制)
|
||
useEffect(() => {
|
||
if (eventId && autoLoad) {
|
||
logger.debug('useEventStocks', '自动加载已启用,加载所有数据', { eventId, autoLoad });
|
||
loadAllData();
|
||
} else if (eventId && !autoLoad) {
|
||
logger.debug('useEventStocks', '自动加载已禁用,等待手动触发', { eventId, autoLoad });
|
||
// 禁用自动加载时,不加载任何数据
|
||
}
|
||
}, [eventId, autoLoad, loadAllData]); // 添加 loadAllData 依赖
|
||
|
||
// 自动加载行情数据
|
||
useEffect(() => {
|
||
if (stocks.length > 0) {
|
||
refreshQuotes();
|
||
}
|
||
}, [stocks.length, eventId]); // 注意:这里不依赖 refreshQuotes,避免重复请求
|
||
|
||
// 计算股票行情合并数据
|
||
const stocksWithQuotes = useMemo(() => {
|
||
return stocks.map(stock => ({
|
||
...stock,
|
||
quote: quotes[stock.stock_code] || null
|
||
}));
|
||
}, [stocks, quotes]);
|
||
|
||
return {
|
||
// 数据
|
||
stocks,
|
||
stocksWithQuotes,
|
||
quotes,
|
||
eventDetail,
|
||
historicalEvents,
|
||
chainAnalysis,
|
||
expectationScore,
|
||
|
||
// 加载状态
|
||
loading: {
|
||
stocks: loading.stocks,
|
||
quotes: loading.quotes,
|
||
eventDetail: loading.eventDetail,
|
||
historicalEvents: loading.historicalEvents,
|
||
chainAnalysis: loading.chainAnalysis
|
||
},
|
||
|
||
// 方法
|
||
loadAllData,
|
||
loadStocksData, // 新增:加载股票数据
|
||
loadHistoricalData, // 新增:加载历史事件数据
|
||
loadChainAnalysis, // 新增:加载传导链数据(重命名避免冲突)
|
||
refreshAllData,
|
||
refreshQuotes
|
||
};
|
||
};
|