Vben
2021-06-11 1c1755cf5b4ada7263c05ddf4105abb52a2abb2f
提交 | 用户 | 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,
17 } from 'vue';
2f6253 18 import { isProdMode } from '/@/utils/env';
84c9d7 19 import { isFunction } from '/@/utils/is';
81baf1 20 import { isEqual } from 'lodash-es';
2c6aa8 21 import { tryOnUnmounted } from '@vueuse/core';
ebf7c8 22 import { error } from '/@/utils/log';
V 23 import { computed } from 'vue';
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;
ebf7c8 51     modalMethod.emitVisible = (visible: boolean, uid: number) => {
V 52       visibleData[uid] = visible;
53     };
2f6253 54   }
0692b4 55
2f6253 56   const getInstance = () => {
1c1755 57     const instance = unref(modal);
2f6253 58     if (!instance) {
ebf7c8 59       error('useModal instance is undefined!');
2f6253 60     }
61     return instance;
62   };
63
64   const methods: ReturnMethods = {
65     setModalProps: (props: Partial<ModalProps>): void => {
ebf7c8 66       getInstance()?.setModalProps(props);
2f6253 67     },
a3a903 68
ebf7c8 69     getVisible: computed((): boolean => {
1c1755 70       return visibleData[~~unref(uid)];
ebf7c8 71     }),
fb0c77 72
a3a903 73     redoModalHeight: () => {
V 74       getInstance()?.redoModalHeight?.();
75     },
76
f646e3 77     openModal: <T = any>(visible = true, data?: T, openOnSet = true): void => {
ebf7c8 78       getInstance()?.setModalProps({
2f6253 79         visible: visible,
80       });
0692b4 81
81baf1 82       if (!data) return;
1c1755 83       const id = unref(uid);
81baf1 84       if (openOnSet) {
1c1755 85         dataTransfer[id] = null;
V 86         dataTransfer[id] = toRaw(data);
81baf1 87         return;
V 88       }
1c1755 89       const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data));
81baf1 90       if (!equal) {
1c1755 91         dataTransfer[id] = toRaw(data);
b6d5e5 92       }
2f6253 93     },
6d5f9a 94
95     closeModal: () => {
96       getInstance()?.setModalProps({ visible: false });
97     },
2f6253 98   };
99   return [register, methods];
100 }
101
84c9d7 102 export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
81baf1 103   const modalInstanceRef = ref<Nullable<ModalMethods>>(null);
ebf7c8 104   const currentInstance = getCurrentInstance();
2f6253 105   const uidRef = ref<string>('');
1293a7 106
2f6253 107   const getInstance = () => {
108     const instance = unref(modalInstanceRef);
109     if (!instance) {
ebf7c8 110       error('useModalInner instance is undefined!');
2f6253 111     }
112     return instance;
113   };
fb0c77 114
2f6253 115   const register = (modalInstance: ModalMethods, uuid: string) => {
81baf1 116     isProdMode() &&
V 117       tryOnUnmounted(() => {
118         modalInstanceRef.value = null;
119       });
2f6253 120     uidRef.value = uuid;
121     modalInstanceRef.value = modalInstance;
ebf7c8 122     currentInstance?.emit('register', modalInstance, uuid);
2f6253 123   };
fb0c77 124
84c9d7 125   watchEffect(() => {
1c1755 126     const data = dataTransfer[unref(uidRef)];
84c9d7 127     if (!data) return;
V 128     if (!callbackFn || !isFunction(callbackFn)) return;
5832ee 129     nextTick(() => {
V 130       callbackFn(data);
131     });
84c9d7 132   });
V 133
2f6253 134   return [
135     register,
136     {
137       changeLoading: (loading = true) => {
ebf7c8 138         getInstance()?.setModalProps({ loading });
2f6253 139       },
ebf7c8 140       getVisible: computed((): boolean => {
V 141         return visibleData[~~unref(uidRef)];
142       }),
fb0c77 143
2f6253 144       changeOkLoading: (loading = true) => {
ebf7c8 145         getInstance()?.setModalProps({ confirmLoading: loading });
2f6253 146       },
fb0c77 147
2f6253 148       closeModal: () => {
ebf7c8 149         getInstance()?.setModalProps({ visible: false });
2f6253 150       },
fb0c77 151
2f6253 152       setModalProps: (props: Partial<ModalProps>) => {
ebf7c8 153         getInstance()?.setModalProps(props);
2f6253 154       },
f732b5 155
156       redoModalHeight: () => {
157         const callRedo = getInstance()?.redoModalHeight;
158         callRedo && callRedo();
159       },
2f6253 160     },
161   ];
162 };