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;