update pay ui
This commit is contained in:
@@ -219,20 +219,46 @@ const handleSZSERealtimeMessage = (
|
||||
case 'afterhours_trading': {
|
||||
const afterhoursData = data as SZSEAfterhoursData;
|
||||
const existing = prevQuotes[fullCode];
|
||||
const afterhoursInfo = {
|
||||
bidPx: afterhoursData.bid_px,
|
||||
bidSize: afterhoursData.bid_size,
|
||||
offerPx: afterhoursData.offer_px,
|
||||
offerSize: afterhoursData.offer_size,
|
||||
volume: afterhoursData.volume,
|
||||
amount: afterhoursData.amount,
|
||||
numTrades: afterhoursData.num_trades || 0,
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
// 合并到现有数据
|
||||
updated[fullCode] = {
|
||||
...existing,
|
||||
afterhours: {
|
||||
bidPx: afterhoursData.bid_px,
|
||||
bidSize: afterhoursData.bid_size,
|
||||
offerPx: afterhoursData.offer_px,
|
||||
offerSize: afterhoursData.offer_size,
|
||||
volume: afterhoursData.volume,
|
||||
amount: afterhoursData.amount,
|
||||
numTrades: afterhoursData.num_trades || 0,
|
||||
},
|
||||
afterhours: afterhoursInfo,
|
||||
updateTime: timestamp,
|
||||
} as QuoteData;
|
||||
} else {
|
||||
// 盘后首次收到数据(刷新页面后),创建基础行情结构
|
||||
updated[fullCode] = {
|
||||
code: fullCode,
|
||||
name: '',
|
||||
price: 0,
|
||||
prevClose: afterhoursData.prev_close,
|
||||
open: 0,
|
||||
high: 0,
|
||||
low: 0,
|
||||
volume: 0,
|
||||
amount: 0,
|
||||
change: 0,
|
||||
changePct: 0,
|
||||
bidPrices: [],
|
||||
bidVolumes: [],
|
||||
askPrices: [],
|
||||
askVolumes: [],
|
||||
tradingPhase: afterhoursData.trading_phase,
|
||||
afterhours: afterhoursInfo,
|
||||
updateTime: timestamp,
|
||||
exchange: 'SZSE',
|
||||
} as QuoteData;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -360,6 +386,9 @@ export const useRealtimeQuote = (codes: string[] = []): UseRealtimeQuoteReturn =
|
||||
const wsRefs = useRef<Record<Exchange, WebSocket | null>>({ SSE: null, SZSE: null });
|
||||
const heartbeatRefs = useRef<Record<Exchange, NodeJS.Timeout | null>>({ SSE: null, SZSE: null });
|
||||
const reconnectRefs = useRef<Record<Exchange, NodeJS.Timeout | null>>({ SSE: null, SZSE: null });
|
||||
// 重连计数器(避免无限重连刷屏)
|
||||
const reconnectCountRef = useRef<Record<Exchange, number>>({ SSE: 0, SZSE: 0 });
|
||||
const MAX_RECONNECT_ATTEMPTS = 5;
|
||||
// 深交所 WebSocket 就绪状态(收到 welcome 消息后才能订阅)
|
||||
const szseReadyRef = useRef<boolean>(false);
|
||||
// 待发送的深交所订阅队列(在 welcome 之前收到的订阅请求)
|
||||
@@ -539,8 +568,10 @@ export const useRealtimeQuote = (codes: string[] = []): UseRealtimeQuoteReturn =
|
||||
wsRefs.current[exchange] = ws;
|
||||
|
||||
ws.onopen = () => {
|
||||
logger.info('FlexScreen', `${exchange} WebSocket 已连接`);
|
||||
logger.info('FlexScreen', `${exchange} WebSocket 已连接`, { url: wsUrl });
|
||||
setConnected(prev => ({ ...prev, [exchange]: true }));
|
||||
// 连接成功,重置重连计数
|
||||
reconnectCountRef.current[exchange] = 0;
|
||||
|
||||
if (exchange === 'SSE') {
|
||||
// 上交所:连接后立即发送订阅
|
||||
@@ -569,7 +600,11 @@ export const useRealtimeQuote = (codes: string[] = []): UseRealtimeQuoteReturn =
|
||||
};
|
||||
|
||||
ws.onerror = (error: Event) => {
|
||||
logger.error('FlexScreen', `${exchange} WebSocket 错误`, error);
|
||||
logger.error('FlexScreen', `${exchange} WebSocket 连接失败`, {
|
||||
url: wsUrl,
|
||||
readyState: ws.readyState,
|
||||
hint: '请检查:1) 后端服务是否启动 2) Nginx 代理是否配置正确',
|
||||
});
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
@@ -582,14 +617,28 @@ export const useRealtimeQuote = (codes: string[] = []): UseRealtimeQuoteReturn =
|
||||
szseReadyRef.current = false;
|
||||
}
|
||||
|
||||
// 自动重连
|
||||
if (!reconnectRefs.current[exchange] && subscribedCodes.current[exchange].size > 0) {
|
||||
// 自动重连(有次数限制,避免刷屏)
|
||||
const currentAttempts = reconnectCountRef.current[exchange];
|
||||
if (
|
||||
!reconnectRefs.current[exchange] &&
|
||||
subscribedCodes.current[exchange].size > 0 &&
|
||||
currentAttempts < MAX_RECONNECT_ATTEMPTS
|
||||
) {
|
||||
reconnectCountRef.current[exchange] = currentAttempts + 1;
|
||||
// 指数退避:3秒、6秒、12秒、24秒、48秒
|
||||
const delay = RECONNECT_INTERVAL * Math.pow(2, currentAttempts);
|
||||
logger.info('FlexScreen', `${exchange} 将在 ${delay / 1000} 秒后重连 (${currentAttempts + 1}/${MAX_RECONNECT_ATTEMPTS})`);
|
||||
|
||||
reconnectRefs.current[exchange] = setTimeout(() => {
|
||||
reconnectRefs.current[exchange] = null;
|
||||
if (subscribedCodes.current[exchange].size > 0) {
|
||||
createConnection(exchange);
|
||||
}
|
||||
}, RECONNECT_INTERVAL);
|
||||
}, delay);
|
||||
} else if (currentAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
logger.warn('FlexScreen', `${exchange} 达到最大重连次数,停止重连。请检查 WebSocket 服务是否正常。`, {
|
||||
url: wsUrl,
|
||||
});
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user