refactor: 重构 StockDetailPanel 目录结构,清理未使用代码
- 将 MiniTimelineChart 和 useEventStocks 迁移到 src/components/Charts/Stock/ - 更新 DynamicNewsDetailPanel 和 StockListItem 的导入路径 - 删除未使用的 SearchBox.js 和 useSearchEvents.js(约 300 行) - 建立统一的股票图表组件目录结构 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
173
src/components/Charts/Stock/hooks/useEventStocks.js
Normal file
173
src/components/Charts/Stock/hooks/useEventStocks.js
Normal file
@@ -0,0 +1,173 @@
|
||||
// src/components/Charts/Stock/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)
|
||||
* @param {boolean} options.autoLoadQuotes - 是否自动加载行情数据(默认true,设为false可延迟到展开时加载)
|
||||
* @returns {Object} 事件数据和加载状态
|
||||
*/
|
||||
export const useEventStocks = (eventId, eventTime, { autoLoad = true, autoLoadQuotes = 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 依赖
|
||||
|
||||
// 自动加载行情数据(可通过 autoLoadQuotes 参数控制)
|
||||
useEffect(() => {
|
||||
if (stocks.length > 0 && autoLoadQuotes) {
|
||||
const codes = stocks.map(s => s.stock_code);
|
||||
logger.debug('useEventStocks', '自动加载行情数据', {
|
||||
stockCount: codes.length,
|
||||
eventTime
|
||||
});
|
||||
dispatch(fetchStockQuotes({ codes, eventTime }));
|
||||
}
|
||||
}, [stocks, eventTime, autoLoadQuotes, dispatch]); // 直接使用 stocks 而不是 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
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user