This commit is contained in:
dap 2024-11-01 08:35:13 +08:00
commit a30029a33d
11 changed files with 97 additions and 13 deletions

View File

@ -110,12 +110,14 @@ const [Modal, modalApi] = useVbenModal({
以下事件,只有在 `useVbenModal({onCancel:()=>{}})` 中传入才会生效。
| 事件名 | 描述 | 类型 |
| --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` |
| onCancel | 点击取消按钮触发 | `()=>void` |
| onConfirm | 点击确认按钮触发 | `()=>void` |
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` |
| 事件名 | 描述 | 类型 | 版本号 |
| --- | --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | |
| onCancel | 点击取消按钮触发 | `()=>void` | |
| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 |
| onConfirm | 点击确认按钮触发 | `()=>void` | |
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | |
| onOpened | 打开动画播放完毕时触发 | `()=>void` | >5.4.3 |
### Slots

View File

@ -64,7 +64,6 @@ const activePath = ref<MenuProvider['activePath']>(props.defaultActive);
const items = ref<MenuProvider['items']>({});
const subMenus = ref<MenuProvider['subMenus']>({});
const mouseInChild = ref(false);
const defaultSlots: VNodeArrayChildren = slots.default?.() ?? [];
const isMenuPopup = computed<MenuProvider['isMenuPopup']>(() => {
return (
@ -73,6 +72,9 @@ const isMenuPopup = computed<MenuProvider['isMenuPopup']>(() => {
});
const getSlot = computed(() => {
//
const defaultSlots: VNodeArrayChildren = slots.default?.() ?? [];
const originalSlot = flattedChildren(defaultSlots) as VNodeArrayChildren;
const slotDefault =
sliceIndex.value === -1
@ -718,6 +720,10 @@ $namespace: vben;
align-items: center;
width: 100%;
height: var(--menu-item-height);
span {
@include menu-title;
}
}
&.is-collapse-show-title {

View File

@ -42,7 +42,9 @@ const hasChildren = computed(() => {
:icon="menu.icon"
:path="menu.path"
>
<template #title>{{ menu.name }}</template>
<template #title>
<span>{{ menu.name }}</span>
</template>
</MenuItem>
<SubMenuComp
v-else
@ -59,7 +61,9 @@ const hasChildren = computed(() => {
class="right-6"
/>
</template>
<template #title>{{ menu.name }}</template>
<template #title>
<span>{{ menu.name }}</span>
</template>
<template v-for="childItem in menu.children || []" :key="childItem.path">
<SubMenu :menu="childItem" />
</template>

View File

@ -110,4 +110,19 @@ describe('modalApi', () => {
expect(modalApi.store.state.title).toBe('Batch Title');
expect(modalApi.store.state.confirmText).toBe('Batch Confirm');
});
it('should call onClosed callback when provided', () => {
const onClosed = vi.fn();
const modalApiWithHook = new ModalApi({ onClosed });
modalApiWithHook.onClosed();
expect(onClosed).toHaveBeenCalled();
});
it('should call onOpened callback when provided', () => {
const onOpened = vi.fn();
const modalApiWithHook = new ModalApi({ onOpened });
modalApiWithHook.open();
modalApiWithHook.onOpened();
expect(onOpened).toHaveBeenCalled();
});
});

View File

@ -6,7 +6,12 @@ import { bindMethods, isFunction } from '@vben-core/shared/utils';
export class ModalApi {
private api: Pick<
ModalApiOptions,
'onBeforeClose' | 'onCancel' | 'onConfirm' | 'onOpenChange'
| 'onBeforeClose'
| 'onCancel'
| 'onClosed'
| 'onConfirm'
| 'onOpenChange'
| 'onOpened'
>;
// private prevState!: ModalState;
private state!: ModalState;
@ -23,8 +28,10 @@ export class ModalApi {
connectedComponent: _,
onBeforeClose,
onCancel,
onClosed,
onConfirm,
onOpenChange,
onOpened,
...storeState
} = options;
@ -77,8 +84,10 @@ export class ModalApi {
this.api = {
onBeforeClose,
onCancel,
onClosed,
onConfirm,
onOpenChange,
onOpened,
};
bindMethods(this);
}
@ -123,6 +132,15 @@ export class ModalApi {
}
}
/**
*
*/
onClosed() {
if (!this.state.isOpen) {
this.api.onClosed?.();
}
}
/**
*
*/
@ -130,6 +148,15 @@ export class ModalApi {
this.api.onConfirm?.();
}
/**
*
*/
onOpened() {
if (this.state.isOpen) {
this.api.onOpened?.();
}
}
open() {
this.store.setState((prev) => ({ ...prev, isOpen: true }));
}

View File

@ -139,6 +139,11 @@ export interface ModalApiOptions extends ModalState {
*
*/
onCancel?: () => void;
/**
*
* @returns
*/
onClosed?: () => void;
/**
*
*/
@ -149,4 +154,9 @@ export interface ModalApiOptions extends ModalState {
* @returns
*/
onOpenChange?: (isOpen: boolean) => void;
/**
*
* @returns
*/
onOpened?: () => void;
}

View File

@ -188,10 +188,12 @@ function handleFocusOutside(e: Event) {
:show-close="closable"
close-class="top-3"
@close-auto-focus="handleFocusOutside"
@closed="() => modalApi?.onClosed()"
@escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside"
@interact-outside="interactOutside"
@open-auto-focus="handerOpenAutoFocus"
@opened="() => modalApi?.onOpened()"
@pointer-down-outside="pointerDownOutside"
>
<DialogHeader

View File

@ -27,7 +27,9 @@ const props = withDefaults(
>(),
{ showClose: true },
);
const emits = defineEmits<{ close: [] } & DialogContentEmits>();
const emits = defineEmits<
{ close: []; closed: []; opened: [] } & DialogContentEmits
>();
const delegatedProps = computed(() => {
const {
@ -44,7 +46,13 @@ const delegatedProps = computed(() => {
const forwarded = useForwardPropsEmits(delegatedProps, emits);
const contentRef = ref<InstanceType<typeof DialogContent> | null>(null);
function onAnimationEnd() {
if (props.open) {
emits('opened');
} else {
emits('closed');
}
}
defineExpose({
getContentRef: () => contentRef.value,
});
@ -57,6 +65,7 @@ defineExpose({
</Transition>
<DialogContent
ref="contentRef"
@animationend="onAnimationEnd"
v-bind="forwarded"
:class="
cn(

View File

@ -28,6 +28,7 @@ import {
VxeSelect,
VxeTooltip,
VxeUI,
VxeUpload,
// VxeSwitch,
// VxeTextarea,
} from 'vxe-pc-ui';
@ -92,6 +93,7 @@ export function initVxeTable() {
// VxeUI.component(VxeSwitch);
// VxeUI.component(VxeTextarea);
VxeUI.component(VxeTooltip);
VxeUI.component(VxeUpload);
isInit = true;
}

View File

@ -7,10 +7,16 @@ const [Modal, modalApi] = useVbenModal({
onCancel() {
modalApi.close();
},
onClosed() {
message.info('onClosed关闭动画结束');
},
onConfirm() {
message.info('onConfirm');
// modalApi.close();
},
onOpened() {
message.info('onOpened打开动画结束');
},
});
</script>
<template>

View File

@ -31,6 +31,7 @@ const gridOptions: VxeGridProps<RowType> = {
{ field: 'price', title: 'Price' },
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'DateTime' },
],
exportConfig: {},
height: 'auto',
keepSource: true,
proxyConfig: {
@ -45,7 +46,7 @@ const gridOptions: VxeGridProps<RowType> = {
},
toolbarConfig: {
custom: true,
// export: true,
export: true,
// import: true,
refresh: true,
zoom: true,