diff --git a/resources/views/chat/partials/scripts.blade.php b/resources/views/chat/partials/scripts.blade.php index 7f1acdb..5485efd 100644 --- a/resources/views/chat/partials/scripts.blade.php +++ b/resources/views/chat/partials/scripts.blade.php @@ -951,8 +951,8 @@ // ── 退出房间 ───────────────────────────────────── async function leaveRoom() { - // 主动移除 beforeunload 监听,防止 Chrome 触发"离开网站?"原生弹窗 - window.removeEventListener('beforeunload', sendLeaveBeacon); + // 标记主动离开,pagehide 里不重复发 beacon + window._manualLeave = true; clearTimeout(visibilityTimer); try { @@ -975,9 +975,14 @@ } + // ── 关闭/离开页面时自动调用 leave,结算勤务时长 ────────────────────── // 使用 sendBeacon 确保浏览器关闭时请求也能发出(比 fetch 更可靠) + // 注意:用 pagehide 而非 beforeunload,避免 Chrome 触发原生「离开网站」确认框 function sendLeaveBeacon() { + if (window._manualLeave) { + return; + } // 主动调用 leaveRoom() 时不重复发 const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); if (!csrfToken || !window.chatContext?.leaveUrl) { return; @@ -987,8 +992,8 @@ navigator.sendBeacon(window.chatContext.leaveUrl, data); } - // beforeunload:关闭标签/浏览器/刷新 时触发 - window.addEventListener('beforeunload', sendLeaveBeacon); + // pagehide:页面关闭/浏览器关闭/刷新均触发,且不会弹原生确认框 + window.addEventListener('pagehide', sendLeaveBeacon); // visibilitychange:切换到后台标签超过30秒也结算(防止长期挂机不算时长) let visibilityTimer = null; @@ -1004,6 +1009,8 @@ }); + + // ── 掉线检测计数器 ── let heartbeatFailCount = 0; const MAX_HEARTBEAT_FAILS = 3;