vben
2021-08-24 56a966cfbf8db5b29a42185f0f25a0e800c30dbb
提交 | 用户 | age
ebf7c8 1 <template>
f750ff 2   <Modal v-bind="getBindValue" @cancel="handleCancel">
ebf7c8 3     <template #closeIcon v-if="!$slots.closeIcon">
V 4       <ModalClose
5         :canFullscreen="getProps.canFullscreen"
6         :fullScreen="fullScreenRef"
7         @cancel="handleCancel"
8         @fullscreen="handleFullScreen"
9       />
10     </template>
11
12     <template #title v-if="!$slots.title">
e3851d 13       <ModalHeader
V 14         :helpMessage="getProps.helpMessage"
15         :title="getMergeProps.title"
16         @dblclick="handleTitleDbClick"
17       />
ebf7c8 18     </template>
V 19
20     <template #footer v-if="!$slots.footer">
ae7821 21       <ModalFooter v-bind="getBindValue" @ok="handleOk" @cancel="handleCancel">
18ad1b 22         <template #[item]="data" v-for="item in Object.keys($slots)">
b1f317 23           <slot :name="item" v-bind="data || {}"></slot>
18ad1b 24         </template>
V 25       </ModalFooter>
ebf7c8 26     </template>
3b126e 27
ebf7c8 28     <ModalWrapper
V 29       :useWrapper="getProps.useWrapper"
30       :footerOffset="wrapperFooterOffset"
31       :fullScreen="fullScreenRef"
32       ref="modalWrapperRef"
33       :loading="getProps.loading"
23568b 34       :loading-tip="getProps.loadingTip"
5091a8 35       :minHeight="getProps.minHeight"
37508c 36       :height="getWrapperHeight"
ebf7c8 37       :visible="visibleRef"
V 38       :modalFooterHeight="footer !== undefined && !footer ? 0 : undefined"
c9089c 39       v-bind="omit(getProps.wrapperProps, 'visible', 'height', 'modalFooterHeight')"
ebf7c8 40       @ext-height="handleExtHeight"
V 41       @height-change="handleHeightChange"
42     >
9edc28 43       <slot></slot>
ebf7c8 44     </ModalWrapper>
3b126e 45
V 46     <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
5138e4 47       <slot :name="item" v-bind="data || {}"></slot>
3b126e 48     </template>
ebf7c8 49   </Modal>
V 50 </template>
51 <script lang="ts">
1c1755 52   import type { ModalProps, ModalMethods } from './typing';
ebf7c8 53
V 54   import {
55     defineComponent,
56     computed,
57     ref,
58     watch,
59     unref,
60     watchEffect,
61     toRef,
62     getCurrentInstance,
a3a903 63     nextTick,
ebf7c8 64   } from 'vue';
V 65   import Modal from './components/Modal';
66   import ModalWrapper from './components/ModalWrapper.vue';
67   import ModalClose from './components/ModalClose.vue';
68   import ModalFooter from './components/ModalFooter.vue';
69   import ModalHeader from './components/ModalHeader.vue';
70   import { isFunction } from '/@/utils/is';
71   import { deepMerge } from '/@/utils';
72   import { basicProps } from './props';
73   import { useFullScreen } from './hooks/useModalFullScreen';
74   import { omit } from 'lodash-es';
1c1755 75
ebf7c8 76   export default defineComponent({
V 77     name: 'BasicModal',
78     components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
9edc28 79     inheritAttrs: false,
ebf7c8 80     props: basicProps,
de12ba 81     emits: ['visible-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible'],
ebf7c8 82     setup(props, { emit, attrs }) {
V 83       const visibleRef = ref(false);
84       const propsRef = ref<Partial<ModalProps> | null>(null);
ae7821 85       const modalWrapperRef = ref<any>(null);
a3a903 86
ebf7c8 87       // modal   Bottom and top height
V 88       const extHeightRef = ref(0);
89       const modalMethods: ModalMethods = {
90         setModalProps,
91         emitVisible: undefined,
a3a903 92         redoModalHeight: () => {
V 93           nextTick(() => {
94             if (unref(modalWrapperRef)) {
95               (unref(modalWrapperRef) as any).setModalHeight();
96             }
97           });
98         },
ebf7c8 99       };
a3a903 100
ebf7c8 101       const instance = getCurrentInstance();
V 102       if (instance) {
103         emit('register', modalMethods, instance.uid);
104       }
105
106       // Custom title component: get title
e15b4f 107       const getMergeProps = computed((): Recordable => {
00fca0 108         return {
V 109           ...props,
110           ...(unref(propsRef) as any),
111         };
112       });
ebf7c8 113
V 114       const { handleFullScreen, getWrapClassName, fullScreenRef } = useFullScreen({
115         modalWrapperRef,
116         extHeightRef,
117         wrapClassName: toRef(getMergeProps.value, 'wrapClassName'),
118       });
119
a579b8 120       // modal component does not need title and origin buttons
e15b4f 121       const getProps = computed((): Recordable => {
00fca0 122         const opt = {
V 123           ...unref(getMergeProps),
124           visible: unref(visibleRef),
125           okButtonProps: undefined,
126           cancelButtonProps: undefined,
127           title: undefined,
128         };
129         return {
130           ...opt,
131           wrapClassName: unref(getWrapClassName),
132         };
133       });
ebf7c8 134
00fca0 135       const getBindValue = computed((): Recordable => {
5baaa5 136         const attr = {
137           ...attrs,
138           ...unref(getMergeProps),
139           visible: unref(visibleRef),
140           wrapClassName: unref(getWrapClassName),
141         };
00fca0 142         if (unref(fullScreenRef)) {
953bfc 143           return omit(attr, ['height', 'title']);
37508c 144         }
953bfc 145         return omit(attr, 'title');
00fca0 146       });
37508c 147
V 148       const getWrapperHeight = computed(() => {
149         if (unref(fullScreenRef)) return undefined;
150         return unref(getProps).height;
ebf7c8 151       });
V 152
153       watchEffect(() => {
154         visibleRef.value = !!props.visible;
efbde0 155         fullScreenRef.value = !!props.defaultFullscreen;
ebf7c8 156       });
V 157
158       watch(
159         () => unref(visibleRef),
160         (v) => {
161           emit('visible-change', v);
de12ba 162           emit('update:visible', v);
ebf7c8 163           instance && modalMethods.emitVisible?.(v, instance.uid);
a3a903 164           nextTick(() => {
V 165             if (props.scrollTop && v && unref(modalWrapperRef)) {
166               (unref(modalWrapperRef) as any).scrollTop();
167             }
168           });
ebf7c8 169         },
V 170         {
171           immediate: false,
56a966 172         },
ebf7c8 173       );
V 174
175       // 取消事件
176       async function handleCancel(e: Event) {
177         e?.stopPropagation();
178
179         if (props.closeFunc && isFunction(props.closeFunc)) {
180           const isClose: boolean = await props.closeFunc();
181           visibleRef.value = !isClose;
182           return;
183         }
184
185         visibleRef.value = false;
de12ba 186         emit('cancel', e);
ebf7c8 187       }
V 188
189       /**
190        * @description: 设置modal参数
191        */
192       function setModalProps(props: Partial<ModalProps>): void {
193         // Keep the last setModalProps
fa828f 194         propsRef.value = deepMerge(unref(propsRef) || ({} as any), props);
c7de65 195         if (Reflect.has(props, 'visible')) {
196           visibleRef.value = !!props.visible;
197         }
198         if (Reflect.has(props, 'defaultFullscreen')) {
199           fullScreenRef.value = !!props.defaultFullscreen;
200         }
ebf7c8 201       }
V 202
de12ba 203       function handleOk(e: Event) {
204         emit('ok', e);
ebf7c8 205       }
V 206
207       function handleHeightChange(height: string) {
208         emit('height-change', height);
209       }
210
211       function handleExtHeight(height: number) {
212         extHeightRef.value = height;
213       }
214
e15b4f 215       function handleTitleDbClick(e) {
e3851d 216         if (!props.canFullscreen) return;
V 217         e.stopPropagation();
218         handleFullScreen(e);
219       }
220
ebf7c8 221       return {
V 222         handleCancel,
223         getBindValue,
224         getProps,
225         handleFullScreen,
226         fullScreenRef,
227         getMergeProps,
228         handleOk,
229         visibleRef,
230         omit,
231         modalWrapperRef,
232         handleExtHeight,
233         handleHeightChange,
e3851d 234         handleTitleDbClick,
37508c 235         getWrapperHeight,
ebf7c8 236       };
V 237     },
238   });
239 </script>