diff --git a/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts b/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts index d8fb5693..53e7e617 100644 --- a/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts +++ b/src/views/StockOverview/components/FlexScreen/hooks/useRealtimeQuote.ts @@ -229,30 +229,38 @@ const handleSZSERealtimeMessage = ( numTrades: afterhoursData.num_trades || 0, }; + // 盘后数据的当前价格:优先使用 bid_px(买入价),否则使用 offer_px(卖出价) + const afterhoursPrice = afterhoursData.bid_px || afterhoursData.offer_px || 0; + const prevClose = afterhoursData.prev_close || existing?.prevClose || 0; + if (existing) { - // 合并到现有数据 + // 合并到现有数据,同时更新价格(如果盘后价格有效) + const newPrice = afterhoursPrice > 0 ? afterhoursPrice : existing.price; updated[fullCode] = { ...existing, + price: newPrice, + change: newPrice - prevClose, + changePct: calcChangePct(newPrice, prevClose), afterhours: afterhoursInfo, updateTime: timestamp, } as QuoteData; } else { - // 盘后首次收到数据(刷新页面后),创建基础行情结构 + // 盘后首次收到数据(刷新页面后),使用盘后价格创建行情结构 updated[fullCode] = { code: fullCode, name: '', - price: 0, - prevClose: afterhoursData.prev_close, + price: afterhoursPrice, + prevClose: prevClose, open: 0, high: 0, low: 0, volume: 0, amount: 0, - change: 0, - changePct: 0, - bidPrices: [], + change: afterhoursPrice - prevClose, + changePct: calcChangePct(afterhoursPrice, prevClose), + bidPrices: afterhoursPrice > 0 ? [afterhoursPrice] : [], bidVolumes: [], - askPrices: [], + askPrices: afterhoursData.offer_px > 0 ? [afterhoursData.offer_px] : [], askVolumes: [], tradingPhase: afterhoursData.trading_phase, afterhours: afterhoursInfo, diff --git a/src/views/StockOverview/components/HotspotOverview/hooks/useHotspotData.js b/src/views/StockOverview/components/HotspotOverview/hooks/useHotspotData.js index 2fbca02a..02ac7458 100644 --- a/src/views/StockOverview/components/HotspotOverview/hooks/useHotspotData.js +++ b/src/views/StockOverview/components/HotspotOverview/hooks/useHotspotData.js @@ -2,7 +2,7 @@ * 热点概览数据获取 Hook * 负责获取指数分时数据和概念异动数据 */ -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect, useCallback, useRef } from 'react'; import { logger } from '@utils/logger'; /** @@ -14,19 +14,36 @@ export const useHotspotData = (selectedDate) => { const [error, setError] = useState(null); const [data, setData] = useState(null); - const fetchData = useCallback(async () => { + // 用于防止 React StrictMode 下的双重请求 + const fetchingRef = useRef(false); + const lastDateRef = useRef(null); + + const fetchData = useCallback(async (forceRefetch = false) => { + // 获取日期字符串用于比较 + const dateStr = selectedDate ? selectedDate.toISOString().split('T')[0] : 'today'; + + // 如果正在请求中,或者日期未变化且不是强制刷新,跳过 + if (fetchingRef.current && !forceRefetch) { + return; + } + if (lastDateRef.current === dateStr && data && !forceRefetch) { + return; + } + + fetchingRef.current = true; setLoading(true); setError(null); try { const dateParam = selectedDate - ? `?date=${selectedDate.toISOString().split('T')[0]}` + ? `?date=${dateStr}` : ''; const response = await fetch(`/api/market/hotspot-overview${dateParam}`); const result = await response.json(); if (result.success) { setData(result.data); + lastDateRef.current = dateStr; } else { setError(result.error || '获取数据失败'); } @@ -35,8 +52,9 @@ export const useHotspotData = (selectedDate) => { setError('网络请求失败'); } finally { setLoading(false); + fetchingRef.current = false; } - }, [selectedDate]); + }, [selectedDate, data]); useEffect(() => { fetchData(); @@ -46,7 +64,7 @@ export const useHotspotData = (selectedDate) => { loading, error, data, - refetch: fetchData, + refetch: () => fetchData(true), }; };