Merge branch 'main' into rounded

This commit is contained in:
Gahotx 2025-01-16 09:49:41 +08:00 committed by GitHub
commit 19497e0427
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 136 additions and 105 deletions

View File

@ -1,11 +1,7 @@
import { createApp, watchEffect } from 'vue'; import { createApp, watchEffect } from 'vue';
import { registerAccessDirective } from '@vben/access'; import { registerAccessDirective } from '@vben/access';
import { import { initTippy } from '@vben/common-ui';
initTippy,
setDefaultDrawerProps,
setDefaultModalProps,
} from '@vben/common-ui';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { initStores } from '@vben/stores'; import { initStores } from '@vben/stores';
import '@vben/styles'; import '@vben/styles';
@ -23,15 +19,14 @@ async function bootstrap(namespace: string) {
// 初始化组件适配器 // 初始化组件适配器
await initComponentAdapter(); await initComponentAdapter();
// 设置弹窗的默认配置 // // 设置弹窗的默认配置
setDefaultModalProps({ // setDefaultModalProps({
fullscreenButton: false, // fullscreenButton: false,
zIndex: 1020, // });
}); // // 设置抽屉的默认配置
// 设置抽屉的默认配置 // setDefaultDrawerProps({
setDefaultDrawerProps({ // zIndex: 1020,
zIndex: 1020, // });
});
const app = createApp(App); const app = createApp(App);

View File

@ -10,7 +10,7 @@ const routes: RouteRecordRaw[] = [
title: $t('page.dashboard.title'), title: $t('page.dashboard.title'),
}, },
name: 'Dashboard', name: 'Dashboard',
path: '/', path: '/dashboard',
children: [ children: [
{ {
name: 'Analytics', name: 'Analytics',

View File

@ -1,11 +1,7 @@
import { createApp, watchEffect } from 'vue'; import { createApp, watchEffect } from 'vue';
import { registerAccessDirective } from '@vben/access'; import { registerAccessDirective } from '@vben/access';
import { import { initTippy } from '@vben/common-ui';
initTippy,
setDefaultDrawerProps,
setDefaultModalProps,
} from '@vben/common-ui';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { initStores } from '@vben/stores'; import { initStores } from '@vben/stores';
import '@vben/styles'; import '@vben/styles';
@ -23,15 +19,14 @@ import { router } from './router';
async function bootstrap(namespace: string) { async function bootstrap(namespace: string) {
// 初始化组件适配器 // 初始化组件适配器
await initComponentAdapter(); await initComponentAdapter();
// 设置弹窗的默认配置 // // 设置弹窗的默认配置
setDefaultModalProps({ // setDefaultModalProps({
fullscreenButton: false, // fullscreenButton: false,
zIndex: 2000, // });
}); // // 设置抽屉的默认配置
// 设置抽屉的默认配置 // setDefaultDrawerProps({
setDefaultDrawerProps({ // zIndex: 2000,
zIndex: 2000, // });
});
const app = createApp(App); const app = createApp(App);
// 注册Element Plus提供的v-loading指令 // 注册Element Plus提供的v-loading指令

View File

@ -10,7 +10,7 @@ const routes: RouteRecordRaw[] = [
title: $t('page.dashboard.title'), title: $t('page.dashboard.title'),
}, },
name: 'Dashboard', name: 'Dashboard',
path: '/', path: '/dashboard',
children: [ children: [
{ {
name: 'Analytics', name: 'Analytics',

View File

@ -1,11 +1,7 @@
import { createApp, watchEffect } from 'vue'; import { createApp, watchEffect } from 'vue';
import { registerAccessDirective } from '@vben/access'; import { registerAccessDirective } from '@vben/access';
import { import { initTippy } from '@vben/common-ui';
initTippy,
setDefaultDrawerProps,
setDefaultModalProps,
} from '@vben/common-ui';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { initStores } from '@vben/stores'; import { initStores } from '@vben/stores';
import '@vben/styles'; import '@vben/styles';
@ -23,15 +19,14 @@ async function bootstrap(namespace: string) {
// 初始化组件适配器 // 初始化组件适配器
initComponentAdapter(); initComponentAdapter();
// 设置弹窗的默认配置 // // 设置弹窗的默认配置
setDefaultModalProps({ // setDefaultModalProps({
fullscreenButton: false, // fullscreenButton: false,
zIndex: 2000, // });
}); // // 设置抽屉的默认配置
// 设置抽屉的默认配置 // setDefaultDrawerProps({
setDefaultDrawerProps({ // // zIndex: 2000,
zIndex: 2000, // });
});
const app = createApp(App); const app = createApp(App);

View File

@ -10,7 +10,7 @@ const routes: RouteRecordRaw[] = [
title: $t('page.dashboard.title'), title: $t('page.dashboard.title'),
}, },
name: 'Dashboard', name: 'Dashboard',
path: '/', path: '/dashboard',
children: [ children: [
{ {
name: 'Analytics', name: 'Analytics',

View File

@ -113,6 +113,7 @@ const [Modal, modalApi] = useVbenModal({
| bordered | 是否显示border | `boolean` | `false` | | bordered | 是否显示border | `boolean` | `false` |
| zIndex | 弹窗的ZIndex层级 | `number` | `1000` | | zIndex | 弹窗的ZIndex层级 | `number` | `1000` |
| overlayBlur | 遮罩模糊度 | `number` | - | | overlayBlur | 遮罩模糊度 | `number` | - |
| submitting | 标记为提交中,锁定弹窗当前状态 | `boolean` | `false` |
::: info appendToMain ::: info appendToMain
@ -126,7 +127,7 @@ const [Modal, modalApi] = useVbenModal({
| 事件名 | 描述 | 类型 | 版本号 | | 事件名 | 描述 | 类型 | 版本号 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | | | onBeforeClose | 关闭前触发,返回 `false`或者被`reject`则禁止关闭 | `()=>Promise<boolean>\|boolean` | |
| onCancel | 点击取消按钮触发 | `()=>void` | | | onCancel | 点击取消按钮触发 | `()=>void` | |
| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 | | onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 |
| onConfirm | 点击确认按钮触发 | `()=>void` | | | onConfirm | 点击确认按钮触发 | `()=>void` | |
@ -153,3 +154,10 @@ const [Modal, modalApi] = useVbenModal({
| setData | 设置共享数据 | `<T>(data:T)=>modalApi` | | setData | 设置共享数据 | `<T>(data:T)=>modalApi` |
| getData | 获取共享数据 | `<T>()=>T` | | getData | 获取共享数据 | `<T>()=>T` |
| useStore | 获取可响应式状态 | - | | useStore | 获取可响应式状态 | - |
| lock | 将弹窗标记为提交中,锁定当前状态 | `(isLock:boolean)=>modalApi` |
::: info lock
`lock`方法用于锁定当前弹窗的状态一般用于提交数据的过程中防止用户重复提交或者弹窗被意外关闭、表单数据被改变等等。当处于锁定状态时弹窗的确认按钮会变为loading状态同时禁用确认按钮、隐藏关闭按钮、禁止ESC或者点击遮罩等方式关闭弹窗、开启弹窗的spinner动画以遮挡弹窗内容。调用`close`方法关闭处于锁定状态的弹窗时,会自动解锁。
:::

View File

@ -81,3 +81,7 @@
transform: translateY(0); transform: translateY(0);
} }
} }
.z-popup {
z-index: var(--popup-z-index);
}

View File

@ -1,4 +1,6 @@
:root { :root {
/** 弹出层的基础层级 **/
--popup-z-index: 2000;
--font-family: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, --font-family: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto,
'Helvetica Neue', arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Helvetica Neue', arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';

View File

@ -109,6 +109,8 @@ type MergeAll<
type EmitType = (name: Name, ...args: any[]) => void; type EmitType = (name: Name, ...args: any[]) => void;
type MaybePromise<T> = Promise<T> | T;
export type { export type {
AnyFunction, AnyFunction,
AnyNormalFunction, AnyNormalFunction,
@ -118,6 +120,7 @@ export type {
EmitType, EmitType,
IntervalHandle, IntervalHandle,
MaybeComputedRef, MaybeComputedRef,
MaybePromise,
MaybeReadonlyRef, MaybeReadonlyRef,
Merge, Merge,
MergeAll, MergeAll,

View File

@ -404,9 +404,8 @@ export class FormApi {
const deletedSchema = prevSchema.filter( const deletedSchema = prevSchema.filter(
(item) => !currentFields.has(item.fieldName), (item) => !currentFields.has(item.fieldName),
); );
for (const schema of deletedSchema) { for (const schema of deletedSchema) {
this.form?.setFieldValue(schema.fieldName, undefined); this.form?.setFieldValue?.(schema.fieldName, undefined);
} }
} }
} }

View File

@ -95,13 +95,18 @@ export class ModalApi {
/** /**
* *
* @description onBeforeClose onBeforeClose false
*/ */
close() { async close() {
// 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗 // 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗
// 如果 onBeforeClose 返回 false则不关闭弹窗 // 如果 onBeforeClose 返回 false则不关闭弹窗
const allowClose = this.api.onBeforeClose?.() ?? true; const allowClose = (await this.api.onBeforeClose?.()) ?? true;
if (allowClose) { if (allowClose) {
this.store.setState((prev) => ({ ...prev, isOpen: false })); this.store.setState((prev) => ({
...prev,
isOpen: false,
submitting: false,
}));
} }
} }
@ -109,6 +114,15 @@ export class ModalApi {
return (this.sharedData?.payload ?? {}) as T; return (this.sharedData?.payload ?? {}) as T;
} }
/**
*
* @description 使spinner覆盖弹窗内容loading状态
* @param isLocked
*/
lock(isLocked = true) {
return this.setState({ submitting: isLocked });
}
/** /**
* *
*/ */

View File

@ -1,5 +1,7 @@
import type { Component, Ref } from 'vue'; import type { Component, Ref } from 'vue';
import type { MaybePromise } from '@vben-core/typings';
import type { ModalApi } from './modal-api'; import type { ModalApi } from './modal-api';
export interface ModalProps { export interface ModalProps {
@ -113,6 +115,10 @@ export interface ModalProps {
* @default true * @default true
*/ */
showConfirmButton?: boolean; showConfirmButton?: boolean;
/**
*
*/
submitting?: boolean;
/** /**
* *
*/ */
@ -155,7 +161,7 @@ export interface ModalApiOptions extends ModalState {
* false * false
* @returns * @returns
*/ */
onBeforeClose?: () => void; onBeforeClose?: () => MaybePromise<boolean | undefined>;
/** /**
* *
*/ */

View File

@ -80,6 +80,7 @@ const {
overlayBlur, overlayBlur,
showCancelButton, showCancelButton,
showConfirmButton, showConfirmButton,
submitting,
title, title,
titleTooltip, titleTooltip,
zIndex, zIndex,
@ -115,9 +116,9 @@ watch(
); );
watch( watch(
() => showLoading.value, () => [showLoading.value, submitting.value],
(v) => { ([l, s]) => {
if (v && wrapperRef.value) { if ((s || l) && wrapperRef.value) {
wrapperRef.value.scrollTo({ wrapperRef.value.scrollTo({
// behavior: 'smooth', // behavior: 'smooth',
top: 0, top: 0,
@ -135,13 +136,13 @@ function handleFullscreen() {
}); });
} }
function interactOutside(e: Event) { function interactOutside(e: Event) {
if (!closeOnClickModal.value) { if (!closeOnClickModal.value || submitting.value) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
} }
function escapeKeyDown(e: KeyboardEvent) { function escapeKeyDown(e: KeyboardEvent) {
if (!closeOnPressEscape.value) { if (!closeOnPressEscape.value || submitting.value) {
e.preventDefault(); e.preventDefault();
} }
} }
@ -156,7 +157,11 @@ function handerOpenAutoFocus(e: Event) {
function pointerDownOutside(e: Event) { function pointerDownOutside(e: Event) {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
const isDismissableModal = target?.dataset.dismissableModal; const isDismissableModal = target?.dataset.dismissableModal;
if (!closeOnClickModal.value || isDismissableModal !== id) { if (
!closeOnClickModal.value ||
isDismissableModal !== id ||
submitting.value
) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
@ -174,7 +179,7 @@ const getAppendTo = computed(() => {
<Dialog <Dialog
:modal="false" :modal="false"
:open="state?.isOpen" :open="state?.isOpen"
@update:open="() => modalApi?.close()" @update:open="() => (!submitting ? modalApi?.close() : undefined)"
> >
<DialogContent <DialogContent
ref="contentRef" ref="contentRef"
@ -195,7 +200,7 @@ const getAppendTo = computed(() => {
" "
:modal="modal" :modal="modal"
:open="state?.isOpen" :open="state?.isOpen"
:show-close="closable" :show-close="submitting ? false : closable"
:z-index="zIndex" :z-index="zIndex"
:overlay-blur="overlayBlur" :overlay-blur="overlayBlur"
close-class="top-3" close-class="top-3"
@ -247,12 +252,12 @@ const getAppendTo = computed(() => {
ref="wrapperRef" ref="wrapperRef"
:class=" :class="
cn('relative min-h-40 flex-1 overflow-y-auto p-3', contentClass, { cn('relative min-h-40 flex-1 overflow-y-auto p-3', contentClass, {
'pointer-events-none overflow-hidden': showLoading, 'pointer-events-none overflow-hidden': showLoading || submitting,
}) })
" "
> >
<VbenLoading <VbenLoading
v-if="showLoading" v-if="showLoading || submitting"
class="size-full h-auto min-h-full" class="size-full h-auto min-h-full"
spinning spinning
/> />
@ -287,6 +292,7 @@ const getAppendTo = computed(() => {
:is="components.DefaultButton || VbenButton" :is="components.DefaultButton || VbenButton"
v-if="showCancelButton" v-if="showCancelButton"
variant="ghost" variant="ghost"
:disabled="submitting"
@click="() => modalApi?.onCancel()" @click="() => modalApi?.onCancel()"
> >
<slot name="cancelText"> <slot name="cancelText">
@ -298,7 +304,7 @@ const getAppendTo = computed(() => {
:is="components.PrimaryButton || VbenButton" :is="components.PrimaryButton || VbenButton"
v-if="showConfirmButton" v-if="showConfirmButton"
:disabled="confirmDisabled" :disabled="confirmDisabled"
:loading="confirmLoading" :loading="confirmLoading || submitting"
@click="() => modalApi?.onConfirm()" @click="() => modalApi?.onConfirm()"
> >
<slot name="confirmText"> <slot name="confirmText">

View File

@ -32,7 +32,7 @@ const { handleClick, visible } = useBackTop(props);
<VbenButton <VbenButton
v-if="visible" v-if="visible"
:style="backTopStyle" :style="backTopStyle"
class="dark:bg-accent dark:hover:bg-heavy bg-background hover:bg-heavy data shadow-float fixed bottom-10 z-[1000] size-10 rounded-full duration-500" class="dark:bg-accent dark:hover:bg-heavy bg-background hover:bg-heavy data shadow-float z-popup fixed bottom-10 size-10 rounded-full duration-500"
size="icon" size="icon"
variant="icon" variant="icon"
@click="handleClick" @click="handleClick"

View File

@ -69,7 +69,7 @@ function handleClick(menu: IContextMenuItem) {
<ContextMenuContent <ContextMenuContent
:class="contentClass" :class="contentClass"
v-bind="contentProps" v-bind="contentProps"
class="side-content z-[1000]" class="side-content z-popup"
> >
<template v-for="menu in menusView" :key="menu.key"> <template v-for="menu in menusView" :key="menu.key">
<ContextMenuItem <ContextMenuItem

View File

@ -47,7 +47,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
<HoverCardContent <HoverCardContent
:class="contentClass" :class="contentClass"
v-bind="contentProps" v-bind="contentProps"
class="side-content z-[1000]" class="side-content z-popup"
> >
<slot></slot> <slot></slot>
</HoverCardContent> </HoverCardContent>

View File

@ -48,7 +48,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
<PopoverContent <PopoverContent
:class="contentClass" :class="contentClass"
class="side-content z-[1000]" class="side-content z-popup"
v-bind="contentProps" v-bind="contentProps"
> >
<slot></slot> <slot></slot>

View File

@ -32,7 +32,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( cn(
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-[1000] min-w-32 overflow-hidden rounded-md border p-1 shadow-md', 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-popup min-w-32 overflow-hidden rounded-md border p-1 shadow-md',
props.class, props.class,
) )
" "

View File

@ -30,7 +30,7 @@ const props = withDefaults(
zIndex?: number; zIndex?: number;
} }
>(), >(),
{ appendTo: 'body', showClose: true, zIndex: 1000 }, { appendTo: 'body', showClose: true },
); );
const emits = defineEmits< const emits = defineEmits<
DialogContentEmits & { close: []; closed: []; opened: [] } DialogContentEmits & { close: []; closed: []; opened: [] }
@ -84,7 +84,7 @@ defineExpose({
<DialogOverlay <DialogOverlay
v-if="open && modal" v-if="open && modal"
:style="{ :style="{
zIndex, ...(zIndex ? { zIndex } : {}),
position, position,
backdropFilter: backdropFilter:
overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none', overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
@ -94,12 +94,12 @@ defineExpose({
</Transition> </Transition>
<DialogContent <DialogContent
ref="contentRef" ref="contentRef"
:style="{ zIndex, position }" :style="{ ...(zIndex ? { zIndex } : {}), position }"
@animationend="onAnimationEnd" @animationend="onAnimationEnd"
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-top-[48%] w-full p-6 shadow-lg outline-none sm:rounded-xl', 'z-popup bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-top-[48%] w-full p-6 shadow-lg outline-none sm:rounded-xl',
props.class, props.class,
) )
" "

View File

@ -7,5 +7,5 @@ useScrollLock();
const id = inject('DISMISSABLE_MODAL_ID'); const id = inject('DISMISSABLE_MODAL_ID');
</script> </script>
<template> <template>
<div :data-dismissable-modal="id" class="bg-overlay inset-0"></div> <div :data-dismissable-modal="id" class="bg-overlay z-popup inset-0"></div>
</template> </template>

View File

@ -37,7 +37,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( cn(
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-[1000] min-w-32 overflow-hidden rounded-md border p-1 shadow-md', 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-popup min-w-32 overflow-hidden rounded-md border p-1 shadow-md',
props.class, props.class,
) )
" "

View File

@ -29,7 +29,7 @@ const forwardedProps = useForwardProps(delegatedProps);
v-bind="forwardedProps" v-bind="forwardedProps"
:class=" :class="
cn( cn(
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-[1000] w-64 rounded-md border p-4 shadow-md outline-none', 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-popup w-64 rounded-md border p-4 shadow-md outline-none',
props.class, props.class,
) )
" "

View File

@ -42,7 +42,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...forwarded, ...$attrs }" v-bind="{ ...forwarded, ...$attrs }"
:class=" :class="
cn( cn(
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border relative z-[1000] max-h-96 min-w-32 overflow-hidden rounded-md border shadow-md', 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-popup relative max-h-96 min-w-32 overflow-hidden rounded-md border shadow-md',
position === 'popper' && position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
props.class, props.class,

View File

@ -28,7 +28,6 @@ defineOptions({
const props = withDefaults(defineProps<SheetContentProps>(), { const props = withDefaults(defineProps<SheetContentProps>(), {
appendTo: 'body', appendTo: 'body',
zIndex: 1000,
}); });
const emits = defineEmits< const emits = defineEmits<
@ -79,7 +78,7 @@ function onAnimationEnd(event: AnimationEvent) {
<SheetOverlay <SheetOverlay
v-if="open && modal" v-if="open && modal"
:style="{ :style="{
zIndex, ...(zIndex ? { zIndex } : {}),
position, position,
backdropFilter: backdropFilter:
overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none', overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
@ -88,9 +87,9 @@ function onAnimationEnd(event: AnimationEvent) {
</Transition> </Transition>
<DialogContent <DialogContent
ref="contentRef" ref="contentRef"
:class="cn(sheetVariants({ side }), props.class)" :class="cn('z-popup', sheetVariants({ side }), props.class)"
:style="{ :style="{
zIndex, ...(zIndex ? { zIndex } : {}),
position, position,
}" }"
@animationend="onAnimationEnd" @animationend="onAnimationEnd"

View File

@ -7,5 +7,5 @@ useScrollLock();
const id = inject('DISMISSABLE_DRAWER_ID'); const id = inject('DISMISSABLE_DRAWER_ID');
</script> </script>
<template> <template>
<div :data-dismissable-drawer="id" class="bg-overlay inset-0"></div> <div :data-dismissable-drawer="id" class="bg-overlay z-popup inset-0"></div>
</template> </template>

View File

@ -37,7 +37,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
v-bind="{ ...forwarded, ...$attrs }" v-bind="{ ...forwarded, ...$attrs }"
:class=" :class="
cn( cn(
'bg-accent text-accent-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border shadow-float z-[1000] overflow-hidden rounded-sm border px-4 py-2 text-xs', 'z-popup bg-accent text-accent-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border shadow-float overflow-hidden rounded-sm border px-4 py-2 text-xs',
props.class, props.class,
) )
" "

View File

@ -25,6 +25,7 @@ export function useAntdDesignTokens() {
colorSuccess: '', colorSuccess: '',
colorTextBase: '', colorTextBase: '',
colorWarning: '', colorWarning: '',
zIndexPopupBase: 2000, // 调整基础弹层层级,避免下拉等组件被弹窗或者最大化状态下的表格遮挡
}); });
const getCssVariableValue = (variable: string, isColor: boolean = true) => { const getCssVariableValue = (variable: string, isColor: boolean = true) => {

View File

@ -54,7 +54,3 @@
.ant-app .form-valid-error .ant-picker-focused { .ant-app .form-valid-error .ant-picker-focused {
box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); box-shadow: 0 0 0 2px rgb(255 38 5 / 6%);
} }
.ant-message {
z-index: 1050;
}

View File

@ -1,11 +1,7 @@
import { createApp, watchEffect } from 'vue'; import { createApp, watchEffect } from 'vue';
import { registerAccessDirective } from '@vben/access'; import { registerAccessDirective } from '@vben/access';
import { import { initTippy } from '@vben/common-ui';
initTippy,
setDefaultDrawerProps,
setDefaultModalProps,
} from '@vben/common-ui';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { initStores } from '@vben/stores'; import { initStores } from '@vben/stores';
import '@vben/styles'; import '@vben/styles';
@ -24,15 +20,14 @@ async function bootstrap(namespace: string) {
// 初始化组件适配器 // 初始化组件适配器
await initComponentAdapter(); await initComponentAdapter();
// 设置弹窗的默认配置 // // 设置弹窗的默认配置
setDefaultModalProps({ // setDefaultModalProps({
fullscreenButton: false, // fullscreenButton: false,
zIndex: 1020, // });
}); // // 设置抽屉的默认配置
// 设置抽屉的默认配置 // setDefaultDrawerProps({
setDefaultDrawerProps({ // // zIndex: 1020,
zIndex: 1020, // });
});
const app = createApp(App); const app = createApp(App);

View File

@ -9,10 +9,6 @@ defineOptions({
name: 'FormModelDemo', name: 'FormModelDemo',
}); });
function onSubmit(values: Record<string, any>) {
message.info(JSON.stringify(values)); //
}
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
handleSubmit: onSubmit, handleSubmit: onSubmit,
schema: [ schema: [
@ -70,6 +66,23 @@ const [Modal, modalApi] = useVbenModal({
}, },
title: '内嵌表单示例', title: '内嵌表单示例',
}); });
function onSubmit(values: Record<string, any>) {
message.loading({
content: '正在提交中...',
duration: 0,
key: 'is-form-submitting',
});
modalApi.lock();
setTimeout(() => {
modalApi.close();
message.success({
content: `提交成功:${JSON.stringify(values)}`,
duration: 2,
key: 'is-form-submitting',
});
}, 3000);
}
</script> </script>
<template> <template>
<Modal> <Modal>

View File

@ -97,7 +97,7 @@ function openFormModal() {
formModalApi formModalApi
.setData({ .setData({
// //
values: { field1: 'abc' }, values: { field1: 'abc', field2: '123' },
}) })
.open(); .open();
} }