import { computed, getCurrentInstance, reactive, ref, type Ref } from 'vue' import { ElMessageBox } from 'element-plus' import { onBeforeRouteLeave } from 'vue-router' import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration' import { isWorkspaceRoute, workspaceRouteId } from '@/core/workspace-tabs/routeWorkspace' /** Veto native closing and supplement cached route switches; retain the shared registry for other exits. */ export function useFleetDraftGuard(key: string, open: Ref, model: object, busy: Ref, uncertain: Ref) { const baseline = ref(''), checking = ref(false) const snapshot = computed(() => JSON.stringify(model)) const registration = useUnsavedWorkRegistration({ key: `${key}:${getCurrentInstance()?.uid}`, label: computed(() => '拼车表单'), isOpen: computed(() => open.value || uncertain.value), model: reactive({ form: model, uncertain }), requiredPermission: computed(() => null) }) function capture() { baseline.value = snapshot.value; if (!uncertain.value) registration.captureBaseline() } async function mayClose(leaving = false) { if (busy.value || checking.value) return false if (snapshot.value !== baseline.value || uncertain.value) { checking.value = true try { await ElMessageBox.confirm( uncertain.value ? `上次提交结果尚未确定,原请求将保留。${leaving ? '离开' : '关闭'}后可重新打开并核对或重试,是否继续?` : leaving ? '表单有未保存内容,离开后将关闭表单并放弃本次修改。是否离开?' : '表单有未保存内容,确认放弃本次修改?', leaving ? '离开页面' : '关闭表单', { customClass: 'admin-density-confirm', confirmButtonText: leaving ? uncertain.value ? '保留请求并离开' : '放弃并离开' : '确认关闭', cancelButtonText: '继续填写' }, ) } catch { return false } finally { checking.value = false } } return true } async function beforeClose(done: () => void) { if (await mayClose()) done() } if (getCurrentInstance()?.proxy?.$route) { onBeforeRouteLeave(async (to, from) => { // The global guard protects destructive navigation; it intentionally skips cached workspace switches. if (!isWorkspaceRoute(to) || workspaceRouteId(to) === workspaceRouteId(from) || !open.value && !uncertain.value) return true if (!await mayClose(true)) return false open.value = false return true }) } return { capture, beforeClose, dirty: computed(() => snapshot.value !== baseline.value) } }