sys.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { ref, computed, watch, nextTick } from 'vue'
  2. import { asyncBusFactory } from '@/utils'
  3. import { Dialog } from 'bill/index'
  4. import { useViewStack } from '@/hook'
  5. import type { UnwrapRef } from 'vue'
  6. const Flags = {
  7. EDIT: 0b10,
  8. // 已经保存,是最新的
  9. NOW: 0b100,
  10. // 可写模式,用户已登陆
  11. LOGIN: 0b1000,
  12. } as const
  13. const mode = ref<number>(Flags.NOW)
  14. export const isEdit = computed(() => !!(mode.value & Flags.EDIT))
  15. export const isLogin = computed(() => !!(mode.value & Flags.LOGIN))
  16. export const isOld = computed(() => !(mode.value & Flags.NOW))
  17. export const isNow = computed(() => !!(mode.value & Flags.NOW))
  18. export const title = '多元融合'
  19. export const appEl = ref<HTMLDivElement | null>(null)
  20. let currentTempIndex = 0
  21. export const isTemploraryID = (id: string) => id.includes('__currentTempIndex__')
  22. export const createTemploraryID = () => `__currentTempIndex__${currentTempIndex++}`
  23. export const sysBus = asyncBusFactory<{ save: void; leave: void }>()
  24. // 进入编辑界面
  25. export const enterEdit = (cb?: () => void) => {
  26. mode.value |= Flags.EDIT
  27. cb && sysBus.on('leave', cb)
  28. }
  29. export const enterOld = (cb?: () => void) => {
  30. mode.value &= ~Flags.NOW
  31. cb && sysBus.on('save', cb)
  32. }
  33. // 放弃保存内容
  34. export const giveupSave = () => {
  35. sysBus.off('save')
  36. mode.value |= Flags.NOW
  37. }
  38. // 放弃编辑内容
  39. export const giveupLeave = () => {
  40. giveupSave()
  41. sysBus.off('leave')
  42. mode.value &= ~Flags.EDIT
  43. }
  44. // 保存
  45. export const save = async () => {
  46. await sysBus.emit('save')
  47. giveupSave()
  48. leave()
  49. }
  50. // 离开
  51. export const leave = async () => {
  52. if (isOld.value && !(await Dialog.confirm('您有操作未保存,确定要退出吗?'))) {
  53. return;
  54. }
  55. await sysBus.emit('leave')
  56. giveupLeave()
  57. }
  58. export type AutoSetModeSetting<T> = {
  59. save: () => any
  60. leave?: () => any
  61. isUpdate?: (newCurrent: UnwrapRef<T>, oldCurrent?: UnwrapRef<T>) => boolean
  62. auto?: boolean
  63. backup?: () => void
  64. recovery?: () => void
  65. }
  66. let isUnset = false
  67. export const unSetModelUpdate = (run: () => void) => {
  68. console.error('unset')
  69. isUnset = true
  70. run()
  71. nextTick(() => isUnset = false)
  72. }
  73. export const autoSetModeCallback = <T extends object>(current: T, setting: AutoSetModeSetting<T>) => {
  74. let isSave = false
  75. const leaveCallback = (setting.recovery || setting.backup)
  76. && (() => {
  77. setting.recovery && setting.recovery()
  78. setting.backup && setting.backup()
  79. setting.leave && setting.leave()
  80. })
  81. const saveCallback = async () => {
  82. leaveCallback && sysBus.off('leave', leaveCallback, { last: true })
  83. isSave = true
  84. await setting.save()
  85. setting.backup && setting.backup()
  86. isSave = false
  87. }
  88. const handler = (newv: UnwrapRef<T>, oldv?: UnwrapRef<T>) => {
  89. if (isSave || isUnset) return
  90. if (!setting.isUpdate || setting.isUpdate(newv, oldv)) {
  91. isEdit.value || enterEdit()
  92. isOld.value || enterOld()
  93. saveCallback && sysBus.on('save', saveCallback, { last: true })
  94. }
  95. leaveCallback && sysBus.on('leave', leaveCallback, { last: true })
  96. }
  97. return () => {
  98. setting.backup && setting.backup()
  99. return watch(current as UnwrapRef<T>, handler, { deep: true })
  100. }
  101. }
  102. export const useAutoSetMode = <T extends object>(current: T, setting: AutoSetModeSetting<T>) => {
  103. const startWatch = autoSetModeCallback(current, setting)
  104. useViewStack(startWatch)
  105. }