| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- import { routeName, router } from '@/router'
- import { Dialog } from '@kankan/components/index'
- import { ref, Ref, watch } from 'vue'
- import { useAsyncBus, Handler } from './useAsyncBus'
- import { useViewStack } from './useViewStack'
- import { disabledMap } from './custom'
- import { ui18n } from '@/lang'
- import { useConfirm } from '@/hook'
- export const editBus = useAsyncBus<{ save: void; leave: void }>()
- export type EditHandler = () => void
- export type EditStatus = {
- edit: EditHandler
- desave: EditHandler
- leaveSave: EditHandler
- leave: EditHandler
- }
- let mark: EditStatus & { isedit: boolean; isdesave: boolean }
- export type KV<T> = [Ref<T>, T] | [Ref<T>, T, T]
- export type KVS<T> = Array<KV<T>>
- export type VS<T> = Array<KVS<T>[number][1]>
- // 进入编辑界面
- export const useEdit = <T>(args?: KV<T> | KVS<T>) => {
- if (!args) return mark.edit()
- const kvs = (Array.isArray(args[0]) ? args : [args]) as KVS<T>
- const cacheks = kvs.map(([k, _, d = k.value]) => d)
- const updateKs = (value: VS<T>) => {
- for (let i = 0; i < kvs.length; i++) {
- kvs[i][0].value = value[i]
- }
- }
- mark.edit()
- updateKs(kvs.map(([_, v]) => v))
- editBus.on('leave', () => updateKs(cacheks), { last: true })
- }
- // 保存
- export const useEmitSave = () => {
- editBus.emit('save').then(() => {
- if (!disabledMap.autoLeave) {
- useLeaveEdit()
- } else {
- useLeaveSave()
- }
- })
- }
- // 退出
- let sureBackPage = true
- export const useEmitLeave = async (isBack = true) => {
- if (mark.isdesave) {
- const isLeave = await useConfirm(ui18n.t('sys.forceLeaveConfirm'))
- if (!isLeave) {
- return false
- }
- }
- sureBackPage = isBack
- editBus.on('leave', () => (sureBackPage = true), { last: true })
- editBus.emit('leave').then(useLeaveEdit)
- return true
- }
- export const useLeaveEditRaw = () => mark.leave()
- // 退出保存
- export const useLeaveSave = () => {
- editBus.off('save')
- mark.leaveSave()
- }
- // 退出编辑
- export const useLeaveEdit = () => {
- editBus.off('save')
- editBus.off('leave')
- mark.leave()
- mark.leaveSave()
- }
- export type DesaveArgs = {
- save?: Handler
- leave?: Handler
- }
- // 进入未保存模式
- export const useDesave = (cbs: DesaveArgs = {}) => {
- mark.desave()
- cbs.leave && editBus.on('leave', cbs.leave)
- cbs.save && editBus.on('save', cbs.save)
- }
- export type DesaveArgsAssistArgs<T> = DesaveArgs & {
- intercept?: (newCurrent: T, oldCurrent: T) => boolean
- auto?: boolean
- backup?: () => void
- recovery?: () => void
- }
- export function useDesaveAssist<T extends object>(
- current: T,
- setting: DesaveArgsAssistArgs<T> & { auto: false }
- ): () => () => void
- export function useDesaveAssist<T extends object>(
- current: T,
- setting: DesaveArgsAssistArgs<T> & { auto: true }
- ): { desave: Ref<boolean> }
- export function useDesaveAssist<T extends object>(
- current: T,
- setting: DesaveArgsAssistArgs<T>
- ) {
- const desave = ref(false)
- const { recovery, backup, leave } = setting
- const leaveHandler = () => {
- isSave = false;
- if (recovery || backup) {
- recovery && recovery()
- backup && backup()
- desave.value = false
- leave && (leave as any)()
- }
- }
-
- let isSave = false
- const save = async args => {
- isSave = true
- try {
- await setting.save(args)
- } catch (e) {
- // recovery && recovery()
- throw e
- }
- isSave = false
- }
- const handler = (newv, oldv) => {
- if (!isSave) {
- if (!setting.intercept || setting.intercept(newv, oldv)) {
- desave.value = true
- mark.isedit || useEdit()
- useDesave({ save })
- backup && editBus.on('save', backup, { last: true })
- }
- leaveHandler && editBus.on('leave', leaveHandler, { last: true })
- }
- }
- const saveWatch = () => {
- backup && backup()
- return watch(current, handler, { deep: true })
- }
- if (setting.auto) {
- useViewStack(saveWatch)
- return { desave }
- } else {
- return saveWatch
- }
- }
- export const useBack = (type: 'save' | 'leave' = 'leave') => {
- if (sureBackPage && (type === 'leave' || !disabledMap.autoLeave)) {
- if (!history.state.back) {
- router.replace({ name: routeName.value.query })
- } else {
- router.back()
- }
- }
- }
- type HookArgs = (...args: any) => void | (() => any | void)
- export const useViewEdit = (
- hook?: HookArgs,
- cb: (type: 'save' | 'leave') => void = useBack
- ) =>
- useViewStack(() => {
- useEdit()
- editBus.on('leave', () => cb('leave'), { last: true })
- editBus.on('save', () => cb('save'), { last: true })
- const exitFn = hook && hook()
- return () => {
- useLeaveEdit()
- exitFn && exitFn()
- }
- })
- export const setupEdit = (status: EditStatus) => {
- mark = {
- edit: () => {
- mark.isedit = true
- status.edit()
- },
- desave: () => {
- mark.isdesave = true
- status.desave()
- },
- leave: () => {
- mark.isdesave = false
- mark.isedit = false
- status.leave()
- },
- leaveSave: () => {
- mark.isdesave = false
- status.leaveSave()
- },
- isedit: false,
- isdesave: false
- }
- }
|