modal-api.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import type { ModalApiOptions, ModalState } from './modal';
  2. import { Store } from '@vben-core/shared/store';
  3. import { bindMethods, isFunction } from '@vben-core/shared/utils';
  4. export class ModalApi {
  5. private api: Pick<
  6. ModalApiOptions,
  7. 'onBeforeClose' | 'onCancel' | 'onConfirm' | 'onOpenChange'
  8. >;
  9. // private prevState!: ModalState;
  10. private state!: ModalState;
  11. // 共享数据
  12. public sharedData: Record<'payload', any> = {
  13. payload: {},
  14. };
  15. public store: Store<ModalState>;
  16. constructor(options: ModalApiOptions = {}) {
  17. const {
  18. connectedComponent: _,
  19. onBeforeClose,
  20. onCancel,
  21. onConfirm,
  22. onOpenChange,
  23. ...storeState
  24. } = options;
  25. const defaultState: ModalState = {
  26. centered: false,
  27. class: '',
  28. closeOnClickModal: true,
  29. closeOnPressEscape: true,
  30. confirmLoading: false,
  31. contentClass: '',
  32. draggable: false,
  33. footer: true,
  34. footerClass: '',
  35. fullscreen: false,
  36. fullscreenButton: true,
  37. header: true,
  38. headerClass: '',
  39. isOpen: false,
  40. loading: false,
  41. modal: true,
  42. openAutoFocus: false,
  43. showCancelButton: true,
  44. showConfirmButton: true,
  45. title: '',
  46. };
  47. this.store = new Store<ModalState>(
  48. {
  49. ...defaultState,
  50. ...storeState,
  51. },
  52. {
  53. onUpdate: () => {
  54. const state = this.store.state;
  55. // 每次更新状态时,都会调用 onOpenChange 回调函数
  56. if (state?.isOpen === this.state?.isOpen) {
  57. this.state = state;
  58. } else {
  59. this.state = state;
  60. this.api.onOpenChange?.(!!state?.isOpen);
  61. }
  62. },
  63. },
  64. );
  65. this.state = this.store.state;
  66. this.api = {
  67. onBeforeClose,
  68. onCancel,
  69. onConfirm,
  70. onOpenChange,
  71. };
  72. bindMethods(this);
  73. }
  74. // 如果需要多次更新状态,可以使用 batch 方法
  75. batchStore(cb: () => void) {
  76. this.store.batch(cb);
  77. }
  78. /**
  79. * 关闭弹窗
  80. */
  81. close() {
  82. // 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗
  83. // 如果 onBeforeClose 返回 false,则不关闭弹窗
  84. const allowClose = this.api.onBeforeClose?.() ?? true;
  85. if (allowClose) {
  86. this.store.setState((prev) => ({ ...prev, isOpen: false }));
  87. }
  88. }
  89. getData<T extends object = Record<string, any>>() {
  90. return (this.sharedData?.payload ?? {}) as T;
  91. }
  92. /**
  93. * 取消操作
  94. */
  95. onCancel() {
  96. if (this.api.onCancel) {
  97. this.api.onCancel?.();
  98. } else {
  99. this.close();
  100. }
  101. }
  102. /**
  103. * 确认操作
  104. */
  105. onConfirm() {
  106. this.api.onConfirm?.();
  107. }
  108. open() {
  109. this.store.setState((prev) => ({ ...prev, isOpen: true }));
  110. }
  111. setData<T>(payload: T) {
  112. this.sharedData.payload = payload;
  113. }
  114. setState(
  115. stateOrFn:
  116. | ((prev: ModalState) => Partial<ModalState>)
  117. | Partial<ModalState>,
  118. ) {
  119. if (isFunction(stateOrFn)) {
  120. this.store.setState(stateOrFn);
  121. } else {
  122. this.store.setState((prev) => ({ ...prev, ...stateOrFn }));
  123. }
  124. }
  125. }