modal-api.ts 2.8 KB

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