import type { DrawerApiOptions, DrawerState } from './drawer'; import { Store } from '@vben-core/shared/store'; import { bindMethods, isFunction } from '@vben-core/shared/utils'; export class DrawerApi { private api: Pick< DrawerApiOptions, | 'onBeforeClose' | 'onCancel' | 'onClosed' | 'onConfirm' | 'onOpenChange' | 'onOpened' >; // private prevState!: DrawerState; private state!: DrawerState; // 共享数据 public sharedData: Record<'payload', any> = { payload: {}, }; public store: Store; constructor(options: DrawerApiOptions = {}) { const { connectedComponent: _, onBeforeClose, onCancel, onClosed, onConfirm, onOpenChange, onOpened, ...storeState } = options; const defaultState: DrawerState = { class: '', closable: true, closeOnClickModal: true, closeOnPressEscape: true, confirmLoading: false, contentClass: '', footer: true, header: true, isOpen: false, loading: false, modal: true, openAutoFocus: false, placement: 'right', showCancelButton: true, showConfirmButton: true, title: '', }; this.store = new Store( { ...defaultState, ...storeState, }, { onUpdate: () => { const state = this.store.state; if (state?.isOpen === this.state?.isOpen) { this.state = state; } else { this.state = state; this.api.onOpenChange?.(!!state?.isOpen); } }, }, ); this.state = this.store.state; this.api = { onBeforeClose, onCancel, onClosed, onConfirm, onOpenChange, onOpened, }; bindMethods(this); } // 如果需要多次更新状态,可以使用 batch 方法 batchStore(cb: () => void) { this.store.batch(cb); } /** * 关闭弹窗 */ close() { // 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗 // 如果 onBeforeClose 返回 false,则不关闭弹窗 const allowClose = this.api.onBeforeClose?.() ?? true; if (allowClose) { this.store.setState((prev) => ({ ...prev, isOpen: false })); } } getData>() { return (this.sharedData?.payload ?? {}) as T; } /** * 取消操作 */ onCancel() { if (this.api.onCancel) { this.api.onCancel?.(); } else { this.close(); } } /** * 弹窗关闭动画播放完毕后的回调 */ onClosed() { if (!this.state.isOpen) { this.api.onClosed?.(); } } /** * 确认操作 */ onConfirm() { this.api.onConfirm?.(); } /** * 弹窗打开动画播放完毕后的回调 */ onOpened() { if (this.state.isOpen) { this.api.onOpened?.(); } } open() { this.store.setState((prev) => ({ ...prev, isOpen: true })); } setData(payload: T) { this.sharedData.payload = payload; } setState( stateOrFn: | ((prev: DrawerState) => Partial) | Partial, ) { if (isFunction(stateOrFn)) { this.store.setState(stateOrFn); } else { this.store.setState((prev) => ({ ...prev, ...stateOrFn })); } } }