Netfan
2021-05-09 a579b8456ac73ac48c6af1510317acca20ed9b52
提交 | 用户 | age
ebf7c8 1 <template>
V 2   <Modal @cancel="handleCancel" v-bind="getBindValue">
3     <template #closeIcon v-if="!$slots.closeIcon">
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">
18ad1b 21       <ModalFooter v-bind="getProps" @ok="handleOk" @cancel="handleCancel">
V 22         <template #[item]="data" v-for="item in Object.keys($slots)">
9edc28 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'))">
9edc28 47       <slot :name="item" v-bind="data"></slot>
3b126e 48     </template>
ebf7c8 49   </Modal>
V 50 </template>
51 <script lang="ts">
52   import type { ModalProps, ModalMethods } from './types';
53
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
66   import Modal from './components/Modal';
67   import ModalWrapper from './components/ModalWrapper.vue';
68   import ModalClose from './components/ModalClose.vue';
69   import ModalFooter from './components/ModalFooter.vue';
70   import ModalHeader from './components/ModalHeader.vue';
71
72   import { isFunction } from '/@/utils/is';
73   import { deepMerge } from '/@/utils';
74
75   import { basicProps } from './props';
76   import { useFullScreen } from './hooks/useModalFullScreen';
a3a903 77
ebf7c8 78   import { omit } from 'lodash-es';
V 79   export default defineComponent({
80     name: 'BasicModal',
81     components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
9edc28 82     inheritAttrs: false,
ebf7c8 83     props: basicProps,
V 84     emits: ['visible-change', 'height-change', 'cancel', 'ok', 'register'],
85     setup(props, { emit, attrs }) {
86       const visibleRef = ref(false);
87       const propsRef = ref<Partial<ModalProps> | null>(null);
88       const modalWrapperRef = ref<ComponentRef>(null);
a3a903 89
ebf7c8 90       // modal   Bottom and top height
V 91       const extHeightRef = ref(0);
92       const modalMethods: ModalMethods = {
93         setModalProps,
94         emitVisible: undefined,
a3a903 95         redoModalHeight: () => {
V 96           nextTick(() => {
97             if (unref(modalWrapperRef)) {
98               (unref(modalWrapperRef) as any).setModalHeight();
99             }
100           });
101         },
ebf7c8 102       };
a3a903 103
ebf7c8 104       const instance = getCurrentInstance();
V 105       if (instance) {
106         emit('register', modalMethods, instance.uid);
107       }
108
109       // Custom title component: get title
110       const getMergeProps = computed(
111         (): ModalProps => {
112           return {
113             ...props,
114             ...(unref(propsRef) as any),
115           };
116         }
117       );
118
119       const { handleFullScreen, getWrapClassName, fullScreenRef } = useFullScreen({
120         modalWrapperRef,
121         extHeightRef,
122         wrapClassName: toRef(getMergeProps.value, 'wrapClassName'),
123       });
124
a579b8 125       // modal component does not need title and origin buttons
ebf7c8 126       const getProps = computed(
V 127         (): ModalProps => {
128           const opt = {
129             ...unref(getMergeProps),
130             visible: unref(visibleRef),
a579b8 131             okButtonProps: undefined,
N 132             cancelButtonProps: undefined,
ebf7c8 133             title: undefined,
V 134           };
135           return {
136             ...opt,
137             wrapClassName: unref(getWrapClassName),
138           };
139         }
140       );
141
37508c 142       const getBindValue = computed(
V 143         (): Recordable => {
144           const attr = { ...attrs, ...unref(getProps) };
145           if (unref(fullScreenRef)) {
146             return omit(attr, 'height');
147           }
148           return attr;
149         }
150       );
151
152       const getWrapperHeight = computed(() => {
153         if (unref(fullScreenRef)) return undefined;
154         return unref(getProps).height;
ebf7c8 155       });
V 156
157       watchEffect(() => {
158         visibleRef.value = !!props.visible;
efbde0 159         fullScreenRef.value = !!props.defaultFullscreen;
ebf7c8 160       });
V 161
162       watch(
163         () => unref(visibleRef),
164         (v) => {
165           emit('visible-change', v);
166           instance && modalMethods.emitVisible?.(v, instance.uid);
a3a903 167           nextTick(() => {
V 168             if (props.scrollTop && v && unref(modalWrapperRef)) {
169               (unref(modalWrapperRef) as any).scrollTop();
170             }
171           });
ebf7c8 172         },
V 173         {
174           immediate: false,
175         }
176       );
177
178       // 取消事件
179       async function handleCancel(e: Event) {
180         e?.stopPropagation();
181
182         if (props.closeFunc && isFunction(props.closeFunc)) {
183           const isClose: boolean = await props.closeFunc();
184           visibleRef.value = !isClose;
185           return;
186         }
187
188         visibleRef.value = false;
189         emit('cancel');
190       }
191
192       /**
193        * @description: 设置modal参数
194        */
195       function setModalProps(props: Partial<ModalProps>): void {
196         // Keep the last setModalProps
197         propsRef.value = deepMerge(unref(propsRef) || {}, props);
198         if (!Reflect.has(props, 'visible')) return;
199         visibleRef.value = !!props.visible;
200       }
201
202       function handleOk() {
203         emit('ok');
204       }
205
206       function handleHeightChange(height: string) {
207         emit('height-change', height);
208       }
209
210       function handleExtHeight(height: number) {
211         extHeightRef.value = height;
212       }
213
e3851d 214       function handleTitleDbClick(e: ChangeEvent) {
V 215         if (!props.canFullscreen) return;
216         e.stopPropagation();
217         handleFullScreen(e);
218       }
219
ebf7c8 220       return {
V 221         handleCancel,
222         getBindValue,
223         getProps,
224         handleFullScreen,
225         fullScreenRef,
226         getMergeProps,
227         handleOk,
228         visibleRef,
229         omit,
230         modalWrapperRef,
231         handleExtHeight,
232         handleHeightChange,
e3851d 233         handleTitleDbClick,
37508c 234         getWrapperHeight,
ebf7c8 235       };
V 236     },
237   });
238 </script>