结束。 // 由于篇幅限制,这里不再重复粘贴,请将之前完整版的这些函数复制进来即可,它们没有改动。 // 注意:在 initWebSocket 之前添加 window.popstate 等启动代码,具体如下: // WebSocket function initWebSocket() { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; ws = new WebSocket(`${protocol}//${window.location.host}?userId=${USER_ID}`); ws.onopen = () => { console.log('WebSocket 已连接'); if (reconnectTimer) clearTimeout(reconnectTimer); }; ws.onmessage = (event) => { try { const data = JSON.parse(event.data); if (data.type === 'data_changed') { if (!isReloading) { isReloading = true; setTimeout(async () => { await handleRouting(); isReloading = false; }, 100); } } else if (data.type === 'danmaku') { addMessageBubble(data.message, data.level, data.userName, data.userAvatar); } else if (data.type === 'offline_messages') { data.messages.forEach(msg => addMessageBubble(msg.message, msg.type)); } } catch (e) { console.error('WebSocket 消息解析失败', e); } }; ws.onclose = () => { console.log('WebSocket 断开,重连...'); reconnectTimer = setTimeout(initWebSocket, 3000); }; ws.onerror = (err) => { console.error('WebSocket 错误', err); }; } // 启动 API.syncUserInfo(); initWebSocket(); window.addEventListener('popstate', () => handleRouting()); document.getElementById('saveRuleBtn')?.addEventListener('click', saveRule); document.querySelectorAll('.close-rule-modal').forEach(b => b.addEventListener('click', closeRuleModal)); document.querySelectorAll('.close-batch-result').forEach(b => b.addEventListener('click', closeBatchResult)); handleRouting(); })();