vben
2023-04-05 8e5a6b7ce547ba8edb1d767bb4d820f3b66ff95a
提交 | 用户 | age
2f6253 1 import type {
2   UseModalReturnType,
3   ModalMethods,
4   ModalProps,
5   ReturnMethods,
6   UseModalInnerReturnType,
1c1755 7 } from '../typing';
81baf1 8 import {
V 9   ref,
10   onUnmounted,
11   unref,
12   getCurrentInstance,
13   reactive,
14   watchEffect,
15   nextTick,
16   toRaw,
8e5a6b 17   computed,
81baf1 18 } from 'vue';
2f6253 19 import { isProdMode } from '/@/utils/env';
84c9d7 20 import { isFunction } from '/@/utils/is';
81baf1 21 import { isEqual } from 'lodash-es';
2c6aa8 22 import { tryOnUnmounted } from '@vueuse/core';
ebf7c8 23 import { error } from '/@/utils/log';
1c1755 24
V 25 const dataTransfer = reactive<any>({});
ebf7c8 26
V 27 const visibleData = reactive<{ [key: number]: boolean }>({});
2f6253 28
29 /**
30  * @description: Applicable to independent modal and call outside
31  */
32 export function useModal(): UseModalReturnType {
1c1755 33   const modal = ref<Nullable<ModalMethods>>(null);
V 34   const loaded = ref<Nullable<boolean>>(false);
35   const uid = ref<string>('');
81baf1 36
2f6253 37   function register(modalMethod: ModalMethods, uuid: string) {
1c1755 38     if (!getCurrentInstance()) {
V 39       throw new Error('useModal() can only be used inside setup() or functional components!');
40     }
41     uid.value = uuid;
2f6253 42     isProdMode() &&
43       onUnmounted(() => {
1c1755 44         modal.value = null;
V 45         loaded.value = false;
46         dataTransfer[unref(uid)] = null;
2f6253 47       });
1c1755 48     if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return;
fb0c77 49
1c1755 50     modal.value = modalMethod;
95aca2 51     loaded.value = true;
ebf7c8 52     modalMethod.emitVisible = (visible: boolean, uid: number) => {
V 53       visibleData[uid] = visible;
54     };
2f6253 55   }
0692b4 56
2f6253 57   const getInstance = () => {
1c1755 58     const instance = unref(modal);
2f6253 59     if (!instance) {
ebf7c8 60       error('useModal instance is undefined!');
2f6253 61     }
62     return instance;
63   };
64
65   const methods: ReturnMethods = {
66     setModalProps: (props: Partial<ModalProps>): void => {
ebf7c8 67       getInstance()?.setModalProps(props);
2f6253 68     },
a3a903 69
ebf7c8 70     getVisible: computed((): boolean => {
1c1755 71       return visibleData[~~unref(uid)];
ebf7c8 72     }),
fb0c77 73
a3a903 74     redoModalHeight: () => {
V 75       getInstance()?.redoModalHeight?.();
76     },
77
f646e3 78     openModal: <T = any>(visible = true, data?: T, openOnSet = true): void => {
ebf7c8 79       getInstance()?.setModalProps({
2f6253 80         visible: visible,
81       });
0692b4 82
81baf1 83       if (!data) return;
1c1755 84       const id = unref(uid);
81baf1 85       if (openOnSet) {
1c1755 86         dataTransfer[id] = null;
V 87         dataTransfer[id] = toRaw(data);
81baf1 88         return;
V 89       }
1c1755 90       const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data));
81baf1 91       if (!equal) {
1c1755 92         dataTransfer[id] = toRaw(data);
b6d5e5 93       }
2f6253 94     },
6d5f9a 95
96     closeModal: () => {
97       getInstance()?.setModalProps({ visible: false });
98     },
2f6253 99   };
100   return [register, methods];
101 }
102
84c9d7 103 export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
81baf1 104   const modalInstanceRef = ref<Nullable<ModalMethods>>(null);
ebf7c8 105   const currentInstance = getCurrentInstance();
2f6253 106   const uidRef = ref<string>('');
1293a7 107
2f6253 108   const getInstance = () => {
109     const instance = unref(modalInstanceRef);
110     if (!instance) {
ebf7c8 111       error('useModalInner instance is undefined!');
2f6253 112     }
113     return instance;
114   };
fb0c77 115
2f6253 116   const register = (modalInstance: ModalMethods, uuid: string) => {
81baf1 117     isProdMode() &&
V 118       tryOnUnmounted(() => {
119         modalInstanceRef.value = null;
120       });
2f6253 121     uidRef.value = uuid;
122     modalInstanceRef.value = modalInstance;
ebf7c8 123     currentInstance?.emit('register', modalInstance, uuid);
2f6253 124   };
fb0c77 125
84c9d7 126   watchEffect(() => {
1c1755 127     const data = dataTransfer[unref(uidRef)];
84c9d7 128     if (!data) return;
V 129     if (!callbackFn || !isFunction(callbackFn)) return;
5832ee 130     nextTick(() => {
V 131       callbackFn(data);
132     });
84c9d7 133   });
V 134
2f6253 135   return [
136     register,
137     {
138       changeLoading: (loading = true) => {
ebf7c8 139         getInstance()?.setModalProps({ loading });
2f6253 140       },
ebf7c8 141       getVisible: computed((): boolean => {
V 142         return visibleData[~~unref(uidRef)];
143       }),
fb0c77 144
2f6253 145       changeOkLoading: (loading = true) => {
ebf7c8 146         getInstance()?.setModalProps({ confirmLoading: loading });
2f6253 147       },
fb0c77 148
2f6253 149       closeModal: () => {
ebf7c8 150         getInstance()?.setModalProps({ visible: false });
2f6253 151       },
fb0c77 152
2f6253 153       setModalProps: (props: Partial<ModalProps>) => {
ebf7c8 154         getInstance()?.setModalProps(props);
2f6253 155       },
f732b5 156
157       redoModalHeight: () => {
158         const callRedo = getInstance()?.redoModalHeight;
159         callRedo && callRedo();
160       },
2f6253 161     },
162   ];
163 };