drawer-api.ts 3.3 KB

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