import type {
|
UseModalReturnType,
|
ModalMethods,
|
ModalProps,
|
ReturnMethods,
|
UseModalInnerReturnType,
|
} from '../types';
|
|
import {
|
ref,
|
onUnmounted,
|
unref,
|
getCurrentInstance,
|
reactive,
|
watchEffect,
|
nextTick,
|
toRaw,
|
} from 'vue';
|
import { isProdMode } from '/@/utils/env';
|
import { isFunction } from '/@/utils/is';
|
import { isEqual } from 'lodash-es';
|
import { tryOnUnmounted } from '@vueuse/core';
|
|
import { error } from '/@/utils/log';
|
import { computed } from 'vue';
|
const dataTransferRef = reactive<any>({});
|
|
const visibleData = reactive<{ [key: number]: boolean }>({});
|
|
/**
|
* @description: Applicable to independent modal and call outside
|
*/
|
export function useModal(): UseModalReturnType {
|
const modalRef = ref<Nullable<ModalMethods>>(null);
|
const loadedRef = ref<Nullable<boolean>>(false);
|
const uidRef = ref<string>('');
|
|
function register(modalMethod: ModalMethods, uuid: string) {
|
uidRef.value = uuid;
|
|
isProdMode() &&
|
onUnmounted(() => {
|
modalRef.value = null;
|
loadedRef.value = false;
|
dataTransferRef[unref(uidRef)] = null;
|
});
|
if (unref(loadedRef) && isProdMode() && modalMethod === unref(modalRef)) return;
|
|
modalRef.value = modalMethod;
|
modalMethod.emitVisible = (visible: boolean, uid: number) => {
|
visibleData[uid] = visible;
|
};
|
}
|
|
const getInstance = () => {
|
const instance = unref(modalRef);
|
if (!instance) {
|
error('useModal instance is undefined!');
|
}
|
return instance;
|
};
|
|
const methods: ReturnMethods = {
|
setModalProps: (props: Partial<ModalProps>): void => {
|
getInstance()?.setModalProps(props);
|
},
|
|
getVisible: computed((): boolean => {
|
return visibleData[~~unref(uidRef)];
|
}),
|
|
redoModalHeight: () => {
|
getInstance()?.redoModalHeight?.();
|
},
|
|
openModal: <T = any>(visible = true, data?: T, openOnSet = true): void => {
|
getInstance()?.setModalProps({
|
visible: visible,
|
});
|
|
if (!data) return;
|
|
if (openOnSet) {
|
dataTransferRef[unref(uidRef)] = null;
|
dataTransferRef[unref(uidRef)] = toRaw(data);
|
return;
|
}
|
const equal = isEqual(toRaw(dataTransferRef[unref(uidRef)]), toRaw(data));
|
if (!equal) {
|
dataTransferRef[unref(uidRef)] = toRaw(data);
|
}
|
},
|
|
closeModal: () => {
|
getInstance()?.setModalProps({ visible: false });
|
},
|
};
|
return [register, methods];
|
}
|
|
export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
|
const modalInstanceRef = ref<Nullable<ModalMethods>>(null);
|
const currentInstance = getCurrentInstance();
|
const uidRef = ref<string>('');
|
|
// currentInstall.type.emits = [...currentInstall.type.emits, 'register'];
|
// Object.assign(currentInstall.type.emits, ['register']);
|
|
const getInstance = () => {
|
const instance = unref(modalInstanceRef);
|
if (!instance) {
|
error('useModalInner instance is undefined!');
|
}
|
return instance;
|
};
|
|
const register = (modalInstance: ModalMethods, uuid: string) => {
|
isProdMode() &&
|
tryOnUnmounted(() => {
|
modalInstanceRef.value = null;
|
});
|
uidRef.value = uuid;
|
modalInstanceRef.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()?.setModalProps({ loading });
|
},
|
getVisible: computed((): boolean => {
|
return visibleData[~~unref(uidRef)];
|
}),
|
|
changeOkLoading: (loading = true) => {
|
getInstance()?.setModalProps({ confirmLoading: loading });
|
},
|
|
closeModal: () => {
|
getInstance()?.setModalProps({ visible: false });
|
},
|
|
setModalProps: (props: Partial<ModalProps>) => {
|
getInstance()?.setModalProps(props);
|
},
|
|
redoModalHeight: () => {
|
const callRedo = getInstance()?.redoModalHeight;
|
callRedo && callRedo();
|
},
|
},
|
];
|
};
|