fix: 会员过期时跳过 API 请求 & 限制 STOMP WebSocket 重连次数

- DynamicNewsDetailPanel: 添加会员过期判断,过期时显示续费提示
  - RelatedConceptsSection: 会员过期时跳过概念 API 请求
  - TransmissionChainAnalysis: 会员过期时跳过传导链 API 请求
  - BytedeskWidget: 限制 STOMP WebSocket 最多重连 3 次,屏蔽相关日志
This commit is contained in:
zdl
2025-12-24 15:24:06 +08:00
parent 6f44b8210e
commit c529626ce2
4 changed files with 120 additions and 18 deletions

View File

@@ -19,6 +19,10 @@ import PropTypes from 'prop-types';
let widgetInitialized = false;
let idleCallbackId = null;
// ⚡ STOMP WebSocket 重连限制(最多重试 3 次)
let stompRetryCount = 0;
const MAX_STOMP_RETRIES = 3;
const BytedeskWidget = ({
config,
autoLoad = true,
@@ -118,18 +122,79 @@ const BytedeskWidget = ({
// 5 秒后停止监听(避免性能问题)
setTimeout(() => observer.disconnect(), 5000);
// ⚡ 屏蔽 STOMP WebSocket 错误日志(不影响功能
// ⚡ 屏蔽 STOMP WebSocket 相关日志(控制台降噪
// STOMP 连接失败是因为后端服务配置问题,不影响客服功能(使用 HTTP 轮询降级)
const isStompLog = (args) => {
const msg = args.map(a => String(a)).join(' ');
// 只屏蔽包含 /stomp 路径的日志,避免误屏蔽其他 WebSocket 日志
return msg.includes('/stomp') || msg.includes('stomp onWebSocketError');
};
// 屏蔽 console.error
const originalConsoleError = console.error;
console.error = function(...args) {
const errorMsg = args.join(' ');
if (errorMsg.includes('/stomp') ||
errorMsg.includes('stomp onWebSocketError') ||
(errorMsg.includes('WebSocket connection to') && errorMsg.includes('/stomp'))) {
return;
}
if (isStompLog(args)) return;
originalConsoleError.apply(console, args);
};
// 屏蔽 console.warn
const originalConsoleWarn = console.warn;
console.warn = function(...args) {
if (isStompLog(args)) return;
originalConsoleWarn.apply(console, args);
};
// 屏蔽 console.log仅屏蔽 STOMP 相关)
const originalConsoleLog = console.log;
console.log = function(...args) {
if (isStompLog(args)) return;
originalConsoleLog.apply(console, args);
};
// ⚡ 限制 STOMP WebSocket 重连次数(最多 3 次)
// 通过代理 WebSocket 构造函数实现
const OriginalWebSocket = window.WebSocket;
const WebSocketProxy = function(url, protocols) {
// 检查是否是 STOMP 连接
if (url && url.includes('/stomp')) {
stompRetryCount++;
// 超过最大重试次数,阻止连接
if (stompRetryCount > MAX_STOMP_RETRIES) {
// 返回一个假的 WebSocket 对象,不实际连接
const fakeWs = Object.create(OriginalWebSocket.prototype);
fakeWs.url = url;
fakeWs.readyState = 3; // CLOSED
fakeWs.send = () => {};
fakeWs.close = () => {};
fakeWs.addEventListener = () => {};
fakeWs.removeEventListener = () => {};
fakeWs.onopen = null;
fakeWs.onclose = null;
fakeWs.onerror = null;
fakeWs.onmessage = null;
// 异步触发 onerror 和 onclose
setTimeout(() => {
if (fakeWs.onerror) fakeWs.onerror(new Event('error'));
if (fakeWs.onclose) fakeWs.onclose(new CloseEvent('close', { code: 1006 }));
}, 0);
return fakeWs;
}
}
// 正常创建 WebSocket
return protocols
? new OriginalWebSocket(url, protocols)
: new OriginalWebSocket(url);
};
// 保留原始 WebSocket 的静态属性和原型链
WebSocketProxy.prototype = OriginalWebSocket.prototype;
WebSocketProxy.CONNECTING = OriginalWebSocket.CONNECTING;
WebSocketProxy.OPEN = OriginalWebSocket.OPEN;
WebSocketProxy.CLOSING = OriginalWebSocket.CLOSING;
WebSocketProxy.CLOSED = OriginalWebSocket.CLOSED;
window.WebSocket = WebSocketProxy;
if (onLoad) {
onLoad(bytedesk);
}