sys.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import { ref, computed, watch, nextTick, watchEffect } 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. import { currentMeta } from "@/router";
  7. import { ui18n } from "@/lang";
  8. const Flags = {
  9. EDIT: 0b10,
  10. // 已经保存,是最新的
  11. NOW: 0b100,
  12. // 可写模式,用户已登陆
  13. LOGIN: 0b1000,
  14. } as const;
  15. const mode = ref<number>(Flags.NOW);
  16. export const isEdit = computed(() => !!(mode.value & Flags.EDIT));
  17. export const isLogin = computed(() => !!(mode.value & Flags.LOGIN));
  18. export const isOld = computed(() => !(mode.value & Flags.NOW));
  19. export const isNow = computed(() => !!(mode.value & Flags.NOW));
  20. export const appEl = ref<HTMLDivElement | null>(null);
  21. export const prefix = ref("");
  22. export const defTitle = ref(ui18n.t('case.name'));
  23. export const title = computed(() => {
  24. console.error(currentMeta.value);
  25. const last =
  26. currentMeta.value && "sysTitle" in currentMeta.value
  27. ? currentMeta.value.sysTitle
  28. : defTitle.value;
  29. console.error(prefix.value);
  30. if (prefix.value && last) {
  31. return prefix.value + " | " + last;
  32. } else {
  33. return prefix.value + last;
  34. }
  35. });
  36. watchEffect(() => (document.title = title.value));
  37. let currentTempIndex = 0;
  38. export const isTemploraryID = (id: string) =>
  39. id.includes("__currentTempIndex__");
  40. export const createTemploraryID = () =>
  41. `__currentTempIndex__${currentTempIndex++}`;
  42. export const sysBus = asyncBusFactory<{ save: void; leave: void }>();
  43. // 进入编辑界面
  44. export const enterEdit = (cb?: () => void) => {
  45. mode.value |= Flags.EDIT;
  46. cb && sysBus.on("leave", cb);
  47. };
  48. export const enterOld = (cb?: () => void) => {
  49. mode.value &= ~Flags.NOW;
  50. cb && sysBus.on("save", cb);
  51. };
  52. // 放弃保存内容
  53. export const giveupSave = () => {
  54. sysBus.off("save");
  55. mode.value |= Flags.NOW;
  56. };
  57. // 放弃编辑内容
  58. export const giveupLeave = () => {
  59. giveupSave();
  60. sysBus.off("leave");
  61. mode.value &= ~Flags.EDIT;
  62. };
  63. // 保存
  64. export const save = async () => {
  65. await sysBus.emit("save");
  66. giveupSave();
  67. leave();
  68. };
  69. // 离开
  70. export const leave = async () => {
  71. if (
  72. isOld.value &&
  73. !(await Dialog.confirm(ui18n.t('sys.unSaveMsg')))
  74. ) {
  75. return;
  76. }
  77. await sysBus.emit("leave");
  78. giveupLeave();
  79. };
  80. export type AutoSetModeSetting<T> = {
  81. save: () => any;
  82. leave?: () => any;
  83. isUpdate?: (newCurrent: UnwrapRef<T>, oldCurrent?: UnwrapRef<T>) => boolean;
  84. auto?: boolean;
  85. backup?: () => void;
  86. recovery?: () => void;
  87. };
  88. let isUnset = false;
  89. export const unSetModelUpdate = (run: () => void) => {
  90. isUnset = true;
  91. run();
  92. nextTick(() => (isUnset = false));
  93. };
  94. export const autoSetModeCallback = <T extends object>(
  95. current: T,
  96. setting: AutoSetModeSetting<T>,
  97. last = true
  98. ) => {
  99. let isLeaveIng = false;
  100. let isSave = false;
  101. const leaveCallback =
  102. (setting.recovery || setting.backup) &&
  103. (async () => {
  104. isLeaveIng = true;
  105. setting.recovery && (await setting.recovery());
  106. // setting.backup && (await setting.backup());
  107. setting.leave && (await setting.leave());
  108. isLeaveIng = false;
  109. });
  110. const saveCallback = async () => {
  111. leaveCallback && sysBus.off("leave", leaveCallback, { last });
  112. isSave = true;
  113. try {
  114. await setting.save();
  115. setting.backup && setting.backup();
  116. isSave = false;
  117. } catch (e) {
  118. isSave = false;
  119. throw e;
  120. }
  121. };
  122. const handler = (newv: UnwrapRef<T>, oldv?: UnwrapRef<T>) => {
  123. if (isSave || isUnset || isLeaveIng) return;
  124. if (!setting.isUpdate || setting.isUpdate(newv, oldv)) {
  125. isEdit.value || enterEdit();
  126. isOld.value || enterOld();
  127. saveCallback && sysBus.on("save", saveCallback, { last });
  128. }
  129. leaveCallback && sysBus.on("leave", leaveCallback, { last });
  130. };
  131. return () => {
  132. setting.backup && setting.backup();
  133. return watch(current as any, handler, { deep: true });
  134. };
  135. };
  136. export const useAutoSetMode = <T extends object>(
  137. current: T,
  138. setting: AutoSetModeSetting<T>,
  139. last = true
  140. ) => {
  141. const startWatch = autoSetModeCallback(current, setting, last);
  142. useViewStack(startWatch);
  143. };