import type { UseDrawerReturnType, DrawerInstance, ReturnMethods, DrawerProps, UseDrawerInnerReturnType, } from './types'; import { ref, getCurrentInstance, unref, reactive, watchEffect, nextTick, toRaw, computed, } from 'vue'; import { isProdMode } from '/@/utils/env'; import { isFunction } from '/@/utils/is'; import { tryOnUnmounted, isInSetup } from '/@/utils/helper/vueHelper'; import { isEqual } from 'lodash-es'; import { error } from '/@/utils/log'; const dataTransferRef = reactive({}); const visibleData = reactive<{ [key: number]: boolean }>({}); /** * @description: Applicable to separate drawer and call outside */ export function useDrawer(): UseDrawerReturnType { isInSetup(); const drawerRef = ref(null); const loadedRef = ref>(false); const uidRef = ref(''); function register(drawerInstance: DrawerInstance, uuid: string) { isProdMode() && tryOnUnmounted(() => { drawerRef.value = null; loadedRef.value = null; dataTransferRef[unref(uidRef)] = null; }); if (unref(loadedRef) && isProdMode() && drawerInstance === unref(drawerRef)) { return; } uidRef.value = uuid; drawerRef.value = drawerInstance; loadedRef.value = true; drawerInstance.emitVisible = (visible: boolean, uid: number) => { visibleData[uid] = visible; }; } const getInstance = () => { const instance = unref(drawerRef); if (!instance) { error('useDrawer instance is undefined!'); } return instance; }; const methods: ReturnMethods = { setDrawerProps: (props: Partial): void => { getInstance()?.setDrawerProps(props); }, getVisible: computed((): boolean => { return visibleData[~~unref(uidRef)]; }), openDrawer: (visible = true, data?: T, openOnSet = true): void => { getInstance()?.setDrawerProps({ visible: visible, }); if (!data) return; if (openOnSet) { dataTransferRef[unref(uidRef)] = null; dataTransferRef[unref(uidRef)] = data; return; } const equal = isEqual(toRaw(dataTransferRef[unref(uidRef)]), data); if (!equal) { dataTransferRef[unref(uidRef)] = data; } }, }; return [register, methods]; } export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => { const drawerInstanceRef = ref>(null); const currentInstance = getCurrentInstance(); const uidRef = ref(''); if (!currentInstance) { error('useDrawerInner instance is undefined!'); } const getInstance = () => { const instance = unref(drawerInstanceRef); if (!instance) { error('useDrawerInner instance is undefined!'); return; } return instance; }; const register = (modalInstance: DrawerInstance, uuid: string) => { isProdMode() && tryOnUnmounted(() => { drawerInstanceRef.value = null; }); uidRef.value = uuid; drawerInstanceRef.value = modalInstance; currentInstance?.emit('register', modalInstance, uuid); }; watchEffect(() => { const data = dataTransferRef[unref(uidRef)]; if (!data) return; if (!callbackFn || !isFunction(callbackFn)) return; nextTick(() => { callbackFn(data); }); }); return [ register, { changeLoading: (loading = true) => { getInstance()?.setDrawerProps({ loading }); }, changeOkLoading: (loading = true) => { getInstance()?.setDrawerProps({ confirmLoading: loading }); }, getVisible: computed((): boolean => { return visibleData[~~unref(uidRef)]; }), closeDrawer: () => { getInstance()?.setDrawerProps({ visible: false }); }, setDrawerProps: (props: Partial) => { getInstance()?.setDrawerProps(props); }, }, ]; };