mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-01-23 09:40:25 +08:00
Merge branch 'main' into rounded
This commit is contained in:
commit
19497e0427
@ -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);
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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指令
|
||||||
|
@ -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',
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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`方法关闭处于锁定状态的弹窗时,会自动解锁。
|
||||||
|
|
||||||
|
:::
|
||||||
|
@ -81,3 +81,7 @@
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.z-popup {
|
||||||
|
z-index: var(--popup-z-index);
|
||||||
|
}
|
||||||
|
@ -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';
|
||||||
|
3
packages/@core/base/typings/src/helper.d.ts
vendored
3
packages/@core/base/typings/src/helper.d.ts
vendored
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消操作
|
* 取消操作
|
||||||
*/
|
*/
|
||||||
|
@ -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>;
|
||||||
/**
|
/**
|
||||||
* 点击取消按钮的回调
|
* 点击取消按钮的回调
|
||||||
*/
|
*/
|
||||||
|
@ -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">
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -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,
|
||||||
|
@ -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"
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -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) => {
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -97,7 +97,7 @@ function openFormModal() {
|
|||||||
formModalApi
|
formModalApi
|
||||||
.setData({
|
.setData({
|
||||||
// 表单值
|
// 表单值
|
||||||
values: { field1: 'abc' },
|
values: { field1: 'abc', field2: '123' },
|
||||||
})
|
})
|
||||||
.open();
|
.open();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user