Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
This commit is contained in:
@@ -53,7 +53,6 @@ export const MOCK_CODES = [
|
||||
|
||||
const dashboardMenus = [
|
||||
{
|
||||
component: 'BasicLayout',
|
||||
meta: {
|
||||
order: -1,
|
||||
title: 'page.dashboard.title',
|
||||
@@ -116,7 +115,6 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||
|
||||
return [
|
||||
{
|
||||
component: 'BasicLayout',
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
|
@@ -20,6 +20,15 @@ async function bootstrap(namespace: string) {
|
||||
// 初始化组件适配器
|
||||
await initComponentAdapter();
|
||||
|
||||
// // 设置弹窗的默认配置
|
||||
// setDefaultModalProps({
|
||||
// fullscreenButton: false,
|
||||
// });
|
||||
// // 设置抽屉的默认配置
|
||||
// setDefaultDrawerProps({
|
||||
// zIndex: 1020,
|
||||
// });
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
// 全局组件
|
||||
|
@@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
import { AuthPageLayout } from '#/layouts';
|
||||
import { AuthPageLayout, BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
import Login from '#/views/_core/authentication/login.vue';
|
||||
|
||||
@@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = {
|
||||
|
||||
/** 基本路由,这些路由是必须存在的 */
|
||||
const coreRoutes: RouteRecordRaw[] = [
|
||||
/**
|
||||
* 根路由
|
||||
* 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。
|
||||
* 此路由必须存在,且不应修改
|
||||
*/
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
hideInBreadcrumb: true,
|
||||
title: 'Root',
|
||||
},
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: DEFAULT_HOME_PATH,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
component: () => import('#/views/_core/social-callback/index.vue'),
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
|
@@ -8,16 +8,15 @@ import {
|
||||
VBEN_NAIVE_PREVIEW_URL,
|
||||
} from '@vben/constants';
|
||||
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
badgeType: 'dot',
|
||||
icon: VBEN_LOGO_URL,
|
||||
order: 9999,
|
||||
order: 9998,
|
||||
title: $t('demos.vben.title'),
|
||||
},
|
||||
name: 'VbenProject',
|
||||
@@ -76,6 +75,16 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
title: $t('demos.vben.about'),
|
||||
order: 9999,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
|
@@ -19,6 +19,14 @@ import { router } from './router';
|
||||
async function bootstrap(namespace: string) {
|
||||
// 初始化组件适配器
|
||||
await initComponentAdapter();
|
||||
// // 设置弹窗的默认配置
|
||||
// setDefaultModalProps({
|
||||
// fullscreenButton: false,
|
||||
// });
|
||||
// // 设置抽屉的默认配置
|
||||
// setDefaultDrawerProps({
|
||||
// zIndex: 2000,
|
||||
// });
|
||||
const app = createApp(App);
|
||||
|
||||
// 注册Element Plus提供的v-loading指令
|
||||
|
@@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
import { AuthPageLayout } from '#/layouts';
|
||||
import { AuthPageLayout, BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
import Login from '#/views/_core/authentication/login.vue';
|
||||
|
||||
@@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = {
|
||||
|
||||
/** 基本路由,这些路由是必须存在的 */
|
||||
const coreRoutes: RouteRecordRaw[] = [
|
||||
/**
|
||||
* 根路由
|
||||
* 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。
|
||||
* 此路由必须存在,且不应修改
|
||||
*/
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
hideInBreadcrumb: true,
|
||||
title: 'Root',
|
||||
},
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: DEFAULT_HOME_PATH,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
component: AuthPageLayout,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
|
@@ -9,30 +9,20 @@ import {
|
||||
} from '@vben/constants';
|
||||
import { SvgAntdvLogoIcon } from '@vben/icons';
|
||||
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
badgeType: 'dot',
|
||||
icon: VBEN_LOGO_URL,
|
||||
order: 9999,
|
||||
order: 9998,
|
||||
title: $t('demos.vben.title'),
|
||||
},
|
||||
name: 'VbenProject',
|
||||
path: '/vben-admin',
|
||||
children: [
|
||||
{
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
title: $t('demos.vben.about'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'VbenDocument',
|
||||
path: '/vben-admin/document',
|
||||
@@ -77,6 +67,16 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
title: $t('demos.vben.about'),
|
||||
order: 9999,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
|
@@ -18,6 +18,16 @@ import { router } from './router';
|
||||
async function bootstrap(namespace: string) {
|
||||
// 初始化组件适配器
|
||||
initComponentAdapter();
|
||||
|
||||
// // 设置弹窗的默认配置
|
||||
// setDefaultModalProps({
|
||||
// fullscreenButton: false,
|
||||
// });
|
||||
// // 设置抽屉的默认配置
|
||||
// setDefaultDrawerProps({
|
||||
// // zIndex: 2000,
|
||||
// });
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
// 国际化 i18n 配置
|
||||
|
@@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
import { AuthPageLayout } from '#/layouts';
|
||||
import { AuthPageLayout, BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
import Login from '#/views/_core/authentication/login.vue';
|
||||
|
||||
@@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = {
|
||||
|
||||
/** 基本路由,这些路由是必须存在的 */
|
||||
const coreRoutes: RouteRecordRaw[] = [
|
||||
/**
|
||||
* 根路由
|
||||
* 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。
|
||||
* 此路由必须存在,且不应修改
|
||||
*/
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
hideInBreadcrumb: true,
|
||||
title: 'Root',
|
||||
},
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: DEFAULT_HOME_PATH,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
component: AuthPageLayout,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
|
@@ -9,30 +9,20 @@ import {
|
||||
} from '@vben/constants';
|
||||
import { SvgAntdvLogoIcon } from '@vben/icons';
|
||||
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
badgeType: 'dot',
|
||||
icon: VBEN_LOGO_URL,
|
||||
order: 9999,
|
||||
order: 9998,
|
||||
title: $t('demos.vben.title'),
|
||||
},
|
||||
name: 'VbenProject',
|
||||
path: '/vben-admin',
|
||||
children: [
|
||||
{
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
title: $t('demos.vben.about'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'VbenDocument',
|
||||
path: '/vben-admin/document',
|
||||
@@ -77,6 +67,16 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
title: $t('demos.vben.about'),
|
||||
order: 9999,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
|
@@ -55,6 +55,7 @@ Drawer 内的内容一般业务中,会比较复杂,所以我们可以将 dra
|
||||
- `VbenDrawer` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenDrawer参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。
|
||||
- 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。
|
||||
- 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。
|
||||
- 如果抽屉的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultDrawerProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。
|
||||
|
||||
:::
|
||||
|
||||
|
@@ -316,7 +316,7 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单
|
||||
| collapsed | 是否折叠,在`showCollapseButton`为`true`时生效 | `boolean` | `false` |
|
||||
| collapseTriggerResize | 折叠时,触发`resize`事件 | `boolean` | `false` |
|
||||
| collapsedRows | 折叠时保持的行数 | `number` | `1` |
|
||||
| fieldMappingTime | 用于将表单内的数组值值映射成 2 个字段 | `[string, [string, string],Nullable<string>?][]` | - |
|
||||
| fieldMappingTime | 用于将表单内的数组值值映射成 2 个字段 | `[string, [string, string],Nullable<string>\|[string,string]\|((any,string)=>any)?][]` | - |
|
||||
| commonConfig | 表单项的通用配置,每个配置都会传递到每个表单项,表单项可覆盖 | `FormCommonConfig` | - |
|
||||
| schema | 表单项的每一项配置 | `FormSchema[]` | - |
|
||||
| submitOnEnter | 按下回车健时提交表单 | `boolean` | false |
|
||||
@@ -324,7 +324,7 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单
|
||||
|
||||
::: tip fieldMappingTime
|
||||
|
||||
此属性用于将表单内的数组值映射成 2 个字段,例如:`[['timeRange', ['startTime', 'endTime'], 'YYYY-MM-DD']]`,`timeRange`应当是一个至少具有2个成员的数组类型的值。Form会将`timeRange`的值前两个值分别按照格式掩码`YYYY-MM-DD`格式化后映射到`startTime`和`endTime`字段上。如果明确地将格式掩码设为null,则原值映射而不进行格式化(适用于非日期时间字段)。
|
||||
此属性用于将表单内的数组值映射成 2 个字段,它应当传入一个数组,数组的每一项是一个映射规则,规则的第一个成员是一个字符串,表示需要映射的字段名,第二个成员是一个数组,表示映射后的字段名,第三个成员是一个可选的格式掩码,用于格式化日期时间字段;也可以提供一个格式化函数(参数分别为当前值和当前字段名,返回格式化后的值)。如果明确地将格式掩码设为null,则原值映射而不进行格式化(适用于非日期时间字段)。例如:`[['timeRange', ['startTime', 'endTime'], 'YYYY-MM-DD']]`,`timeRange`应当是一个至少具有2个成员的数组类型的值。Form会将`timeRange`的值前两个值分别按照格式掩码`YYYY-MM-DD`格式化后映射到`startTime`和`endTime`字段上。每一项的第三个参数是一个可选的格式掩码,
|
||||
|
||||
:::
|
||||
|
||||
|
@@ -61,6 +61,7 @@ Modal 内的内容一般业务中,会比较复杂,所以我们可以将 moda
|
||||
- `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。
|
||||
- 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。
|
||||
- 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。
|
||||
- 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。
|
||||
|
||||
:::
|
||||
|
||||
|
@@ -73,7 +73,6 @@ import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
badgeType: 'dot',
|
||||
badgeVariants: 'destructive',
|
||||
@@ -124,7 +123,6 @@ import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
@@ -249,7 +247,6 @@ import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'mdi:home',
|
||||
title: $t('page.home.title'),
|
||||
|
@@ -62,12 +62,10 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { VBEN_LOGO_URL } from '@vben/constants';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
badgeType: 'dot',
|
||||
badgeVariants: 'destructive',
|
||||
@@ -103,7 +101,6 @@ export default routes;
|
||||
|
||||
::: tip
|
||||
|
||||
- 多级路由的父级路由无需设置 `component` 属性,只需设置 `children` 属性即可。除非你真的需要在父级路由嵌套下显示内容。
|
||||
- 如果没有特殊情况,父级路由的 `redirect` 属性,不需要指定,默认会指向第一个子路由。
|
||||
|
||||
:::
|
||||
@@ -113,12 +110,10 @@ export default routes;
|
||||
```ts
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
@@ -238,12 +233,10 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { VBEN_LOGO_URL } from '@vben/constants';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'mdi:home',
|
||||
title: $t('page.home.title'),
|
||||
@@ -400,6 +393,10 @@ interface RouteMeta {
|
||||
* 菜单可以看到,但是访问会被重定向到403
|
||||
*/
|
||||
menuVisibleWithForbidden?: boolean;
|
||||
/**
|
||||
* 当前路由不使用基础布局(仅在顶级生效)
|
||||
*/
|
||||
noBasicLayout?: boolean;
|
||||
/**
|
||||
* 在新窗口打开
|
||||
*/
|
||||
@@ -584,6 +581,13 @@ _注意:_ 排序仅针对一级菜单有效,二级菜单的排序需要在对
|
||||
|
||||
用于配置页面的菜单参数,会在菜单中传递给页面。
|
||||
|
||||
### noBasicLayout
|
||||
|
||||
- 类型:`boolean`
|
||||
- 默认值:`false`
|
||||
|
||||
用于配置当前路由不使用基础布局,仅在顶级时生效。默认情况下,所有的路由都会被包裹在基础布局中(包含顶部以及侧边等导航部件),如果你的页面不需要这些部件,可以设置 `noBasicLayout` 为 `true`。
|
||||
|
||||
## 路由刷新
|
||||
|
||||
路由刷新方式如下:
|
||||
|
@@ -81,3 +81,7 @@
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.z-popup {
|
||||
z-index: var(--popup-z-index);
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
:root {
|
||||
/** 弹出层的基础层级 **/
|
||||
--popup-z-index: 2000;
|
||||
--font-family: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto,
|
||||
'Helvetica Neue', arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
|
11
packages/@core/base/typings/src/vue-router.d.ts
vendored
11
packages/@core/base/typings/src/vue-router.d.ts
vendored
@@ -97,6 +97,10 @@ interface RouteMeta {
|
||||
* 菜单可以看到,但是访问会被重定向到403
|
||||
*/
|
||||
menuVisibleWithForbidden?: boolean;
|
||||
/**
|
||||
* 不使用基础布局(仅在顶级生效)
|
||||
*/
|
||||
noBasicLayout?: boolean;
|
||||
/**
|
||||
* 在新窗口打开
|
||||
*/
|
||||
@@ -116,10 +120,13 @@ interface RouteMeta {
|
||||
}
|
||||
|
||||
// 定义递归类型以将 RouteRecordRaw 的 component 属性更改为 string
|
||||
type RouteRecordStringComponent<T = string> = {
|
||||
type RouteRecordStringComponent<T = string> = Omit<
|
||||
RouteRecordRaw,
|
||||
'children' | 'component'
|
||||
> & {
|
||||
children?: RouteRecordStringComponent<T>[];
|
||||
component: T;
|
||||
} & Omit<RouteRecordRaw, 'children' | 'component'>;
|
||||
};
|
||||
|
||||
type ComponentRecordType = Record<string, () => Promise<Component>>;
|
||||
|
||||
|
@@ -371,6 +371,9 @@ export class FormApi {
|
||||
if (format === null) {
|
||||
values[startTimeKey] = startTime;
|
||||
values[endTimeKey] = endTime;
|
||||
} else if (isFunction(format)) {
|
||||
values[startTimeKey] = format(startTime, startTimeKey);
|
||||
values[endTimeKey] = format(endTime, endTimeKey);
|
||||
} else {
|
||||
const [startTimeFormat, endTimeFormat] = Array.isArray(format)
|
||||
? format
|
||||
|
@@ -4,7 +4,7 @@ import type { ZodTypeAny } from 'zod';
|
||||
import type { Component, HtmlHTMLAttributes, Ref } from 'vue';
|
||||
|
||||
import type { VbenButtonProps } from '@vben-core/shadcn-ui';
|
||||
import type { ClassType, MaybeComputedRef, Nullable } from '@vben-core/typings';
|
||||
import type { ClassType, MaybeComputedRef } from '@vben-core/typings';
|
||||
|
||||
import type { FormApi } from './form-api';
|
||||
|
||||
@@ -224,7 +224,12 @@ export type HandleResetFn = (
|
||||
export type FieldMappingTime = [
|
||||
string,
|
||||
[string, string],
|
||||
([string, string] | Nullable<string>)?,
|
||||
(
|
||||
| ((value: any, fieldName: string) => any)
|
||||
| [string, string]
|
||||
| null
|
||||
| string
|
||||
)?,
|
||||
][];
|
||||
|
||||
export interface FormSchema<
|
||||
|
@@ -1,3 +1,3 @@
|
||||
export type * from './drawer';
|
||||
export { default as VbenDrawer } from './drawer.vue';
|
||||
export { useVbenDrawer } from './use-drawer';
|
||||
export { setDefaultDrawerProps, useVbenDrawer } from './use-drawer';
|
||||
|
@@ -4,7 +4,6 @@ import type {
|
||||
ExtendedDrawerApi,
|
||||
} from './drawer';
|
||||
|
||||
import { useStore } from '@vben-core/shared/store';
|
||||
import {
|
||||
defineComponent,
|
||||
h,
|
||||
@@ -15,11 +14,19 @@ import {
|
||||
ref,
|
||||
} from 'vue';
|
||||
|
||||
import VbenDrawer from './drawer.vue';
|
||||
import { useStore } from '@vben-core/shared/store';
|
||||
|
||||
import { DrawerApi } from './drawer-api';
|
||||
import VbenDrawer from './drawer.vue';
|
||||
|
||||
const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT');
|
||||
|
||||
const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {};
|
||||
|
||||
export function setDefaultDrawerProps(props: Partial<DrawerProps>) {
|
||||
Object.assign(DEFAULT_DRAWER_PROPS, props);
|
||||
}
|
||||
|
||||
export function useVbenDrawer<
|
||||
TParentDrawerProps extends DrawerProps = DrawerProps,
|
||||
>(options: DrawerApiOptions = {}) {
|
||||
@@ -68,6 +75,7 @@ export function useVbenDrawer<
|
||||
const injectData = inject<any>(USER_DRAWER_INJECT_KEY, {});
|
||||
|
||||
const mergedOptions = {
|
||||
...DEFAULT_DRAWER_PROPS,
|
||||
...injectData.options,
|
||||
...options,
|
||||
} as DrawerApiOptions;
|
||||
|
@@ -1,3 +1,3 @@
|
||||
export type * from './modal';
|
||||
export { default as VbenModal } from './modal.vue';
|
||||
export { useVbenModal } from './use-modal';
|
||||
export { setDefaultModalProps, useVbenModal } from './use-modal';
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import type { ExtendedModalApi, ModalApiOptions, ModalProps } from './modal';
|
||||
|
||||
import { useStore } from '@vben-core/shared/store';
|
||||
import {
|
||||
defineComponent,
|
||||
h,
|
||||
@@ -11,11 +10,19 @@ import {
|
||||
ref,
|
||||
} from 'vue';
|
||||
|
||||
import VbenModal from './modal.vue';
|
||||
import { useStore } from '@vben-core/shared/store';
|
||||
|
||||
import { ModalApi } from './modal-api';
|
||||
import VbenModal from './modal.vue';
|
||||
|
||||
const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT');
|
||||
|
||||
const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {};
|
||||
|
||||
export function setDefaultModalProps(props: Partial<ModalProps>) {
|
||||
Object.assign(DEFAULT_MODAL_PROPS, props);
|
||||
}
|
||||
|
||||
export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
|
||||
options: ModalApiOptions = {},
|
||||
) {
|
||||
@@ -67,6 +74,7 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
|
||||
const injectData = inject<any>(USER_MODAL_INJECT_KEY, {});
|
||||
|
||||
const mergedOptions = {
|
||||
...DEFAULT_MODAL_PROPS,
|
||||
...injectData.options,
|
||||
...options,
|
||||
} as ModalApiOptions;
|
||||
|
@@ -32,7 +32,7 @@ const { handleClick, visible } = useBackTop(props);
|
||||
<VbenButton
|
||||
v-if="visible"
|
||||
: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"
|
||||
variant="icon"
|
||||
@click="handleClick"
|
||||
|
@@ -1,16 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
import type {
|
||||
ContextMenuContentProps,
|
||||
ContextMenuRootEmits,
|
||||
ContextMenuRootProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
|
||||
import type { IContextMenuItem } from './interface';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
@@ -21,14 +23,14 @@ import {
|
||||
} from '../../ui/context-menu';
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
ContextMenuRootProps & {
|
||||
class?: ClassType;
|
||||
contentClass?: ClassType;
|
||||
contentProps?: ContextMenuContentProps;
|
||||
handlerData?: Record<string, any>;
|
||||
itemClass?: ClassType;
|
||||
menus: (data: any) => IContextMenuItem[];
|
||||
} & ContextMenuRootProps
|
||||
}
|
||||
>();
|
||||
|
||||
const emits = defineEmits<ContextMenuRootEmits>();
|
||||
@@ -67,7 +69,7 @@ function handleClick(menu: IContextMenuItem) {
|
||||
<ContextMenuContent
|
||||
:class="contentClass"
|
||||
v-bind="contentProps"
|
||||
class="side-content z-[1000]"
|
||||
class="side-content z-popup"
|
||||
>
|
||||
<template v-for="menu in menusView" :key="menu.key">
|
||||
<ContextMenuItem
|
||||
|
@@ -1,14 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
import type {
|
||||
HoverCardContentProps,
|
||||
HoverCardRootEmits,
|
||||
HoverCardRootProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '../../ui';
|
||||
|
||||
interface Props extends HoverCardRootProps {
|
||||
@@ -45,7 +47,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
<HoverCardContent
|
||||
:class="contentClass"
|
||||
v-bind="contentProps"
|
||||
class="side-content z-[1000]"
|
||||
class="side-content z-popup"
|
||||
>
|
||||
<slot></slot>
|
||||
</HoverCardContent>
|
||||
|
@@ -1,14 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
import type {
|
||||
PopoverContentProps,
|
||||
PopoverRootEmits,
|
||||
PopoverRootProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
import {
|
||||
PopoverContent,
|
||||
Popover as PopoverRoot,
|
||||
@@ -46,7 +48,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
|
||||
<PopoverContent
|
||||
:class="contentClass"
|
||||
class="side-content z-[1000]"
|
||||
class="side-content z-popup"
|
||||
v-bind="contentProps"
|
||||
>
|
||||
<slot></slot>
|
||||
|
@@ -4,15 +4,17 @@ import type {
|
||||
ContextMenuContentProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import {
|
||||
ContextMenuContent,
|
||||
ContextMenuPortal,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{ class?: any } & ContextMenuContentProps>();
|
||||
const props = defineProps<ContextMenuContentProps & { class?: any }>();
|
||||
const emits = defineEmits<ContextMenuContentEmits>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
@@ -30,7 +32,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
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,
|
||||
)
|
||||
"
|
||||
|
@@ -30,7 +30,7 @@ const props = withDefaults(
|
||||
zIndex?: number;
|
||||
}
|
||||
>(),
|
||||
{ appendTo: 'body', showClose: true, zIndex: 1000 },
|
||||
{ appendTo: 'body', showClose: true },
|
||||
);
|
||||
const emits = defineEmits<
|
||||
DialogContentEmits & { close: []; closed: []; opened: [] }
|
||||
@@ -84,7 +84,7 @@ defineExpose({
|
||||
<DialogOverlay
|
||||
v-if="open && modal"
|
||||
:style="{
|
||||
zIndex,
|
||||
...(zIndex ? { zIndex } : {}),
|
||||
position,
|
||||
backdropFilter:
|
||||
overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
|
||||
@@ -94,12 +94,12 @@ defineExpose({
|
||||
</Transition>
|
||||
<DialogContent
|
||||
ref="contentRef"
|
||||
:style="{ zIndex, position }"
|
||||
:style="{ ...(zIndex ? { zIndex } : {}), position }"
|
||||
@animationend="onAnimationEnd"
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
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,
|
||||
)
|
||||
"
|
||||
|
@@ -7,5 +7,5 @@ useScrollLock();
|
||||
const id = inject('DISMISSABLE_MODAL_ID');
|
||||
</script>
|
||||
<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>
|
||||
|
@@ -4,16 +4,18 @@ import type {
|
||||
DropdownMenuContentProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuPortal,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{ class?: any } & DropdownMenuContentProps>(),
|
||||
defineProps<DropdownMenuContentProps & { class?: any }>(),
|
||||
{
|
||||
sideOffset: 4,
|
||||
},
|
||||
@@ -35,7 +37,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
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,
|
||||
)
|
||||
"
|
||||
|
@@ -1,12 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { HoverCardContentProps } from 'radix-vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
import { HoverCardContent, HoverCardPortal, useForwardProps } from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { HoverCardContent, HoverCardPortal, useForwardProps } from 'radix-vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{ class?: any } & HoverCardContentProps>(),
|
||||
defineProps<HoverCardContentProps & { class?: any }>(),
|
||||
{
|
||||
sideOffset: 4,
|
||||
},
|
||||
@@ -27,7 +29,7 @@ const forwardedProps = useForwardProps(delegatedProps);
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
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,
|
||||
)
|
||||
"
|
||||
|
@@ -1,14 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { SelectContentEmits, SelectContentProps } from 'radix-vue';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import {
|
||||
SelectContent,
|
||||
SelectPortal,
|
||||
SelectViewport,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import SelectScrollDownButton from './SelectScrollDownButton.vue';
|
||||
import SelectScrollUpButton from './SelectScrollUpButton.vue';
|
||||
@@ -18,7 +20,7 @@ defineOptions({
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{ class?: any } & SelectContentProps>(),
|
||||
defineProps<SelectContentProps & { class?: any }>(),
|
||||
{
|
||||
position: 'popper',
|
||||
},
|
||||
@@ -40,7 +42,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
v-bind="{ ...forwarded, ...$attrs }"
|
||||
:class="
|
||||
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' &&
|
||||
'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,
|
||||
|
@@ -28,7 +28,6 @@ defineOptions({
|
||||
|
||||
const props = withDefaults(defineProps<SheetContentProps>(), {
|
||||
appendTo: 'body',
|
||||
zIndex: 1000,
|
||||
});
|
||||
|
||||
const emits = defineEmits<
|
||||
@@ -79,7 +78,7 @@ function onAnimationEnd(event: AnimationEvent) {
|
||||
<SheetOverlay
|
||||
v-if="open && modal"
|
||||
:style="{
|
||||
zIndex,
|
||||
...(zIndex ? { zIndex } : {}),
|
||||
position,
|
||||
backdropFilter:
|
||||
overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
|
||||
@@ -88,9 +87,9 @@ function onAnimationEnd(event: AnimationEvent) {
|
||||
</Transition>
|
||||
<DialogContent
|
||||
ref="contentRef"
|
||||
:class="cn(sheetVariants({ side }), props.class)"
|
||||
:class="cn('z-popup', sheetVariants({ side }), props.class)"
|
||||
:style="{
|
||||
zIndex,
|
||||
...(zIndex ? { zIndex } : {}),
|
||||
position,
|
||||
}"
|
||||
@animationend="onAnimationEnd"
|
||||
|
@@ -7,5 +7,5 @@ useScrollLock();
|
||||
const id = inject('DISMISSABLE_DRAWER_ID');
|
||||
</script>
|
||||
<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>
|
||||
|
@@ -1,16 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import type { TooltipContentEmits, TooltipContentProps } from 'radix-vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
import { TooltipContent, TooltipPortal, useForwardPropsEmits } from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { TooltipContent, TooltipPortal, useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{ class?: any } & TooltipContentProps>(),
|
||||
defineProps<TooltipContentProps & { class?: any }>(),
|
||||
{
|
||||
class: '',
|
||||
side: 'right',
|
||||
@@ -35,7 +37,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
v-bind="{ ...forwarded, ...$attrs }"
|
||||
:class="
|
||||
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,
|
||||
)
|
||||
"
|
||||
|
@@ -23,6 +23,8 @@ async function generateAccessible(
|
||||
// 生成路由
|
||||
const accessibleRoutes = await generateRoutes(mode, options);
|
||||
|
||||
const root = router.getRoutes().find((item) => item.path === '/');
|
||||
|
||||
// 动态添加到router实例内
|
||||
accessibleRoutes.forEach((route) => {
|
||||
/**
|
||||
@@ -31,9 +33,26 @@ async function generateAccessible(
|
||||
if (/^https?:\/\//.test(route.path)) {
|
||||
return;
|
||||
}
|
||||
if (root && !route.meta?.noBasicLayout) {
|
||||
// 为了兼容之前的版本用法,如果包含子路由,则将component移除,以免出现多层BasicLayout
|
||||
// 如果你的项目已经跟进了本次修改,移除了所有自定义菜单首级的BasicLayout,可以将这段if代码删除
|
||||
// TODO: 这里后期需要follow更新
|
||||
if (route.children && route.children.length > 0) {
|
||||
delete route.component;
|
||||
}
|
||||
root.children?.push(route);
|
||||
} else {
|
||||
router.addRoute(route);
|
||||
}
|
||||
});
|
||||
|
||||
if (root) {
|
||||
if (root.name) {
|
||||
router.removeRoute(root.name);
|
||||
}
|
||||
router.addRoute(root);
|
||||
}
|
||||
|
||||
// 生成菜单
|
||||
const accessibleMenus = await generateMenus(accessibleRoutes, options.router);
|
||||
|
||||
|
@@ -25,6 +25,7 @@ export function useAntdDesignTokens() {
|
||||
colorSuccess: '',
|
||||
colorTextBase: '',
|
||||
colorWarning: '',
|
||||
zIndexPopupBase: 2000, // 调整基础弹层层级,避免下拉等组件被弹窗或者最大化状态下的表格遮挡
|
||||
});
|
||||
|
||||
const getCssVariableValue = (variable: string, isColor: boolean = true) => {
|
||||
|
@@ -112,3 +112,7 @@ button[disabled].btn-success {
|
||||
color: rgb(50 54 57 / 25%) !important;
|
||||
border-color: hsl(240deg 5.9% 90%) !important;
|
||||
}
|
||||
|
||||
.ant-message {
|
||||
z-index: var(--popup-z-index);
|
||||
}
|
||||
|
@@ -38,3 +38,7 @@
|
||||
border: 1px solid var(--el-color-danger);
|
||||
}
|
||||
}
|
||||
|
||||
html .el-loading-mask {
|
||||
z-index: 1000;
|
||||
}
|
||||
|
@@ -20,6 +20,15 @@ async function bootstrap(namespace: string) {
|
||||
// 初始化组件适配器
|
||||
await initComponentAdapter();
|
||||
|
||||
// // 设置弹窗的默认配置
|
||||
// setDefaultModalProps({
|
||||
// fullscreenButton: false,
|
||||
// });
|
||||
// // 设置抽屉的默认配置
|
||||
// setDefaultDrawerProps({
|
||||
// // zIndex: 1020,
|
||||
// });
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
// 国际化 i18n 配置
|
||||
|
@@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
import { AuthPageLayout } from '#/layouts';
|
||||
import { AuthPageLayout, BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
import Login from '#/views/_core/authentication/login.vue';
|
||||
|
||||
@@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = {
|
||||
|
||||
/** 基本路由,这些路由是必须存在的 */
|
||||
const coreRoutes: RouteRecordRaw[] = [
|
||||
/**
|
||||
* 根路由
|
||||
* 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。
|
||||
* 此路由必须存在,且不应修改
|
||||
*/
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
hideInBreadcrumb: true,
|
||||
title: 'Root',
|
||||
},
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: DEFAULT_HOME_PATH,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
component: AuthPageLayout,
|
||||
|
@@ -1,18 +1,16 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
title: $t('page.dashboard.title'),
|
||||
},
|
||||
name: 'Dashboard',
|
||||
path: '/',
|
||||
path: '/dashboard',
|
||||
children: [
|
||||
{
|
||||
name: 'Analytics',
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ic:baseline-view-in-ar',
|
||||
keepAlive: true,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'ion:layers-outline',
|
||||
keepAlive: true,
|
||||
|
@@ -10,30 +10,20 @@ import {
|
||||
} from '@vben/constants';
|
||||
import { SvgAntdvLogoIcon } from '@vben/icons';
|
||||
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
badgeType: 'dot',
|
||||
icon: VBEN_LOGO_URL,
|
||||
order: 9999,
|
||||
order: 9998,
|
||||
title: $t('demos.vben.title'),
|
||||
},
|
||||
name: 'VbenProject',
|
||||
path: '/vben-admin',
|
||||
children: [
|
||||
{
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
title: $t('demos.vben.about'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'VbenDocument',
|
||||
path: '/vben-admin/document',
|
||||
@@ -89,6 +79,16 @@ const routes: RouteRecordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
order: 9999,
|
||||
title: $t('demos.vben.about'),
|
||||
},
|
||||
name: 'VbenAbout',
|
||||
path: '/vben-admin/about',
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
|
Reference in New Issue
Block a user