import { ref, computed, watch, nextTick, watchEffect } from "vue"; import { asyncBusFactory } from "@/utils"; import { Dialog } from "bill/index"; import { useViewStack } from "@/hook"; import type { UnwrapRef } from "vue"; import { currentMeta } from "@/router"; const Flags = { EDIT: 0b10, // 已经保存,是最新的 NOW: 0b100, // 可写模式,用户已登陆 LOGIN: 0b1000, } as const; const mode = ref(Flags.NOW); export const isEdit = computed(() => !!(mode.value & Flags.EDIT)); export const isLogin = computed(() => !!(mode.value & Flags.LOGIN)); export const isOld = computed(() => !(mode.value & Flags.NOW)); export const isNow = computed(() => !!(mode.value & Flags.NOW)); export const appEl = ref(null); export const prefix = ref(""); export const defTitle = ref("案件信息"); export const title = computed(() => { console.error(currentMeta.value); const last = currentMeta.value && "sysTitle" in currentMeta.value ? currentMeta.value.sysTitle : defTitle.value; console.error(prefix.value); if (prefix.value && last) { return prefix.value + " | " + last; } else { return prefix.value + last; } }); watchEffect(() => (document.title = title.value)); let currentTempIndex = 0; export const isTemploraryID = (id: string) => id.includes("__currentTempIndex__"); export const createTemploraryID = () => `__currentTempIndex__${currentTempIndex++}`; export const sysBus = asyncBusFactory<{ save: void; leave: void }>(); // 进入编辑界面 export const enterEdit = (cb?: () => void) => { mode.value |= Flags.EDIT; cb && sysBus.on("leave", cb); }; export const enterOld = (cb?: () => void) => { mode.value &= ~Flags.NOW; cb && sysBus.on("save", cb); }; // 放弃保存内容 export const giveupSave = () => { sysBus.off("save"); mode.value |= Flags.NOW; }; // 放弃编辑内容 export const giveupLeave = () => { giveupSave(); sysBus.off("leave"); mode.value &= ~Flags.EDIT; }; // 保存 export const save = async () => { await sysBus.emit("save"); giveupSave(); leave(); }; // 离开 export const leave = async () => { if ( isOld.value && !(await Dialog.confirm("您有操作未保存,确定要退出吗?")) ) { return; } await sysBus.emit("leave"); giveupLeave(); }; export type AutoSetModeSetting = { save: () => any; leave?: () => any; isUpdate?: (newCurrent: UnwrapRef, oldCurrent?: UnwrapRef) => boolean; auto?: boolean; backup?: () => void; recovery?: () => void; }; let isUnset = false; export const unSetModelUpdate = (run: () => void) => { isUnset = true; run(); nextTick(() => (isUnset = false)); }; export const autoSetModeCallback = ( current: T, setting: AutoSetModeSetting, last = true ) => { let isLeaveIng = false; let isSave = false; const leaveCallback = (setting.recovery || setting.backup) && (async () => { isLeaveIng = true; setting.recovery && (await setting.recovery()); // setting.backup && (await setting.backup()); setting.leave && (await setting.leave()); isLeaveIng = false; }); const saveCallback = async () => { isSave = true; try { await setting.save(); leaveCallback && sysBus.off("leave", leaveCallback, { last }); setting.backup && setting.backup(); isSave = false; } catch (e) { isSave = false; throw e; } }; const handler = (newv: UnwrapRef, oldv?: UnwrapRef) => { if (isSave || isUnset || isLeaveIng) return; if (!setting.isUpdate || setting.isUpdate(newv, oldv)) { isEdit.value || enterEdit(); isOld.value || enterOld(); saveCallback && sysBus.on("save", saveCallback, { last }); } leaveCallback && sysBus.on("leave", leaveCallback, { last }); }; return () => { setting.backup && setting.backup(); return watch(current as any, handler, { deep: true }); }; }; export const useAutoSetMode = ( current: T, setting: AutoSetModeSetting, last = true ) => { const startWatch = autoSetModeCallback(current, setting, last); useViewStack(startWatch); };