From 1ad54561b0dc4f36f8b5d8bf356d93d247846be5 Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 14 Jan 2025 12:12:08 +0800 Subject: [PATCH 1/6] feat: add `noBasicLayout` in route meta (#5386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 所有菜单数据无需配置component为BasicLayout,它们将会默认使用基础布局,也可以通过meta.noBasicLayout来阻止这一行为 --- apps/backend-mock/utils/mock-data.ts | 2 -- apps/web-antd/src/router/routes/core.ts | 12 +++++++++- .../src/router/routes/modules/dashboard.ts | 2 -- .../src/router/routes/modules/demos.ts | 2 -- .../src/router/routes/modules/vben.ts | 24 +++++++++---------- apps/web-ele/src/router/routes/core.ts | 12 +++++++++- .../src/router/routes/modules/dashboard.ts | 2 -- .../src/router/routes/modules/demos.ts | 2 -- .../web-ele/src/router/routes/modules/vben.ts | 24 +++++++++---------- apps/web-naive/src/router/routes/core.ts | 12 +++++++++- .../src/router/routes/modules/dashboard.ts | 2 -- .../src/router/routes/modules/demos.ts | 2 -- .../src/router/routes/modules/vben.ts | 24 +++++++++---------- docs/src/en/guide/essentials/route.md | 3 --- docs/src/guide/essentials/route.md | 18 ++++++++------ .../@core/base/typings/src/vue-router.d.ts | 4 ++++ packages/effects/access/src/accessible.ts | 20 +++++++++++++++- playground/src/router/routes/core.ts | 12 +++++++++- .../src/router/routes/modules/dashboard.ts | 4 +--- playground/src/router/routes/modules/demos.ts | 3 +-- .../src/router/routes/modules/examples.ts | 2 -- playground/src/router/routes/modules/vben.ts | 24 +++++++++---------- 22 files changed, 128 insertions(+), 84 deletions(-) diff --git a/apps/backend-mock/utils/mock-data.ts b/apps/backend-mock/utils/mock-data.ts index 057588e36..3967b906c 100644 --- a/apps/backend-mock/utils/mock-data.ts +++ b/apps/backend-mock/utils/mock-data.ts @@ -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, diff --git a/apps/web-antd/src/router/routes/core.ts b/apps/web-antd/src/router/routes/core.ts index fe030a9a2..1d0a07fad 100644 --- a/apps/web-antd/src/router/routes/core.ts +++ b/apps/web-antd/src/router/routes/core.ts @@ -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,23 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/apps/web-antd/src/router/routes/modules/dashboard.ts b/apps/web-antd/src/router/routes/modules/dashboard.ts index 1bddab9db..f3a952b08 100644 --- a/apps/web-antd/src/router/routes/modules/dashboard.ts +++ b/apps/web-antd/src/router/routes/modules/dashboard.ts @@ -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, diff --git a/apps/web-antd/src/router/routes/modules/demos.ts b/apps/web-antd/src/router/routes/modules/demos.ts index 32bb338e0..55ade09c9 100644 --- a/apps/web-antd/src/router/routes/modules/demos.ts +++ b/apps/web-antd/src/router/routes/modules/demos.ts @@ -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, diff --git a/apps/web-antd/src/router/routes/modules/vben.ts b/apps/web-antd/src/router/routes/modules/vben.ts index 210e8610f..98acf5821 100644 --- a/apps/web-antd/src/router/routes/modules/vben.ts +++ b/apps/web-antd/src/router/routes/modules/vben.ts @@ -8,30 +8,20 @@ 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', 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', @@ -76,6 +66,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; diff --git a/apps/web-ele/src/router/routes/core.ts b/apps/web-ele/src/router/routes/core.ts index fe030a9a2..1d0a07fad 100644 --- a/apps/web-ele/src/router/routes/core.ts +++ b/apps/web-ele/src/router/routes/core.ts @@ -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,23 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/apps/web-ele/src/router/routes/modules/dashboard.ts b/apps/web-ele/src/router/routes/modules/dashboard.ts index 1bddab9db..f3a952b08 100644 --- a/apps/web-ele/src/router/routes/modules/dashboard.ts +++ b/apps/web-ele/src/router/routes/modules/dashboard.ts @@ -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, diff --git a/apps/web-ele/src/router/routes/modules/demos.ts b/apps/web-ele/src/router/routes/modules/demos.ts index 90cc2f11c..907ea3f45 100644 --- a/apps/web-ele/src/router/routes/modules/demos.ts +++ b/apps/web-ele/src/router/routes/modules/demos.ts @@ -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, diff --git a/apps/web-ele/src/router/routes/modules/vben.ts b/apps/web-ele/src/router/routes/modules/vben.ts index 2cfef5498..20fbc96c0 100644 --- a/apps/web-ele/src/router/routes/modules/vben.ts +++ b/apps/web-ele/src/router/routes/modules/vben.ts @@ -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; diff --git a/apps/web-naive/src/router/routes/core.ts b/apps/web-naive/src/router/routes/core.ts index fe030a9a2..1d0a07fad 100644 --- a/apps/web-naive/src/router/routes/core.ts +++ b/apps/web-naive/src/router/routes/core.ts @@ -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,23 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/apps/web-naive/src/router/routes/modules/dashboard.ts b/apps/web-naive/src/router/routes/modules/dashboard.ts index 1bddab9db..f3a952b08 100644 --- a/apps/web-naive/src/router/routes/modules/dashboard.ts +++ b/apps/web-naive/src/router/routes/modules/dashboard.ts @@ -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, diff --git a/apps/web-naive/src/router/routes/modules/demos.ts b/apps/web-naive/src/router/routes/modules/demos.ts index d0631cb53..5e49ffa01 100644 --- a/apps/web-naive/src/router/routes/modules/demos.ts +++ b/apps/web-naive/src/router/routes/modules/demos.ts @@ -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, diff --git a/apps/web-naive/src/router/routes/modules/vben.ts b/apps/web-naive/src/router/routes/modules/vben.ts index 44461a7fd..169de855b 100644 --- a/apps/web-naive/src/router/routes/modules/vben.ts +++ b/apps/web-naive/src/router/routes/modules/vben.ts @@ -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; diff --git a/docs/src/en/guide/essentials/route.md b/docs/src/en/guide/essentials/route.md index bef40d691..8fb0a6d1c 100644 --- a/docs/src/en/guide/essentials/route.md +++ b/docs/src/en/guide/essentials/route.md @@ -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'), diff --git a/docs/src/guide/essentials/route.md b/docs/src/guide/essentials/route.md index 0eb74aea4..d8a938dda 100644 --- a/docs/src/guide/essentials/route.md +++ b/docs/src/guide/essentials/route.md @@ -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`。 + ## 路由刷新 路由刷新方式如下: diff --git a/packages/@core/base/typings/src/vue-router.d.ts b/packages/@core/base/typings/src/vue-router.d.ts index b5809f0ed..099e8171a 100644 --- a/packages/@core/base/typings/src/vue-router.d.ts +++ b/packages/@core/base/typings/src/vue-router.d.ts @@ -97,6 +97,10 @@ interface RouteMeta { * 菜单可以看到,但是访问会被重定向到403 */ menuVisibleWithForbidden?: boolean; + /** + * 不使用基础布局(仅在顶级生效) + */ + noBasicLayout?: boolean; /** * 在新窗口打开 */ diff --git a/packages/effects/access/src/accessible.ts b/packages/effects/access/src/accessible.ts index c951d92a5..960af3fbc 100644 --- a/packages/effects/access/src/accessible.ts +++ b/packages/effects/access/src/accessible.ts @@ -22,11 +22,29 @@ async function generateAccessible( // 生成路由 const accessibleRoutes = await generateRoutes(mode, options); + const root = router.getRoutes().find((item) => item.path === '/'); + // 动态添加到router实例内 accessibleRoutes.forEach((route) => { - router.addRoute(route); + if (root && !route.meta?.noBasicLayout) { + // 为了兼容之前的版本用法,如果包含子路由,则将component移除,以免出现多层BasicLayout + // 如果你的项目已经跟进了本次修改,移除了所有自定义菜单首级的BasicLayout,可以将这段if代码删除 + 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); diff --git a/playground/src/router/routes/core.ts b/playground/src/router/routes/core.ts index fe030a9a2..1d0a07fad 100644 --- a/playground/src/router/routes/core.ts +++ b/playground/src/router/routes/core.ts @@ -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,23 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/playground/src/router/routes/modules/dashboard.ts b/playground/src/router/routes/modules/dashboard.ts index 1bddab9db..5254dc65d 100644 --- a/playground/src/router/routes/modules/dashboard.ts +++ b/playground/src/router/routes/modules/dashboard.ts @@ -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', diff --git a/playground/src/router/routes/modules/demos.ts b/playground/src/router/routes/modules/demos.ts index 46ebeeb9f..422e5bf13 100644 --- a/playground/src/router/routes/modules/demos.ts +++ b/playground/src/router/routes/modules/demos.ts @@ -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, diff --git a/playground/src/router/routes/modules/examples.ts b/playground/src/router/routes/modules/examples.ts index 449bbc2c1..7287f0ddc 100644 --- a/playground/src/router/routes/modules/examples.ts +++ b/playground/src/router/routes/modules/examples.ts @@ -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, diff --git a/playground/src/router/routes/modules/vben.ts b/playground/src/router/routes/modules/vben.ts index 2f2eb6604..ec44d58ab 100644 --- a/playground/src/router/routes/modules/vben.ts +++ b/playground/src/router/routes/modules/vben.ts @@ -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; From 5965755caa3bf7e3e762a5ce7fc9c0d5790dc2b5 Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 14 Jan 2025 15:15:02 +0800 Subject: [PATCH 2/6] fix: root router config fixed (#5389) --- apps/web-antd/src/router/routes/core.ts | 3 --- apps/web-ele/src/router/routes/core.ts | 3 --- apps/web-naive/src/router/routes/core.ts | 3 --- playground/src/router/routes/core.ts | 3 --- 4 files changed, 12 deletions(-) diff --git a/apps/web-antd/src/router/routes/core.ts b/apps/web-antd/src/router/routes/core.ts index 1d0a07fad..7c3ca2ebf 100644 --- a/apps/web-antd/src/router/routes/core.ts +++ b/apps/web-antd/src/router/routes/core.ts @@ -29,9 +29,6 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { - hideInBreadcrumb: true, - hideInMenu: true, - hideInTab: true, title: 'Root', }, name: 'Root', diff --git a/apps/web-ele/src/router/routes/core.ts b/apps/web-ele/src/router/routes/core.ts index 1d0a07fad..7c3ca2ebf 100644 --- a/apps/web-ele/src/router/routes/core.ts +++ b/apps/web-ele/src/router/routes/core.ts @@ -29,9 +29,6 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { - hideInBreadcrumb: true, - hideInMenu: true, - hideInTab: true, title: 'Root', }, name: 'Root', diff --git a/apps/web-naive/src/router/routes/core.ts b/apps/web-naive/src/router/routes/core.ts index 1d0a07fad..7c3ca2ebf 100644 --- a/apps/web-naive/src/router/routes/core.ts +++ b/apps/web-naive/src/router/routes/core.ts @@ -29,9 +29,6 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { - hideInBreadcrumb: true, - hideInMenu: true, - hideInTab: true, title: 'Root', }, name: 'Root', diff --git a/playground/src/router/routes/core.ts b/playground/src/router/routes/core.ts index 1d0a07fad..7c3ca2ebf 100644 --- a/playground/src/router/routes/core.ts +++ b/playground/src/router/routes/core.ts @@ -29,9 +29,6 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { - hideInBreadcrumb: true, - hideInMenu: true, - hideInTab: true, title: 'Root', }, name: 'Root', From e1c503e51e64485ca5fadbd9fa1e6d22329c4ced Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 14 Jan 2025 17:11:18 +0800 Subject: [PATCH 3/6] feat: support set default props for drawer and modal (#5390) * feat: support set default props for drawer and modal * docs: fix typo --- apps/web-antd/src/bootstrap.ts | 16 +++++++++++++++- apps/web-ele/src/bootstrap.ts | 15 ++++++++++++++- apps/web-naive/src/bootstrap.ts | 17 ++++++++++++++++- docs/src/components/common-ui/vben-drawer.md | 1 + docs/src/components/common-ui/vben-modal.md | 1 + .../@core/ui-kit/popup-ui/src/drawer/index.ts | 2 +- .../ui-kit/popup-ui/src/drawer/use-drawer.ts | 7 +++++++ .../@core/ui-kit/popup-ui/src/modal/index.ts | 2 +- .../ui-kit/popup-ui/src/modal/use-modal.ts | 7 +++++++ packages/styles/src/antd/index.css | 4 ++++ playground/src/bootstrap.ts | 16 +++++++++++++++- 11 files changed, 82 insertions(+), 6 deletions(-) diff --git a/apps/web-antd/src/bootstrap.ts b/apps/web-antd/src/bootstrap.ts index 30ab99888..780363c29 100644 --- a/apps/web-antd/src/bootstrap.ts +++ b/apps/web-antd/src/bootstrap.ts @@ -1,7 +1,11 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; -import { initTippy } from '@vben/common-ui'; +import { + initTippy, + setDefaultDrawerProps, + setDefaultModalProps, +} from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; @@ -19,6 +23,16 @@ async function bootstrap(namespace: string) { // 初始化组件适配器 await initComponentAdapter(); + // 设置弹窗的默认配置 + setDefaultModalProps({ + fullscreenButton: false, + zIndex: 1020, + }); + // 设置抽屉的默认配置 + setDefaultDrawerProps({ + zIndex: 1020, + }); + const app = createApp(App); // 国际化 i18n 配置 diff --git a/apps/web-ele/src/bootstrap.ts b/apps/web-ele/src/bootstrap.ts index 9cdb0863b..7edc070b7 100644 --- a/apps/web-ele/src/bootstrap.ts +++ b/apps/web-ele/src/bootstrap.ts @@ -1,7 +1,11 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; -import { initTippy } from '@vben/common-ui'; +import { + initTippy, + setDefaultDrawerProps, + setDefaultModalProps, +} from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; @@ -19,6 +23,15 @@ import { router } from './router'; async function bootstrap(namespace: string) { // 初始化组件适配器 await initComponentAdapter(); + // 设置弹窗的默认配置 + setDefaultModalProps({ + fullscreenButton: false, + zIndex: 2000, + }); + // 设置抽屉的默认配置 + setDefaultDrawerProps({ + zIndex: 2000, + }); const app = createApp(App); // 注册Element Plus提供的v-loading指令 diff --git a/apps/web-naive/src/bootstrap.ts b/apps/web-naive/src/bootstrap.ts index d4172b28c..9e9ac2530 100644 --- a/apps/web-naive/src/bootstrap.ts +++ b/apps/web-naive/src/bootstrap.ts @@ -1,7 +1,11 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; -import { initTippy } from '@vben/common-ui'; +import { + initTippy, + setDefaultDrawerProps, + setDefaultModalProps, +} from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; @@ -18,6 +22,17 @@ import { router } from './router'; async function bootstrap(namespace: string) { // 初始化组件适配器 initComponentAdapter(); + + // 设置弹窗的默认配置 + setDefaultModalProps({ + fullscreenButton: false, + zIndex: 2000, + }); + // 设置抽屉的默认配置 + setDefaultDrawerProps({ + zIndex: 2000, + }); + const app = createApp(App); // 国际化 i18n 配置 diff --git a/docs/src/components/common-ui/vben-drawer.md b/docs/src/components/common-ui/vben-drawer.md index 044208555..61b7c9e59 100644 --- a/docs/src/components/common-ui/vben-drawer.md +++ b/docs/src/components/common-ui/vben-drawer.md @@ -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等。 ::: diff --git a/docs/src/components/common-ui/vben-modal.md b/docs/src/components/common-ui/vben-modal.md index f3e2a17bb..8d0b42841 100644 --- a/docs/src/components/common-ui/vben-modal.md +++ b/docs/src/components/common-ui/vben-modal.md @@ -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等。 ::: diff --git a/packages/@core/ui-kit/popup-ui/src/drawer/index.ts b/packages/@core/ui-kit/popup-ui/src/drawer/index.ts index f2dd83969..00f87b2ce 100644 --- a/packages/@core/ui-kit/popup-ui/src/drawer/index.ts +++ b/packages/@core/ui-kit/popup-ui/src/drawer/index.ts @@ -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'; diff --git a/packages/@core/ui-kit/popup-ui/src/drawer/use-drawer.ts b/packages/@core/ui-kit/popup-ui/src/drawer/use-drawer.ts index d02027634..21b11c56f 100644 --- a/packages/@core/ui-kit/popup-ui/src/drawer/use-drawer.ts +++ b/packages/@core/ui-kit/popup-ui/src/drawer/use-drawer.ts @@ -21,6 +21,12 @@ import VbenDrawer from './drawer.vue'; const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT'); +const DEFAULT_DRAWER_PROPS: Partial = {}; + +export function setDefaultDrawerProps(props: Partial) { + Object.assign(DEFAULT_DRAWER_PROPS, props); +} + export function useVbenDrawer< TParentDrawerProps extends DrawerProps = DrawerProps, >(options: DrawerApiOptions = {}) { @@ -69,6 +75,7 @@ export function useVbenDrawer< const injectData = inject(USER_DRAWER_INJECT_KEY, {}); const mergedOptions = { + ...DEFAULT_DRAWER_PROPS, ...injectData.options, ...options, } as DrawerApiOptions; diff --git a/packages/@core/ui-kit/popup-ui/src/modal/index.ts b/packages/@core/ui-kit/popup-ui/src/modal/index.ts index c8d3498c3..0cdedf2f5 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/index.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/index.ts @@ -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'; diff --git a/packages/@core/ui-kit/popup-ui/src/modal/use-modal.ts b/packages/@core/ui-kit/popup-ui/src/modal/use-modal.ts index 456d001b4..6cc0a30d5 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/use-modal.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/use-modal.ts @@ -17,6 +17,12 @@ import VbenModal from './modal.vue'; const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT'); +const DEFAULT_MODAL_PROPS: Partial = {}; + +export function setDefaultModalProps(props: Partial) { + Object.assign(DEFAULT_MODAL_PROPS, props); +} + export function useVbenModal( options: ModalApiOptions = {}, ) { @@ -68,6 +74,7 @@ export function useVbenModal( const injectData = inject(USER_MODAL_INJECT_KEY, {}); const mergedOptions = { + ...DEFAULT_MODAL_PROPS, ...injectData.options, ...options, } as ModalApiOptions; diff --git a/packages/styles/src/antd/index.css b/packages/styles/src/antd/index.css index ed822fdca..2a265eacd 100644 --- a/packages/styles/src/antd/index.css +++ b/packages/styles/src/antd/index.css @@ -54,3 +54,7 @@ .ant-app .form-valid-error .ant-picker-focused { box-shadow: 0 0 0 2px rgb(255 38 5 / 6%); } + +.ant-message { + z-index: 1050; +} diff --git a/playground/src/bootstrap.ts b/playground/src/bootstrap.ts index d82c8e5e6..7b580fd19 100644 --- a/playground/src/bootstrap.ts +++ b/playground/src/bootstrap.ts @@ -1,7 +1,11 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; -import { initTippy } from '@vben/common-ui'; +import { + initTippy, + setDefaultDrawerProps, + setDefaultModalProps, +} from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; @@ -20,6 +24,16 @@ async function bootstrap(namespace: string) { // 初始化组件适配器 await initComponentAdapter(); + // 设置弹窗的默认配置 + setDefaultModalProps({ + fullscreenButton: false, + zIndex: 1020, + }); + // 设置抽屉的默认配置 + setDefaultDrawerProps({ + zIndex: 1020, + }); + const app = createApp(App); // 国际化 i18n 配置 From 76c4aa2c55eaede2507c130e8bbd0ae9216f25ff Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 14 Jan 2025 17:51:39 +0800 Subject: [PATCH 4/6] fix: hide root route in breadcrumb --- apps/web-antd/src/router/routes/core.ts | 1 + apps/web-ele/src/router/routes/core.ts | 1 + apps/web-naive/src/router/routes/core.ts | 1 + playground/src/router/routes/core.ts | 1 + 4 files changed, 4 insertions(+) diff --git a/apps/web-antd/src/router/routes/core.ts b/apps/web-antd/src/router/routes/core.ts index 7c3ca2ebf..7218da228 100644 --- a/apps/web-antd/src/router/routes/core.ts +++ b/apps/web-antd/src/router/routes/core.ts @@ -29,6 +29,7 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', diff --git a/apps/web-ele/src/router/routes/core.ts b/apps/web-ele/src/router/routes/core.ts index 7c3ca2ebf..7218da228 100644 --- a/apps/web-ele/src/router/routes/core.ts +++ b/apps/web-ele/src/router/routes/core.ts @@ -29,6 +29,7 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', diff --git a/apps/web-naive/src/router/routes/core.ts b/apps/web-naive/src/router/routes/core.ts index 7c3ca2ebf..7218da228 100644 --- a/apps/web-naive/src/router/routes/core.ts +++ b/apps/web-naive/src/router/routes/core.ts @@ -29,6 +29,7 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', diff --git a/playground/src/router/routes/core.ts b/playground/src/router/routes/core.ts index 7c3ca2ebf..7218da228 100644 --- a/playground/src/router/routes/core.ts +++ b/playground/src/router/routes/core.ts @@ -29,6 +29,7 @@ const coreRoutes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', From fb0ec05ff8aa3bfb1b01d8372537e3018d653dec Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 14 Jan 2025 18:15:00 +0800 Subject: [PATCH 5/6] perf: improve fieldMappingTime to support format function (#5392) --- docs/src/components/common-ui/vben-form.md | 4 ++-- packages/@core/ui-kit/form-ui/src/form-api.ts | 3 +++ packages/@core/ui-kit/form-ui/src/types.ts | 9 +++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/src/components/common-ui/vben-form.md b/docs/src/components/common-ui/vben-form.md index a15c366f0..0193e0704 100644 --- a/docs/src/components/common-ui/vben-form.md +++ b/docs/src/components/common-ui/vben-form.md @@ -316,7 +316,7 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单 | collapsed | 是否折叠,在`showCollapseButton`为`true`时生效 | `boolean` | `false` | | collapseTriggerResize | 折叠时,触发`resize`事件 | `boolean` | `false` | | collapsedRows | 折叠时保持的行数 | `number` | `1` | -| fieldMappingTime | 用于将表单内的数组值值映射成 2 个字段 | `[string, [string, string],Nullable?][]` | - | +| fieldMappingTime | 用于将表单内的数组值值映射成 2 个字段 | `[string, [string, string],Nullable\|[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`字段上。每一项的第三个参数是一个可选的格式掩码, ::: diff --git a/packages/@core/ui-kit/form-ui/src/form-api.ts b/packages/@core/ui-kit/form-ui/src/form-api.ts index a2877cbff..2d1e971ab 100644 --- a/packages/@core/ui-kit/form-ui/src/form-api.ts +++ b/packages/@core/ui-kit/form-ui/src/form-api.ts @@ -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 diff --git a/packages/@core/ui-kit/form-ui/src/types.ts b/packages/@core/ui-kit/form-ui/src/types.ts index 07a2afd43..dd007292f 100644 --- a/packages/@core/ui-kit/form-ui/src/types.ts +++ b/packages/@core/ui-kit/form-ui/src/types.ts @@ -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)?, + ( + | ((value: any, fieldName: string) => any) + | [string, string] + | null + | string + )?, ][]; export interface FormSchema< From 27a3888e351e909253f36aa6702b1fe61dc28f22 Mon Sep 17 00:00:00 2001 From: Netfan Date: Wed, 15 Jan 2025 00:49:11 +0800 Subject: [PATCH 6/6] style: element plus loading style fixed (#5393) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Element Plus的loading组件默认zIndex太高 --- packages/styles/src/ele/index.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/styles/src/ele/index.css b/packages/styles/src/ele/index.css index b59ee2adf..4ee8f7b12 100644 --- a/packages/styles/src/ele/index.css +++ b/packages/styles/src/ele/index.css @@ -38,3 +38,7 @@ border: 1px solid var(--el-color-danger); } } + +html .el-loading-mask { + z-index: 1000; +}