import { useEffect } from "react"; import { bindScriptWorkspaceApi, editSessionHandle, useScriptWorkspaceStore, } from "../state/scriptWorkspaceStore"; type ActivePage = "home" | "scripts" | "schedules" | "system"; /** * 必须在 layout 层挂载,不能放在 ScriptsPage。 * 原因:心跳 / cleanup / beforeunload 需要在用户切到 /schedules 时仍运行, * 否则其他 tab 中的编辑会话锁会过期。 */ export function useEditSessionLifecycle({ activePage, }: { activePage: ActivePage; }) { // 1) 切到非 scripts 页时,如果当前有 active session,结束编辑 useEffect(() => { if (activePage === "scripts") return; const editBusy = useScriptWorkspaceStore.getState().editBusy; if (editBusy) return; if (!editSessionHandle.current) return; void useScriptWorkspaceStore.getState().endEditing(true, false); }, [activePage]); // 2) 心跳 + cleanup 定时器(15s 心跳,60s 检查 cleanup) useEffect(() => { let heartbeatRunning = false; let cleanupRunning = false; const heartbeatTimer = window.setInterval(() => { if (heartbeatRunning) return; heartbeatRunning = true; void useScriptWorkspaceStore.getState().tickHeartbeats().finally(() => { heartbeatRunning = false; }); }, 15 * 1000); const cleanupTimer = window.setInterval(() => { if (cleanupRunning) return; cleanupRunning = true; try { useScriptWorkspaceStore.getState().tickCleanup(); } finally { cleanupRunning = false; } }, 60 * 1000); return () => { window.clearInterval(heartbeatTimer); window.clearInterval(cleanupTimer); }; }, []); // 3) 卸载前释放编辑锁 useEffect(() => { const handleUnload = () => { useScriptWorkspaceStore.getState().releaseActiveOnUnload(); }; window.addEventListener("beforeunload", handleUnload); return () => window.removeEventListener("beforeunload", handleUnload); }, []); // 4) layout 卸载时解绑 api useEffect(() => { return () => { bindScriptWorkspaceApi(null); }; }, []); }