import { ref, computed, watch, nextTick } from 'vue' import { asyncBusFactory } from '@/utils' import { Dialog } from 'bill/index' import { useViewStack } from '@/hook' import type { UnwrapRef } from 'vue' 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 title = '多元融合' export const appEl = ref(null) 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) => { console.error('unset') isUnset = true run() nextTick(() => isUnset = false) } export const autoSetModeCallback = (current: T, setting: AutoSetModeSetting) => { let isSave = false const leaveCallback = (setting.recovery || setting.backup) && (() => { setting.recovery && setting.recovery() setting.backup && setting.backup() setting.leave && setting.leave() }) const saveCallback = async () => { leaveCallback && sysBus.off('leave', leaveCallback, { last: true }) isSave = true await setting.save() setting.backup && setting.backup() isSave = false } const handler = (newv: UnwrapRef, oldv?: UnwrapRef) => { if (isSave || isUnset) return if (!setting.isUpdate || setting.isUpdate(newv, oldv)) { isEdit.value || enterEdit() isOld.value || enterOld() saveCallback && sysBus.on('save', saveCallback, { last: true }) } leaveCallback && sysBus.on('leave', leaveCallback, { last: true }) } return () => { setting.backup && setting.backup() return watch(current as UnwrapRef, handler, { deep: true }) } } export const useAutoSetMode = (current: T, setting: AutoSetModeSetting) => { const startWatch = autoSetModeCallback(current, setting) useViewStack(startWatch) }