mirror of
https://github.com/vbenjs/gf-vben-admin.git
synced 2025-01-23 03:40:19 +08:00
fix(modal): ensure that the full screen height is calculated correctly
This commit is contained in:
parent
639520ad5d
commit
1c1755cf5b
@ -2,9 +2,15 @@
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- `Cropper` 头像裁剪新增圆形裁剪功能
|
||||
- 新增头像上传组件
|
||||
- `useDrawer`新增`closeDrawer`函数
|
||||
- **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能
|
||||
- **CropperAvatar** 新增头像上传组件
|
||||
- **Drawer** `useDrawer`新增`closeDrawer`函数
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **Modal** 修复全屏高度计算错误
|
||||
- **PageWrapper** 修复高度计算问题
|
||||
- 修复后台模式下,Iframe 路由错误
|
||||
|
||||
## 2.4.2(2021-06-10)
|
||||
|
||||
|
@ -163,7 +163,7 @@
|
||||
|
||||
function setDrawerProps(props: Partial<DrawerProps>): void {
|
||||
// Keep the last setDrawerProps
|
||||
propsRef.value = deepMerge((unref(propsRef) as any) || {}, props);
|
||||
propsRef.value = deepMerge(unref(propsRef), props);
|
||||
|
||||
if (Reflect.has(props, 'visible')) {
|
||||
visibleRef.value = !!props.visible;
|
||||
|
@ -5,7 +5,6 @@ import type {
|
||||
DrawerProps,
|
||||
UseDrawerInnerReturnType,
|
||||
} from './typing';
|
||||
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance,
|
||||
@ -16,11 +15,9 @@ import {
|
||||
toRaw,
|
||||
computed,
|
||||
} from 'vue';
|
||||
|
||||
import { isProdMode } from '/@/utils/env';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
import { tryOnUnmounted } from '@vueuse/core';
|
||||
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { error } from '/@/utils/log';
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { withInstall } from '/@/utils';
|
||||
import './src/index.less';
|
||||
import BasicModal from './src/BasicModal.vue';
|
||||
import basicModal from './src/BasicModal.vue';
|
||||
|
||||
export { BasicModal };
|
||||
export const BasicModal = withInstall(basicModal);
|
||||
export { useModalContext } from './src/hooks/useModalContext';
|
||||
export { useModal, useModalInner } from './src/hooks/useModal';
|
||||
export * from './src/types';
|
||||
export * from './src/typing';
|
||||
|
@ -49,7 +49,7 @@
|
||||
</Modal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { ModalProps, ModalMethods } from './types';
|
||||
import type { ModalProps, ModalMethods } from './typing';
|
||||
|
||||
import {
|
||||
defineComponent,
|
||||
@ -62,20 +62,17 @@
|
||||
getCurrentInstance,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
|
||||
import Modal from './components/Modal';
|
||||
import ModalWrapper from './components/ModalWrapper.vue';
|
||||
import ModalClose from './components/ModalClose.vue';
|
||||
import ModalFooter from './components/ModalFooter.vue';
|
||||
import ModalHeader from './components/ModalHeader.vue';
|
||||
|
||||
import { isFunction } from '/@/utils/is';
|
||||
import { deepMerge } from '/@/utils';
|
||||
|
||||
import { basicProps } from './props';
|
||||
import { useFullScreen } from './hooks/useModalFullScreen';
|
||||
|
||||
import { omit } from 'lodash-es';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BasicModal',
|
||||
components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
|
||||
@ -189,7 +186,7 @@
|
||||
*/
|
||||
function setModalProps(props: Partial<ModalProps>): void {
|
||||
// Keep the last setModalProps
|
||||
propsRef.value = deepMerge(unref(propsRef) || {}, props);
|
||||
propsRef.value = deepMerge(unref(propsRef), props);
|
||||
if (!Reflect.has(props, 'visible')) return;
|
||||
visibleRef.value = !!props.visible;
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ export default defineComponent({
|
||||
|
||||
return () => {
|
||||
const propsData = { ...unref(attrs), ...props } as Recordable;
|
||||
|
||||
return <Modal {...propsData}>{extendSlots(slots)}</Modal>;
|
||||
};
|
||||
},
|
||||
|
@ -2,7 +2,6 @@
|
||||
<div :class="getClass">
|
||||
<template v-if="canFullscreen">
|
||||
<FullscreenExitOutlined role="full" @click="handleFullScreen" v-if="fullScreen" />
|
||||
|
||||
<FullscreenOutlined role="close" @click="handleFullScreen" v-else />
|
||||
</template>
|
||||
<CloseOutlined @click="handleCancel" />
|
||||
@ -12,14 +11,13 @@
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined } from '@ant-design/icons-vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ModalClose',
|
||||
components: { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined },
|
||||
props: {
|
||||
canFullscreen: propTypes.bool.def(true),
|
||||
fullScreen: propTypes.bool,
|
||||
canFullscreen: { type: Boolean, default: true },
|
||||
fullScreen: { type: Boolean },
|
||||
},
|
||||
emits: ['cancel', 'fullscreen'],
|
||||
setup(props, { emit }) {
|
||||
@ -38,6 +36,7 @@
|
||||
function handleCancel(e: Event) {
|
||||
emit('cancel', e);
|
||||
}
|
||||
|
||||
function handleFullScreen(e: Event) {
|
||||
e?.stopPropagation();
|
||||
e?.preventDefault();
|
||||
|
@ -33,6 +33,7 @@
|
||||
function handleCancel(e: Event) {
|
||||
emit('cancel', e);
|
||||
}
|
||||
|
||||
return { handleOk, handleCancel };
|
||||
},
|
||||
});
|
||||
|
@ -8,7 +8,6 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTitle } from '/@/components/Basic';
|
||||
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
export default defineComponent({
|
||||
name: 'BasicModalHeader',
|
||||
components: { BasicTitle },
|
||||
@ -16,7 +15,7 @@
|
||||
helpMessage: {
|
||||
type: [String, Array] as PropType<string | string[]>,
|
||||
},
|
||||
title: propTypes.string,
|
||||
title: { type: String },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -6,9 +6,7 @@
|
||||
</ScrollContainer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { ModalWrapperProps } from '../types';
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
import {
|
||||
defineComponent,
|
||||
computed,
|
||||
@ -20,31 +18,31 @@
|
||||
nextTick,
|
||||
onUnmounted,
|
||||
} from 'vue';
|
||||
|
||||
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
|
||||
import { ScrollContainer } from '/@/components/Container';
|
||||
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { createModalContext } from '../hooks/useModalContext';
|
||||
import { useMutationObserver } from '@vueuse/core';
|
||||
|
||||
const props = {
|
||||
loading: { type: Boolean },
|
||||
useWrapper: { type: Boolean, default: true },
|
||||
modalHeaderHeight: { type: Number, default: 57 },
|
||||
modalFooterHeight: { type: Number, default: 74 },
|
||||
minHeight: { type: Number, default: 200 },
|
||||
height: { type: Number },
|
||||
footerOffset: { type: Number, default: 0 },
|
||||
visible: { type: Boolean },
|
||||
fullScreen: { type: Boolean },
|
||||
loadingTip: { type: String },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ModalWrapper',
|
||||
components: { ScrollContainer },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
loading: propTypes.bool,
|
||||
useWrapper: propTypes.bool.def(true),
|
||||
modalHeaderHeight: propTypes.number.def(57),
|
||||
modalFooterHeight: propTypes.number.def(74),
|
||||
minHeight: propTypes.number.def(200),
|
||||
height: propTypes.number,
|
||||
footerOffset: propTypes.number.def(0),
|
||||
visible: propTypes.bool,
|
||||
fullScreen: propTypes.bool,
|
||||
loadingTip: propTypes.string,
|
||||
},
|
||||
props,
|
||||
emits: ['height-change', 'ext-height'],
|
||||
setup(props: ModalWrapperProps, { emit }) {
|
||||
setup(props, { emit }) {
|
||||
const wrapperRef = ref<ComponentRef>(null);
|
||||
const spinRef = ref<ElRef>(null);
|
||||
const realHeightRef = ref(0);
|
||||
@ -56,6 +54,17 @@
|
||||
|
||||
useWindowSizeFn(setModalHeight.bind(null, false));
|
||||
|
||||
useMutationObserver(
|
||||
spinRef,
|
||||
() => {
|
||||
setModalHeight();
|
||||
},
|
||||
{
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
}
|
||||
);
|
||||
|
||||
createModalContext({
|
||||
redoModalHeight: setModalHeight,
|
||||
});
|
||||
@ -63,8 +72,7 @@
|
||||
const spinStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
minHeight: `${props.minHeight}px`,
|
||||
// padding 28
|
||||
maxHeight: `${unref(realHeightRef)}px`,
|
||||
[props.fullScreen ? 'height' : 'maxHeight']: `${unref(realHeightRef)}px`,
|
||||
};
|
||||
});
|
||||
|
||||
@ -87,7 +95,6 @@
|
||||
onMounted(() => {
|
||||
const { modalHeaderHeight, modalFooterHeight } = props;
|
||||
emit('ext-height', modalHeaderHeight + modalFooterHeight);
|
||||
// listenElResize();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
@ -4,8 +4,7 @@ import type {
|
||||
ModalProps,
|
||||
ReturnMethods,
|
||||
UseModalInnerReturnType,
|
||||
} from '../types';
|
||||
|
||||
} from '../typing';
|
||||
import {
|
||||
ref,
|
||||
onUnmounted,
|
||||
@ -20,10 +19,10 @@ import { isProdMode } from '/@/utils/env';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { tryOnUnmounted } from '@vueuse/core';
|
||||
|
||||
import { error } from '/@/utils/log';
|
||||
import { computed } from 'vue';
|
||||
const dataTransferRef = reactive<any>({});
|
||||
|
||||
const dataTransfer = reactive<any>({});
|
||||
|
||||
const visibleData = reactive<{ [key: number]: boolean }>({});
|
||||
|
||||
@ -31,29 +30,31 @@ const visibleData = reactive<{ [key: number]: boolean }>({});
|
||||
* @description: Applicable to independent modal and call outside
|
||||
*/
|
||||
export function useModal(): UseModalReturnType {
|
||||
const modalRef = ref<Nullable<ModalMethods>>(null);
|
||||
const loadedRef = ref<Nullable<boolean>>(false);
|
||||
const uidRef = ref<string>('');
|
||||
const modal = ref<Nullable<ModalMethods>>(null);
|
||||
const loaded = ref<Nullable<boolean>>(false);
|
||||
const uid = ref<string>('');
|
||||
|
||||
function register(modalMethod: ModalMethods, uuid: string) {
|
||||
uidRef.value = uuid;
|
||||
|
||||
if (!getCurrentInstance()) {
|
||||
throw new Error('useModal() can only be used inside setup() or functional components!');
|
||||
}
|
||||
uid.value = uuid;
|
||||
isProdMode() &&
|
||||
onUnmounted(() => {
|
||||
modalRef.value = null;
|
||||
loadedRef.value = false;
|
||||
dataTransferRef[unref(uidRef)] = null;
|
||||
modal.value = null;
|
||||
loaded.value = false;
|
||||
dataTransfer[unref(uid)] = null;
|
||||
});
|
||||
if (unref(loadedRef) && isProdMode() && modalMethod === unref(modalRef)) return;
|
||||
if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return;
|
||||
|
||||
modalRef.value = modalMethod;
|
||||
modal.value = modalMethod;
|
||||
modalMethod.emitVisible = (visible: boolean, uid: number) => {
|
||||
visibleData[uid] = visible;
|
||||
};
|
||||
}
|
||||
|
||||
const getInstance = () => {
|
||||
const instance = unref(modalRef);
|
||||
const instance = unref(modal);
|
||||
if (!instance) {
|
||||
error('useModal instance is undefined!');
|
||||
}
|
||||
@ -66,7 +67,7 @@ export function useModal(): UseModalReturnType {
|
||||
},
|
||||
|
||||
getVisible: computed((): boolean => {
|
||||
return visibleData[~~unref(uidRef)];
|
||||
return visibleData[~~unref(uid)];
|
||||
}),
|
||||
|
||||
redoModalHeight: () => {
|
||||
@ -79,15 +80,15 @@ export function useModal(): UseModalReturnType {
|
||||
});
|
||||
|
||||
if (!data) return;
|
||||
|
||||
const id = unref(uid);
|
||||
if (openOnSet) {
|
||||
dataTransferRef[unref(uidRef)] = null;
|
||||
dataTransferRef[unref(uidRef)] = toRaw(data);
|
||||
dataTransfer[id] = null;
|
||||
dataTransfer[id] = toRaw(data);
|
||||
return;
|
||||
}
|
||||
const equal = isEqual(toRaw(dataTransferRef[unref(uidRef)]), toRaw(data));
|
||||
const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data));
|
||||
if (!equal) {
|
||||
dataTransferRef[unref(uidRef)] = toRaw(data);
|
||||
dataTransfer[id] = toRaw(data);
|
||||
}
|
||||
},
|
||||
|
||||
@ -103,9 +104,6 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
|
||||
const currentInstance = getCurrentInstance();
|
||||
const uidRef = ref<string>('');
|
||||
|
||||
// currentInstall.type.emits = [...currentInstall.type.emits, 'register'];
|
||||
// Object.assign(currentInstall.type.emits, ['register']);
|
||||
|
||||
const getInstance = () => {
|
||||
const instance = unref(modalInstanceRef);
|
||||
if (!instance) {
|
||||
@ -125,7 +123,7 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
const data = dataTransferRef[unref(uidRef)];
|
||||
const data = dataTransfer[unref(uidRef)];
|
||||
if (!data) return;
|
||||
if (!callbackFn || !isFunction(callbackFn)) return;
|
||||
nextTick(() => {
|
||||
|
@ -12,7 +12,6 @@ export function useFullScreen(context: UseFullScreenContext) {
|
||||
|
||||
const getWrapClassName = computed(() => {
|
||||
const clsName = unref(context.wrapClassName) || '';
|
||||
|
||||
return unref(fullScreenRef) ? `fullscreen-modal ${clsName} ` : unref(clsName);
|
||||
});
|
||||
|
||||
|
@ -1,45 +1,44 @@
|
||||
import type { PropType, CSSProperties } from 'vue';
|
||||
import type { ModalWrapperProps } from './typing';
|
||||
import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { propTypes, VueNode } from '/@/utils/propTypes';
|
||||
import type { ModalWrapperProps } from './types';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
export const modalProps = {
|
||||
visible: propTypes.bool,
|
||||
scrollTop: propTypes.bool.def(true),
|
||||
height: propTypes.number,
|
||||
minHeight: propTypes.number,
|
||||
visible: { type: Boolean },
|
||||
scrollTop: { type: Boolean, default: true },
|
||||
height: { type: Number },
|
||||
minHeight: { type: Number },
|
||||
// open drag
|
||||
draggable: propTypes.bool.def(true),
|
||||
centered: propTypes.bool,
|
||||
cancelText: propTypes.string.def(t('common.cancelText')),
|
||||
okText: propTypes.string.def(t('common.okText')),
|
||||
draggable: { type: Boolean, default: true },
|
||||
centered: { type: Boolean },
|
||||
cancelText: { type: String, default: t('common.cancelText') },
|
||||
okText: { type: String, default: t('common.okText') },
|
||||
|
||||
closeFunc: Function as PropType<() => Promise<boolean>>,
|
||||
};
|
||||
|
||||
export const basicProps = Object.assign({}, modalProps, {
|
||||
defaultFullscreen: propTypes.bool,
|
||||
defaultFullscreen: { type: Boolean },
|
||||
// Can it be full screen
|
||||
canFullscreen: propTypes.bool.def(true),
|
||||
canFullscreen: { type: Boolean, default: true },
|
||||
// After enabling the wrapper, the bottom can be increased in height
|
||||
wrapperFooterOffset: propTypes.number.def(0),
|
||||
wrapperFooterOffset: { type: Number, default: 0 },
|
||||
// Warm reminder message
|
||||
helpMessage: [String, Array] as PropType<string | string[]>,
|
||||
// Whether to setting wrapper
|
||||
useWrapper: propTypes.bool.def(true),
|
||||
loading: propTypes.bool,
|
||||
loadingTip: propTypes.string,
|
||||
useWrapper: { type: Boolean, default: true },
|
||||
loading: { type: Boolean },
|
||||
loadingTip: { type: String },
|
||||
/**
|
||||
* @description: Show close button
|
||||
*/
|
||||
showCancelBtn: propTypes.bool.def(true),
|
||||
showCancelBtn: { type: Boolean, default: true },
|
||||
/**
|
||||
* @description: Show confirmation button
|
||||
*/
|
||||
showOkBtn: propTypes.bool.def(true),
|
||||
showOkBtn: { type: Boolean, default: true },
|
||||
|
||||
wrapperProps: Object as PropType<Partial<ModalWrapperProps>>,
|
||||
|
||||
@ -47,38 +46,38 @@ export const basicProps = Object.assign({}, modalProps, {
|
||||
|
||||
bodyStyle: Object as PropType<CSSProperties>,
|
||||
|
||||
closable: propTypes.bool.def(true),
|
||||
closable: { type: Boolean, default: true },
|
||||
|
||||
closeIcon: Object as PropType<VueNode>,
|
||||
|
||||
confirmLoading: propTypes.bool,
|
||||
confirmLoading: { type: Boolean },
|
||||
|
||||
destroyOnClose: propTypes.bool,
|
||||
destroyOnClose: { type: Boolean },
|
||||
|
||||
footer: Object as PropType<VueNode>,
|
||||
|
||||
getContainer: Function as PropType<() => any>,
|
||||
|
||||
mask: propTypes.bool.def(true),
|
||||
mask: { type: Boolean, default: true },
|
||||
|
||||
maskClosable: propTypes.bool.def(true),
|
||||
keyboard: propTypes.bool.def(true),
|
||||
maskClosable: { type: Boolean, default: true },
|
||||
keyboard: { type: Boolean, default: true },
|
||||
|
||||
maskStyle: Object as PropType<CSSProperties>,
|
||||
|
||||
okType: propTypes.string.def('primary'),
|
||||
okType: { type: String, default: 'primary' },
|
||||
|
||||
okButtonProps: Object as PropType<ButtonProps>,
|
||||
|
||||
cancelButtonProps: Object as PropType<ButtonProps>,
|
||||
|
||||
title: propTypes.string,
|
||||
title: { type: String },
|
||||
|
||||
visible: propTypes.bool,
|
||||
visible: { type: Boolean },
|
||||
|
||||
width: [String, Number] as PropType<string | number>,
|
||||
|
||||
wrapClassName: propTypes.string,
|
||||
wrapClassName: { type: String },
|
||||
|
||||
zIndex: propTypes.number,
|
||||
zIndex: { type: Number },
|
||||
});
|
||||
|
@ -1,3 +1,5 @@
|
||||
export { default as QrCode } from './src/Qrcode.vue';
|
||||
import { withInstall } from '/@/utils';
|
||||
import qrCode from './src/Qrcode.vue';
|
||||
|
||||
export * from './src/types';
|
||||
export const QrCode = withInstall(qrCode);
|
||||
export * from './src/typing';
|
||||
|
@ -8,7 +8,7 @@
|
||||
import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus';
|
||||
import { toDataURL } from 'qrcode';
|
||||
import { downloadByUrl } from '/@/utils/file/download';
|
||||
import { QrcodeDoneEventParams } from './types';
|
||||
import { QrcodeDoneEventParams } from './typing';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QrCode',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { toCanvas } from 'qrcode';
|
||||
import type { QRCodeRenderersOptions } from 'qrcode';
|
||||
import { RenderQrCodeParams, ContentType } from './types';
|
||||
import { RenderQrCodeParams, ContentType } from './typing';
|
||||
export const renderQrCode = ({ canvas, content, width = 0, options = {} }: RenderQrCodeParams) => {
|
||||
// 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率
|
||||
options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content);
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { isString } from '/@/utils/is';
|
||||
import { RenderQrCodeParams, LogoType } from './types';
|
||||
import { RenderQrCodeParams, LogoType } from './typing';
|
||||
export const drawLogo = ({ canvas, logo }: RenderQrCodeParams) => {
|
||||
if (!logo) {
|
||||
return new Promise((resolve) => {
|
||||
resolve((canvas as HTMLCanvasElement).toDataURL());
|
||||
});
|
||||
}
|
||||
|
||||
const canvasWidth = (canvas as HTMLCanvasElement).width;
|
||||
const {
|
||||
logoSize = 0.15,
|
||||
|
@ -1,5 +1,4 @@
|
||||
// 参考 qr-code-with-logo 进行ts版本修改
|
||||
import { toCanvas } from './toCanvas';
|
||||
export * from './types';
|
||||
|
||||
export * from './typing';
|
||||
export { toCanvas };
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { renderQrCode } from './drawCanvas';
|
||||
import { drawLogo } from './drawLogo';
|
||||
import { RenderQrCodeParams } from './types';
|
||||
import { RenderQrCodeParams } from './typing';
|
||||
export const toCanvas = (options: RenderQrCodeParams) => {
|
||||
return renderQrCode(options)
|
||||
.then(() => {
|
||||
|
@ -95,7 +95,7 @@
|
||||
&__entry {
|
||||
position: relative;
|
||||
//height: 240px;
|
||||
padding: 130px 30px 60px 30px;
|
||||
padding: 130px 30px 30px 30px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,7 @@
|
||||
<Alert message="自适应高度/显示footer" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openDrawer3(true)"> 打开Drawer </a-button>
|
||||
|
||||
<Alert
|
||||
message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式"
|
||||
show-icon
|
||||
/>
|
||||
<Alert message="内外数据交互" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="send"> 打开Drawer并传递数据 </a-button>
|
||||
<Alert message="详情页模式" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openDrawer5(true)"> 打开详情Drawer </a-button>
|
||||
|
@ -14,10 +14,7 @@
|
||||
<Alert message="自适应高度" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openModal3"> 打开弹窗 </a-button>
|
||||
|
||||
<Alert
|
||||
message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式"
|
||||
show-icon
|
||||
/>
|
||||
<Alert message="内外数据交互" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="send"> 打开弹窗并传递数据 </a-button>
|
||||
|
||||
<Modal1 @register="register1" :minHeight="100" />
|
||||
|
2
types/global.d.ts
vendored
2
types/global.d.ts
vendored
@ -1,6 +1,7 @@
|
||||
import type {
|
||||
ComponentRenderProxy,
|
||||
VNode,
|
||||
VNodeChild,
|
||||
ComponentPublicInstance,
|
||||
FunctionalComponent,
|
||||
PropType as VuePropType,
|
||||
@ -23,6 +24,7 @@ declare global {
|
||||
|
||||
// vue
|
||||
declare type PropType<T> = VuePropType<T>;
|
||||
declare type VueNode = VNodeChild | JSX.Element;
|
||||
|
||||
export type Writable<T> = {
|
||||
-readonly [P in keyof T]: T[P];
|
||||
|
Loading…
Reference in New Issue
Block a user