Procházet zdrojové kódy

feat(modal): exporse redoModalHeight

vben před 4 roky
rodič
revize
a3a903bc86

+ 4 - 0
CHANGELOG.zh_CN.md

@@ -1,5 +1,9 @@
 ## Wip
 
+### ✨ Features
+
+- useModal 新增返回值函数 `redoModalHeight`,用于在 modal 内为动态内容时刷新 modal 高度
+
 ### 🐛 Bug Fixes
 
 - 修复 Upload 组件 maxNumber 失效问题

+ 16 - 0
src/components/Modal/src/BasicModal.vue

@@ -55,6 +55,7 @@
     watchEffect,
     toRef,
     getCurrentInstance,
+    nextTick,
   } from 'vue';
 
   import Modal from './components/Modal';
@@ -68,6 +69,7 @@
 
   import { basicProps } from './props';
   import { useFullScreen } from './hooks/useModalFullScreen';
+
   import { omit } from 'lodash-es';
   export default defineComponent({
     name: 'BasicModal',
@@ -79,12 +81,21 @@
       const visibleRef = ref(false);
       const propsRef = ref<Partial<ModalProps> | null>(null);
       const modalWrapperRef = ref<ComponentRef>(null);
+
       // modal   Bottom and top height
       const extHeightRef = ref(0);
       const modalMethods: ModalMethods = {
         setModalProps,
         emitVisible: undefined,
+        redoModalHeight: () => {
+          nextTick(() => {
+            if (unref(modalWrapperRef)) {
+              (unref(modalWrapperRef) as any).setModalHeight();
+            }
+          });
+        },
       };
+
       const instance = getCurrentInstance();
       if (instance) {
         emit('register', modalMethods, instance.uid);
@@ -135,6 +146,11 @@
         (v) => {
           emit('visible-change', v);
           instance && modalMethods.emitVisible?.(v, instance.uid);
+          nextTick(() => {
+            if (props.scrollTop && v && unref(modalWrapperRef)) {
+              (unref(modalWrapperRef) as any).scrollTop();
+            }
+          });
         },
         {
           immediate: false,

+ 11 - 2
src/components/Modal/src/components/ModalWrapper.vue

@@ -55,7 +55,7 @@
 
       let stopElResizeFn: Fn = () => {};
 
-      useWindowSizeFn(setModalHeight);
+      useWindowSizeFn(setModalHeight.bind(null, false));
 
       createModalContext({
         redoModalHeight: setModalHeight,
@@ -97,12 +97,21 @@
         stopElResizeFn && stopElResizeFn();
       });
 
+      async function scrollTop() {
+        nextTick(() => {
+          const wrapperRefDom = unref(wrapperRef);
+          if (!wrapperRefDom) return;
+          (wrapperRefDom as any)?.scrollTo?.(0);
+        });
+      }
+
       async function setModalHeight() {
         // 解决在弹窗关闭的时候监听还存在,导致再次打开弹窗没有高度
         // 加上这个,就必须在使用的时候传递父级的visible
         if (!props.visible) return;
         const wrapperRefDom = unref(wrapperRef);
         if (!wrapperRefDom) return;
+
         const bodyDom = wrapperRefDom.$el.parentElement;
         if (!bodyDom) return;
         bodyDom.style.padding = '0';
@@ -150,7 +159,7 @@
         }
       }
 
-      return { wrapperRef, spinRef, spinStyle };
+      return { wrapperRef, spinRef, spinStyle, scrollTop, setModalHeight };
     },
   });
 </script>

+ 5 - 0
src/components/Modal/src/hooks/useModal.ts

@@ -64,10 +64,15 @@ export function useModal(): UseModalReturnType {
     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,

+ 1 - 0
src/components/Modal/src/props.ts

@@ -8,6 +8,7 @@ const { t } = useI18n();
 
 export const modalProps = {
   visible: propTypes.bool,
+  scrollTop: propTypes.bool.def(true),
   height: propTypes.number,
   minHeight: propTypes.number,
   // open drag

+ 2 - 0
src/components/Modal/src/types.ts

@@ -6,6 +6,7 @@ import type { CSSProperties, VNodeChild, ComputedRef } from 'vue';
 export interface ModalMethods {
   setModalProps: (props: Partial<ModalProps>) => void;
   emitVisible?: (visible: boolean, uid: number) => void;
+  redoModalHeight?: () => void;
 }
 
 export type RegisterFn = (modalMethods: ModalMethods, uuid?: string) => void;
@@ -32,6 +33,7 @@ export interface ModalProps {
   // 启用wrapper后 底部可以适当增加高度
   wrapperFooterOffset?: number;
   draggable?: boolean;
+  scrollTop?: boolean;
 
   // 是否可以进行全屏
   canFullscreen?: boolean;

+ 1 - 0
src/components/Table/src/BasicTable.vue

@@ -205,6 +205,7 @@
         if (slots.expandedRowRender) {
           propsData = omit(propsData, 'scroll');
         }
+
         return propsData;
       });
 

+ 1 - 0
src/views/demo/page/form/high/PersonTable.vue

@@ -98,6 +98,7 @@
           dept: '',
           editable: true,
           isNew: true,
+          key: `${Date.now()}`,
         };
         data.push(addRow);
       }