From 1caaec5601affaefafecacb742109696055d582e Mon Sep 17 00:00:00 2001 From: lkddi Date: Sun, 1 Mar 2026 00:12:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=B5=8F=E8=A7=88=E5=99=A8=E6=97=B6=20leave=20=E4=B8=8D?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E5=AF=BC=E8=87=B4=E5=8B=A4=E5=8A=A1=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E4=B8=8D=E7=BB=93=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 sendLeaveBeacon(),使用 navigator.sendBeacon 发送 leave 请求 - beforeunload 事件:关闭标签/浏览器/刷新均自动结算 - visibilitychange 事件:切到后台 30 秒后自动结算,切回来取消 - sendBeacon 比 fetch 更可靠,浏览器关闭时也能确保请求发出 --- .../views/chat/partials/scripts.blade.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/resources/views/chat/partials/scripts.blade.php b/resources/views/chat/partials/scripts.blade.php index 3da2a7e..01b658c 100644 --- a/resources/views/chat/partials/scripts.blade.php +++ b/resources/views/chat/partials/scripts.blade.php @@ -970,6 +970,35 @@ }, 500); } + // ── 关闭/离开页面时自动调用 leave,结算勤务时长 ────────────────────── + // 使用 sendBeacon 确保浏览器关闭时请求也能发出(比 fetch 更可靠) + function sendLeaveBeacon() { + const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); + if (!csrfToken || !window.chatContext?.leaveUrl) { + return; + } + const data = new FormData(); + data.append('_token', csrfToken); + navigator.sendBeacon(window.chatContext.leaveUrl, data); + } + + // beforeunload:关闭标签/浏览器/刷新 时触发 + window.addEventListener('beforeunload', sendLeaveBeacon); + + // visibilitychange:切换到后台标签超过30秒也结算(防止长期挂机不算时长) + let visibilityTimer = null; + document.addEventListener('visibilitychange', () => { + if (document.hidden) { + // 切到后台,30秒后结算 + visibilityTimer = setTimeout(sendLeaveBeacon, 30 * 1000); + } else { + // 切回来,取消结算 + clearTimeout(visibilityTimer); + visibilityTimer = null; + } + }); + + // ── 掉线检测计数器 ── let heartbeatFailCount = 0; const MAX_HEARTBEAT_FAILS = 3;