drawer-api.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. header: true,
  34. isOpen: false,
  35. loading: false,
  36. modal: true,
  37. openAutoFocus: false,
  38. placement: 'right',
  39. showCancelButton: true,
  40. showConfirmButton: true,
  41. title: '',
  42. };
  43. this.store = new Store<DrawerState>(
  44. {
  45. ...defaultState,
  46. ...storeState,
  47. },
  48. {
  49. onUpdate: () => {
  50. const state = this.store.state;
  51. if (state?.isOpen === this.state?.isOpen) {
  52. this.state = state;
  53. } else {
  54. this.state = state;
  55. this.api.onOpenChange?.(!!state?.isOpen);
  56. }
  57. },
  58. },
  59. );
  60. this.state = this.store.state;
  61. this.api = {
  62. onBeforeClose,
  63. onCancel,
  64. onConfirm,
  65. onOpenChange,
  66. };
  67. bindMethods(this);
  68. }
  69. // 如果需要多次更新状态,可以使用 batch 方法
  70. batchStore(cb: () => void) {
  71. this.store.batch(cb);
  72. }
  73. /**
  74. * 关闭弹窗
  75. */
  76. close() {
  77. // 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗
  78. // 如果 onBeforeClose 返回 false,则不关闭弹窗
  79. const allowClose = this.api.onBeforeClose?.() ?? true;
  80. if (allowClose) {
  81. this.store.setState((prev) => ({ ...prev, isOpen: false }));
  82. }
  83. }
  84. getData<T extends object = Record<string, any>>() {
  85. return (this.sharedData?.payload ?? {}) as T;
  86. }
  87. /**
  88. * 取消操作
  89. */
  90. onCancel() {
  91. if (this.api.onCancel) {
  92. this.api.onCancel?.();
  93. } else {
  94. this.close();
  95. }
  96. }
  97. /**
  98. * 确认操作
  99. */
  100. onConfirm() {
  101. this.api.onConfirm?.();
  102. }
  103. open() {
  104. this.store.setState((prev) => ({ ...prev, isOpen: true }));
  105. }
  106. setData<T>(payload: T) {
  107. this.sharedData.payload = payload;
  108. }
  109. setState(
  110. stateOrFn:
  111. | ((prev: DrawerState) => Partial<DrawerState>)
  112. | Partial<DrawerState>,
  113. ) {
  114. if (isFunction(stateOrFn)) {
  115. this.store.setState(stateOrFn);
  116. } else {
  117. this.store.setState((prev) => ({ ...prev, ...stateOrFn }));
  118. }
  119. }
  120. }