drawer-api.ts 2.8 KB

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