update pay ui
This commit is contained in:
@@ -116,56 +116,74 @@ const extractSZSEPrices = (stockData: SZSEStockData) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理深交所股票行情消息(新 API 格式:type='stock')
|
||||
* 处理深交所批量行情消息(新 API 格式,与 SSE 一致)
|
||||
* 格式:{ type: 'stock', data: { '000001': {...}, '000002': {...} }, timestamp: '...' }
|
||||
*/
|
||||
const handleSZSEStockMessage = (
|
||||
data: SZSEStockData,
|
||||
timestamp: string,
|
||||
const handleSZSEBatchMessage = (
|
||||
msg: SZSERealtimeMessage,
|
||||
subscribedCodes: Set<string>,
|
||||
prevQuotes: QuotesMap
|
||||
): QuotesMap | null => {
|
||||
const rawCode = data.security_id;
|
||||
const fullCode = rawCode.includes('.') ? rawCode : `${rawCode}.SZ`;
|
||||
const { data, timestamp } = msg;
|
||||
|
||||
if (!subscribedCodes.has(rawCode) && !subscribedCodes.has(fullCode)) {
|
||||
// 新 API 格式:data 是 { code: quote, ... } 的字典
|
||||
if (!data || typeof data !== 'object') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { bidPrices, bidVolumes, askPrices, askVolumes } = extractSZSEOrderBook(data);
|
||||
const { prevClose, volume, amount, upperLimit, lowerLimit, tradingPhase } = extractSZSEPrices(data);
|
||||
|
||||
const updated: QuotesMap = { ...prevQuotes };
|
||||
updated[fullCode] = {
|
||||
code: fullCode,
|
||||
name: prevQuotes[fullCode]?.name || '',
|
||||
price: data.last_px,
|
||||
prevClose,
|
||||
open: data.open_px,
|
||||
high: data.high_px,
|
||||
low: data.low_px,
|
||||
volume,
|
||||
amount,
|
||||
numTrades: data.num_trades,
|
||||
upperLimit,
|
||||
lowerLimit,
|
||||
change: data.last_px - prevClose,
|
||||
changePct: calcChangePct(data.last_px, prevClose),
|
||||
bidPrices,
|
||||
bidVolumes,
|
||||
askPrices,
|
||||
askVolumes,
|
||||
tradingPhase,
|
||||
updateTime: data.update_time || timestamp,
|
||||
exchange: 'SZSE',
|
||||
} as QuoteData;
|
||||
let hasUpdate = false;
|
||||
|
||||
return updated;
|
||||
// 遍历所有股票数据
|
||||
Object.entries(data).forEach(([code, quote]) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const stockData = quote as any;
|
||||
if (!stockData || typeof stockData !== 'object') return;
|
||||
|
||||
const rawCode = stockData.security_id || code;
|
||||
const fullCode = rawCode.includes('.') ? rawCode : `${rawCode}.SZ`;
|
||||
|
||||
// 只处理已订阅的代码
|
||||
if (!subscribedCodes.has(code) && !subscribedCodes.has(rawCode) && !subscribedCodes.has(fullCode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasUpdate = true;
|
||||
const { bidPrices, bidVolumes, askPrices, askVolumes } = extractSZSEOrderBook(stockData);
|
||||
const { prevClose, volume, amount, upperLimit, lowerLimit, tradingPhase } = extractSZSEPrices(stockData);
|
||||
|
||||
updated[fullCode] = {
|
||||
code: fullCode,
|
||||
name: prevQuotes[fullCode]?.name || '',
|
||||
price: stockData.last_px,
|
||||
prevClose,
|
||||
open: stockData.open_px,
|
||||
high: stockData.high_px,
|
||||
low: stockData.low_px,
|
||||
volume,
|
||||
amount,
|
||||
numTrades: stockData.num_trades,
|
||||
upperLimit,
|
||||
lowerLimit,
|
||||
change: stockData.last_px - prevClose,
|
||||
changePct: calcChangePct(stockData.last_px, prevClose),
|
||||
bidPrices,
|
||||
bidVolumes,
|
||||
askPrices,
|
||||
askVolumes,
|
||||
tradingPhase,
|
||||
updateTime: stockData.update_time || timestamp,
|
||||
exchange: 'SZSE',
|
||||
} as QuoteData;
|
||||
});
|
||||
|
||||
return hasUpdate ? updated : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理深交所实时消息 (兼容新旧 API)
|
||||
* 新 API: type='stock'/'bond'/'fund', data 直接是行情对象
|
||||
* 旧 API: type='realtime', category='stock'/'bond'/etc
|
||||
* 新 API (批量模式): type='stock'/'bond'/'fund', data = { code: quote, ... }
|
||||
* 旧 API (单条模式): type='realtime', category='stock', data = { security_id, ... }
|
||||
*/
|
||||
const handleSZSERealtimeMessage = (
|
||||
msg: SZSERealtimeMessage,
|
||||
@@ -173,7 +191,22 @@ const handleSZSERealtimeMessage = (
|
||||
prevQuotes: QuotesMap
|
||||
): QuotesMap | null => {
|
||||
const { type, category, data, timestamp } = msg;
|
||||
const rawCode = data.security_id;
|
||||
|
||||
// 新 API 批量格式检测:data 是字典 { code: quote, ... },没有 security_id 在顶层
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const anyData = data as any;
|
||||
const isBatchFormat = anyData && typeof anyData === 'object' && !anyData.security_id;
|
||||
|
||||
if (isBatchFormat && (type === 'stock' || type === 'bond' || type === 'fund')) {
|
||||
return handleSZSEBatchMessage(msg, subscribedCodes, prevQuotes);
|
||||
}
|
||||
|
||||
// 旧 API 单条格式:data 直接是行情对象 { security_id, last_px, ... }
|
||||
const rawCode = anyData?.security_id;
|
||||
if (!rawCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fullCode = rawCode.includes('.') ? rawCode : `${rawCode}.SZ`;
|
||||
|
||||
if (!subscribedCodes.has(rawCode) && !subscribedCodes.has(fullCode)) {
|
||||
|
||||
Reference in New Issue
Block a user