From b4710818f9d88cbc542ed3fde06bd279b0e2026c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=B7=E5=B0=8F=E5=89=8D?= Date: Fri, 23 Jan 2026 14:23:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0ios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StockQuoteCard/hooks/useStockQuoteData.ts | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts b/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts index a282672d..d3c72ee2 100644 --- a/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts +++ b/src/views/Company/components/StockQuoteCard/hooks/useStockQuoteData.ts @@ -3,14 +3,22 @@ * * 使用 /api/stock/{code}/quote-detail 接口获取完整行情数据 * 供 StockQuoteCard 内部使用 + * + * 支持实时刷新功能: + * - 默认每 5 秒自动刷新股价数据 + * - 可通过 refreshInterval 参数自定义刷新间隔 + * - 设置 refreshInterval 为 0 可禁用自动刷新 */ -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect, useCallback, useRef } from 'react'; import { logger } from '@utils/logger'; import axios from '@utils/axiosConfig'; import type { StockQuoteCardData } from '../types'; import type { BasicInfo } from '../../CompanyOverview/types'; +// 默认刷新间隔(毫秒) +const DEFAULT_REFRESH_INTERVAL = 5000; + /** * 将 API 响应数据转换为 StockQuoteCard 所需格式 */ @@ -52,6 +60,11 @@ const transformQuoteData = (apiData: any, stockCode: string): StockQuoteCardData }; }; +interface UseStockQuoteDataOptions { + /** 自动刷新间隔(毫秒),默认 5000ms,设为 0 禁用自动刷新 */ + refreshInterval?: number; +} + interface UseStockQuoteDataResult { quoteData: StockQuoteCardData | null; basicInfo: BasicInfo | null; @@ -63,10 +76,17 @@ interface UseStockQuoteDataResult { /** * 股票行情数据获取 Hook * 合并获取行情数据和基本信息 + * 支持定时自动刷新实现实时行情显示 * * @param stockCode - 股票代码 + * @param options - 配置选项 + * @param options.refreshInterval - 自动刷新间隔(毫秒),默认 5000,设为 0 禁用 */ -export const useStockQuoteData = (stockCode?: string): UseStockQuoteDataResult => { +export const useStockQuoteData = ( + stockCode?: string, + options: UseStockQuoteDataOptions = {} +): UseStockQuoteDataResult => { + const { refreshInterval = DEFAULT_REFRESH_INTERVAL } = options; const [quoteData, setQuoteData] = useState(null); const [basicInfo, setBasicInfo] = useState(null); const [quoteLoading, setQuoteLoading] = useState(false); @@ -186,6 +206,51 @@ export const useStockQuoteData = (stockCode?: string): UseStockQuoteDataResult = }; }, [stockCode]); + // 静默刷新行情数据(不触发 loading 状态,用于定时刷新) + const silentRefreshRef = useRef<() => Promise>(); + silentRefreshRef.current = async () => { + if (!stockCode) return; + + const baseCode = stockCode.split('.')[0]; + + try { + // 只刷新行情数据,不刷新基本信息(基本信息变化不频繁) + const quoteResult = await axios.get(`/api/stock/${baseCode}/quote-detail`); + + if (quoteResult.data.success && quoteResult.data.data) { + const transformedData = transformQuoteData(quoteResult.data.data, stockCode); + setQuoteData(transformedData); + logger.debug('useStockQuoteData', '静默刷新行情成功', { + stockCode, + price: transformedData?.currentPrice, + changePercent: transformedData?.changePercent, + }); + } + } catch (err) { + // 静默刷新失败时不更新 error 状态,保持之前的数据显示 + logger.warn('useStockQuoteData', '静默刷新失败', err); + } + }; + + // 定时自动刷新行情数据 + useEffect(() => { + // 禁用刷新或没有股票代码时不启动定时器 + if (!refreshInterval || refreshInterval <= 0 || !stockCode) { + return; + } + + logger.debug('useStockQuoteData', '启动定时刷新', { stockCode, refreshInterval }); + + const intervalId = setInterval(() => { + silentRefreshRef.current?.(); + }, refreshInterval); + + return () => { + logger.debug('useStockQuoteData', '停止定时刷新', { stockCode }); + clearInterval(intervalId); + }; + }, [stockCode, refreshInterval]); + return { quoteData, basicInfo,