feat: 创建第三个 Hook - useStockMonitoring.js(实时监控功能)
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
// src/views/Community/components/StockDetailPanel/hooks/useStockMonitoring.js
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { fetchStockQuotes } from '../../../../../store/slices/stockSlice';
|
||||
import { message } from 'antd';
|
||||
import { logger } from '../../../../../utils/logger';
|
||||
|
||||
/**
|
||||
* 股票实时监控 Hook
|
||||
* 提供定时刷新股票行情的功能
|
||||
*
|
||||
* @param {Array} stocks - 股票列表
|
||||
* @param {string} eventTime - 事件时间
|
||||
* @param {number} interval - 刷新间隔(毫秒),默认 5000ms
|
||||
* @returns {Object} 监控状态和控制方法
|
||||
*/
|
||||
export const useStockMonitoring = (stocks = [], eventTime = null, interval = 5000) => {
|
||||
const dispatch = useDispatch();
|
||||
const [isMonitoring, setIsMonitoring] = useState(false);
|
||||
const monitoringIntervalRef = useRef(null);
|
||||
|
||||
// 从 Redux 获取行情数据和加载状态
|
||||
const quotes = useSelector(state => state.stock.quotes);
|
||||
const quotesLoading = useSelector(state => state.stock.loading.quotes);
|
||||
|
||||
/**
|
||||
* 执行一次行情更新
|
||||
*/
|
||||
const updateQuotes = useCallback(() => {
|
||||
if (stocks.length === 0) {
|
||||
logger.warn('useStockMonitoring', '股票列表为空,跳过更新');
|
||||
return;
|
||||
}
|
||||
|
||||
const codes = stocks.map(s => s.stock_code);
|
||||
logger.debug('useStockMonitoring', '更新行情数据', {
|
||||
stockCount: codes.length,
|
||||
eventTime,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
dispatch(fetchStockQuotes({ codes, eventTime }));
|
||||
}, [dispatch, stocks, eventTime]);
|
||||
|
||||
/**
|
||||
* 开启实时监控
|
||||
*/
|
||||
const startMonitoring = useCallback(() => {
|
||||
if (isMonitoring) {
|
||||
logger.warn('useStockMonitoring', '监控已经在运行中');
|
||||
return;
|
||||
}
|
||||
|
||||
if (stocks.length === 0) {
|
||||
message.warning('暂无股票数据,无法开启监控');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('useStockMonitoring', '开启实时监控', {
|
||||
interval,
|
||||
stockCount: stocks.length
|
||||
});
|
||||
|
||||
setIsMonitoring(true);
|
||||
message.success(`已开启实时监控,每${interval / 1000}秒自动更新`);
|
||||
|
||||
// 立即执行一次
|
||||
updateQuotes();
|
||||
}, [isMonitoring, stocks, interval, updateQuotes]);
|
||||
|
||||
/**
|
||||
* 停止实时监控
|
||||
*/
|
||||
const stopMonitoring = useCallback(() => {
|
||||
if (!isMonitoring) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('useStockMonitoring', '停止实时监控');
|
||||
|
||||
setIsMonitoring(false);
|
||||
message.info('已停止实时监控');
|
||||
}, [isMonitoring]);
|
||||
|
||||
/**
|
||||
* 切换监控状态
|
||||
*/
|
||||
const toggleMonitoring = useCallback(() => {
|
||||
if (isMonitoring) {
|
||||
stopMonitoring();
|
||||
} else {
|
||||
startMonitoring();
|
||||
}
|
||||
}, [isMonitoring, startMonitoring, stopMonitoring]);
|
||||
|
||||
/**
|
||||
* 手动刷新一次
|
||||
*/
|
||||
const manualRefresh = useCallback(() => {
|
||||
logger.debug('useStockMonitoring', '手动刷新行情');
|
||||
updateQuotes();
|
||||
}, [updateQuotes]);
|
||||
|
||||
// 监控定时器效果
|
||||
useEffect(() => {
|
||||
// 清理旧的定时器
|
||||
if (monitoringIntervalRef.current) {
|
||||
clearInterval(monitoringIntervalRef.current);
|
||||
monitoringIntervalRef.current = null;
|
||||
}
|
||||
|
||||
if (isMonitoring && stocks.length > 0) {
|
||||
// 设置定时器
|
||||
monitoringIntervalRef.current = setInterval(() => {
|
||||
updateQuotes();
|
||||
}, interval);
|
||||
|
||||
logger.debug('useStockMonitoring', '定时器已设置', {
|
||||
interval,
|
||||
stockCount: stocks.length
|
||||
});
|
||||
}
|
||||
|
||||
// 清理函数
|
||||
return () => {
|
||||
if (monitoringIntervalRef.current) {
|
||||
clearInterval(monitoringIntervalRef.current);
|
||||
monitoringIntervalRef.current = null;
|
||||
logger.debug('useStockMonitoring', '定时器已清理');
|
||||
}
|
||||
};
|
||||
}, [isMonitoring, stocks.length, interval]); // 注意:不依赖 updateQuotes,避免重复创建定时器
|
||||
|
||||
// 组件卸载时自动停止监控
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (isMonitoring) {
|
||||
logger.debug('useStockMonitoring', '组件卸载,自动停止监控');
|
||||
setIsMonitoring(false);
|
||||
}
|
||||
};
|
||||
}, []); // 只在卸载时执行
|
||||
|
||||
return {
|
||||
// 状态
|
||||
isMonitoring,
|
||||
quotes,
|
||||
quotesLoading,
|
||||
|
||||
// 控制方法
|
||||
startMonitoring,
|
||||
stopMonitoring,
|
||||
toggleMonitoring,
|
||||
manualRefresh,
|
||||
|
||||
// 工具方法
|
||||
setIsMonitoring
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user