From 1d6b1f4926373ce37ea7773be6d042c56f1e38c7 Mon Sep 17 00:00:00 2001 From: vben Date: Sat, 8 Jun 2024 20:14:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=9E=E9=80=80=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/router/guard.ts | 50 ++-- apps/web-antd/src/router/index.ts | 12 +- .../web-antd/src/router/routes/_essentials.ts | 52 ++-- .../src/router/routes/dynamic/outside.ts | 39 --- .../src/router/routes/external/.gitkeep | 0 apps/web-antd/src/router/routes/index.ts | 32 ++- .../src/router/routes/modules/fallback.ts | 49 ++++ .../{dynamic/root.ts => modules/home.ts} | 0 .../routes/{dynamic => modules}/nested.ts | 26 +- .../src/router/routes/modules/outside.ts | 85 +++++++ .../routes/{dynamic => modules}/vben.ts | 20 +- .../src/router/routes/static/.gitkeep | 0 .../views/_essential/fallback/forbidden.vue | 7 + .../_essential/fallback/internal-error.vue | 7 + .../views/_essential/fallback/not-found.vue | 2 +- .../{ => _essential/vben}/about/index.vue | 0 .../inject-app-loading/loading-antd.html | 2 + .../plugins/inject-app-loading/loading.html | 2 + .../forward/helpers/src/generator-menus.ts | 4 +- .../shared/typings/src/vue-router.d.ts | 8 +- .../common-ui/src/fallback/fallback.ts | 31 +++ .../common-ui/src/fallback/fallback.vue | 93 +++++--- .../common-ui/src/fallback/icons/icon-403.vue | 158 ++++++++++++- .../icons/{fallback-icon.vue => icon-404.vue} | 0 .../common-ui/src/fallback/icons/icon-500.vue | 222 +++++++++++++++++- .../business/common-ui/src/fallback/index.ts | 1 + .../layouts/src/basic/content/content.vue | 1 - packages/constants/src/_essentials.ts | 6 +- packages/constants/src/vben.ts | 7 +- packages/locales/src/langs/en-US.yaml | 38 ++- packages/locales/src/langs/zh-CN.yaml | 38 ++- 31 files changed, 791 insertions(+), 201 deletions(-) delete mode 100644 apps/web-antd/src/router/routes/dynamic/outside.ts delete mode 100644 apps/web-antd/src/router/routes/external/.gitkeep create mode 100644 apps/web-antd/src/router/routes/modules/fallback.ts rename apps/web-antd/src/router/routes/{dynamic/root.ts => modules/home.ts} (100%) rename apps/web-antd/src/router/routes/{dynamic => modules}/nested.ts (65%) create mode 100644 apps/web-antd/src/router/routes/modules/outside.ts rename apps/web-antd/src/router/routes/{dynamic => modules}/vben.ts (69%) delete mode 100644 apps/web-antd/src/router/routes/static/.gitkeep rename apps/web-antd/src/views/{ => _essential/vben}/about/index.vue (100%) create mode 100644 packages/business/common-ui/src/fallback/fallback.ts rename packages/business/common-ui/src/fallback/icons/{fallback-icon.vue => icon-404.vue} (100%) diff --git a/apps/web-antd/src/router/guard.ts b/apps/web-antd/src/router/guard.ts index 6dc67738..1f93398b 100644 --- a/apps/web-antd/src/router/guard.ts +++ b/apps/web-antd/src/router/guard.ts @@ -1,4 +1,4 @@ -import type { RouteLocationNormalized, Router } from 'vue-router'; +import type { Router } from 'vue-router'; import { LOGIN_PATH } from '@vben/constants'; import { $t } from '@vben/locales'; @@ -9,7 +9,9 @@ import { useAccessStore } from '@vben-core/stores'; import { useTitle } from '@vueuse/core'; -import { dynamicRoutes } from '@/router/routes'; +import { dynamicRoutes, essentialsRouteNames } from '@/router/routes'; + +const forbiddenPage = () => import('@/views/_essential/fallback/forbidden.vue'); /** * 通用守卫配置 @@ -56,18 +58,24 @@ function setupAccessGuard(router: Router) { // accessToken 检查 if (!accessToken) { - if (to.path === '/') { - return loginPageMeta(to); - } - - // 明确声明忽略权限访问权限,则可以访问 - if (to.meta.ignoreAccess) { + if ( + // 基本路由,这些路由不需要进入权限拦截 + essentialsRouteNames.includes(to.name as string) || + // 明确声明忽略权限访问权限,则可以访问 + to.meta.ignoreAccess + ) { return true; } // 没有访问权限,跳转登录页面 if (to.fullPath !== LOGIN_PATH) { - return loginPageMeta(to); + return { + path: LOGIN_PATH, + // 如不需要,直接删除 query + query: { redirect: encodeURIComponent(to.fullPath) }, + // 携带当前跳转的页面,登录后重新跳转该页面 + replace: true, + }; } return to; } @@ -82,7 +90,15 @@ function setupAccessGuard(router: Router) { // 生成路由表 // 当前登录用户拥有的角色标识列表 const userRoles = accessStore.getUserRoles; - const accessibleRoutes = await generatorRoutes(dynamicRoutes, userRoles); + + const accessibleRoutes = await generatorRoutes( + dynamicRoutes, + userRoles, + // 如果 route.meta.menuVisibleWithForbidden = true + // 则会在菜单中显示,但是访问会被重定向到403 + // 这里可以指定403页面 + forbiddenPage, + ); // 动态添加到router实例内 accessibleRoutes.forEach((route) => router.addRoute(route)); @@ -101,20 +117,6 @@ function setupAccessGuard(router: Router) { }); } -/** - * 登录页面信息 - * @param to - */ -function loginPageMeta(to: RouteLocationNormalized) { - return { - path: LOGIN_PATH, - // 如不需要,直接删除 query - query: { redirect: encodeURIComponent(to.fullPath) }, - // 携带当前跳转的页面,登录后重新跳转该页面 - replace: true, - }; -} - /** * 项目守卫配置 * @param router diff --git a/apps/web-antd/src/router/index.ts b/apps/web-antd/src/router/index.ts index 2401d520..bddd05c3 100644 --- a/apps/web-antd/src/router/index.ts +++ b/apps/web-antd/src/router/index.ts @@ -14,15 +14,9 @@ const router = createRouter({ history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH), // 应该添加到路由的初始路由列表。 routes, - scrollBehavior: (_to, _from, savedPosition) => { - // if (to.path !== from.path) { - // const app = document.querySelector('#app'); - // if (app) { - // app.scrollTop = 0; - // } - // } - return savedPosition || { left: 0, top: 0 }; - }, + scrollBehavior: () => ({ left: 0, top: 0 }), + // 是否应该禁止尾部斜杠。默认为假 + // strict: true, }); /** diff --git a/apps/web-antd/src/router/routes/_essentials.ts b/apps/web-antd/src/router/routes/_essentials.ts index 1c09c1a0..bbf06cd6 100644 --- a/apps/web-antd/src/router/routes/_essentials.ts +++ b/apps/web-antd/src/router/routes/_essentials.ts @@ -1,13 +1,35 @@ import type { RouteRecordRaw } from 'vue-router'; +import { DEFAULT_HOME_PATH } from '@vben/constants'; import { $t } from '@vben/locales'; import { AuthPageLayoutType } from '@/layouts'; import Login from '@/views/_essential/authentication/login.vue'; +/** 全局404页面 */ +const fallbackNotFoundRoute: RouteRecordRaw = { + component: () => import('@/views/_essential/fallback/not-found.vue'), + meta: { + hideInBreadcrumb: true, + hideInMenu: true, + hideInTab: true, + title: '404', + }, + name: 'Fallback', + path: '/:path(.*)*', +}; + /** 基本路由,这些路由是必须存在的 */ const essentialsRoutes: RouteRecordRaw[] = [ + { + meta: { + title: 'Root', + }, + name: 'Root', + path: '/', + redirect: DEFAULT_HOME_PATH, + }, { component: AuthPageLayoutType, meta: { @@ -21,8 +43,7 @@ const essentialsRoutes: RouteRecordRaw[] = [ path: 'login', component: Login, meta: { - ignoreAccess: true, - title: $t('page.login'), + title: $t('page.essentials.login'), }, }, { @@ -31,8 +52,7 @@ const essentialsRoutes: RouteRecordRaw[] = [ component: () => import('@/views/_essential/authentication/code-login.vue'), meta: { - ignoreAccess: true, - title: $t('page.code-login'), + title: $t('page.essentials.code-login'), }, }, { @@ -41,8 +61,7 @@ const essentialsRoutes: RouteRecordRaw[] = [ component: () => import('@/views/_essential/authentication/qrcode-login.vue'), meta: { - ignoreAccess: true, - title: $t('page.qrcode-login'), + title: $t('page.essentials.qrcode-login'), }, }, { @@ -51,8 +70,7 @@ const essentialsRoutes: RouteRecordRaw[] = [ component: () => import('@/views/_essential/authentication/forget-password.vue'), meta: { - ignoreAccess: true, - title: $t('page.forget-password'), + title: $t('page.essentials.forget-password'), }, }, { @@ -61,25 +79,11 @@ const essentialsRoutes: RouteRecordRaw[] = [ component: () => import('@/views/_essential/authentication/register.vue'), meta: { - ignoreAccess: true, - title: $t('page.register'), + title: $t('page.essentials.register'), }, }, ], }, - // 错误页 - { - component: () => import('@/views/_essential/fallback/not-found.vue'), - meta: { - hideInBreadcrumb: true, - hideInMenu: true, - hideInTab: true, - // ignoreAccess: true, - title: 'Fallback', - }, - name: 'Fallback', - path: '/:path(.*)*', - }, ]; -export { essentialsRoutes }; +export { essentialsRoutes, fallbackNotFoundRoute }; diff --git a/apps/web-antd/src/router/routes/dynamic/outside.ts b/apps/web-antd/src/router/routes/dynamic/outside.ts deleted file mode 100644 index 9727048b..00000000 --- a/apps/web-antd/src/router/routes/dynamic/outside.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { RouteRecordRaw } from 'vue-router'; - -import { BasicLayout, IFrameView } from '@/layouts'; - -const routes: RouteRecordRaw[] = [ - { - component: BasicLayout, - meta: { - title: '外部页面', - }, - name: 'Outside', - path: '/outside', - redirect: '/outside/document', - children: [ - { - name: 'Document', - path: 'document', - component: IFrameView, - meta: { - iframeSrc: 'https://doc.vvbin.cn/', - // keepAlive: true, - title: '项目文档', - }, - }, - { - name: 'IFrameView', - path: 'vue-document', - component: IFrameView, - meta: { - iframeSrc: 'https://cn.vuejs.org/', - keepAlive: true, - title: 'Vue 文档(缓存)', - }, - }, - ], - }, -]; - -export default routes; diff --git a/apps/web-antd/src/router/routes/external/.gitkeep b/apps/web-antd/src/router/routes/external/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/web-antd/src/router/routes/index.ts b/apps/web-antd/src/router/routes/index.ts index 5f08eb44..bc1981e1 100644 --- a/apps/web-antd/src/router/routes/index.ts +++ b/apps/web-antd/src/router/routes/index.ts @@ -1,29 +1,35 @@ import type { RouteRecordRaw } from 'vue-router'; +import { traverseTreeValues } from '@vben/utils'; import { mergeRouteModules } from '@vben-core/helpers'; -import { essentialsRoutes } from './_essentials'; +import { essentialsRoutes, fallbackNotFoundRoute } from './_essentials'; -const dynamicRouteFiles = import.meta.glob('./dynamic/**/*.ts', { +const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', { eager: true, }); -const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true }); - -const externalRouteFiles = import.meta.glob('./external/**/*.ts', { - eager: true, -}); +// 有需要可以自行打开注释,并创建文件夹 +// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true }); /** 动态路由 */ const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles); /** 静态路由列表,访问这些页面可以不需要权限 */ -const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles); - -/** 排除在主框架外的路由,这些路由没有菜单和顶部及其他框架内容 */ -const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles); +// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles); +const staticRoutes: RouteRecordRaw[] = []; /** 路由列表,由基本路由+静态路由组成 */ -const routes: RouteRecordRaw[] = [...essentialsRoutes, ...staticRoutes]; +const routes: RouteRecordRaw[] = [ + ...essentialsRoutes, + ...staticRoutes, + fallbackNotFoundRoute, +]; -export { dynamicRoutes, externalRoutes, routes }; +/** 基本路由列表,这些路由不需要进入权限拦截 */ +const essentialsRouteNames = traverseTreeValues( + essentialsRoutes, + (route) => route.name, +); + +export { dynamicRoutes, essentialsRouteNames, routes }; diff --git a/apps/web-antd/src/router/routes/modules/fallback.ts b/apps/web-antd/src/router/routes/modules/fallback.ts new file mode 100644 index 00000000..4f38dccf --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/fallback.ts @@ -0,0 +1,49 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { BasicLayout } from '@/layouts'; +import { $t } from '@vben/locales/helper'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + icon: 'mdi:lightbulb-error-outline', + title: $t('page.fallback.page'), + }, + name: 'FallbackLayout', + path: '/fallback', + redirect: '/fallback/403', + children: [ + { + name: 'Fallback403', + path: '403', + component: () => import('@/views/_essential/fallback/forbidden.vue'), + meta: { + icon: 'mdi:do-not-disturb-alt', + title: '403', + }, + }, + { + name: 'Fallback404', + path: '404', + component: () => import('@/views/_essential/fallback/not-found.vue'), + meta: { + icon: 'mdi:table-off', + title: '404', + }, + }, + { + name: 'Fallback500', + path: '500', + component: () => + import('@/views/_essential/fallback/internal-error.vue'), + meta: { + icon: 'mdi:server-network-off', + title: '500', + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/router/routes/dynamic/root.ts b/apps/web-antd/src/router/routes/modules/home.ts similarity index 100% rename from apps/web-antd/src/router/routes/dynamic/root.ts rename to apps/web-antd/src/router/routes/modules/home.ts diff --git a/apps/web-antd/src/router/routes/dynamic/nested.ts b/apps/web-antd/src/router/routes/modules/nested.ts similarity index 65% rename from apps/web-antd/src/router/routes/dynamic/nested.ts rename to apps/web-antd/src/router/routes/modules/nested.ts index 99b96b85..7cd2a85e 100644 --- a/apps/web-antd/src/router/routes/dynamic/nested.ts +++ b/apps/web-antd/src/router/routes/modules/nested.ts @@ -1,24 +1,29 @@ import type { RouteRecordRaw } from 'vue-router'; import { BasicLayout } from '@/layouts'; +import { $t } from '@vben/locales/helper'; const routes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { + icon: 'ic:round-menu', keepAlive: true, - title: '多级菜单', + order: 1000, + title: $t('page.nested.page'), }, name: 'Nested', path: '/nested', + redirect: '/nested/menu1', children: [ { name: 'Menu1', path: 'menu1', component: () => import('@/views/nested/menu-1.vue'), meta: { + icon: 'ic:round-menu', keepAlive: true, - title: '菜单1', + title: $t('page.nested.menu1'), }, }, { @@ -26,40 +31,47 @@ const routes: RouteRecordRaw[] = [ path: 'menu2', component: () => import('@/views/nested/menu-2.vue'), meta: { + icon: 'ic:round-menu', keepAlive: true, - title: '菜单2', + title: $t('page.nested.menu2'), }, }, { name: 'Menu3', path: 'menu3', meta: { - title: '菜单3', + icon: 'ic:round-menu', + title: $t('page.nested.menu3'), }, + redirect: '/nested/menu3/menu3-1', children: [ { name: 'Menu31', path: 'menu3-1', component: () => import('@/views/nested/menu-3-1.vue'), meta: { + icon: 'ic:round-menu', keepAlive: true, - title: '菜单3-1', + title: $t('page.nested.menu31'), }, }, { name: 'Menu32', path: 'menu3-2', meta: { - title: '菜单3-2', + icon: 'ic:round-menu', + title: $t('page.nested.menu32'), }, + redirect: '/nested/menu3/menu3-2/menu3-2-1', children: [ { name: 'Menu321', path: 'menu3-2-1', component: () => import('@/views/nested/menu-3-2-1.vue'), meta: { + icon: 'ic:round-menu', keepAlive: true, - title: '菜单3-2-1', + title: $t('page.nested.menu321'), }, }, ], diff --git a/apps/web-antd/src/router/routes/modules/outside.ts b/apps/web-antd/src/router/routes/modules/outside.ts new file mode 100644 index 00000000..f5620ebd --- /dev/null +++ b/apps/web-antd/src/router/routes/modules/outside.ts @@ -0,0 +1,85 @@ +import type { RouteRecordRaw } from 'vue-router'; + +import { BasicLayout, IFrameView } from '@/layouts'; +import { $t } from '@vben/locales/helper'; + +const routes: RouteRecordRaw[] = [ + { + component: BasicLayout, + meta: { + icon: 'ic:round-settings-input-composite', + title: $t('page.outside.page'), + }, + name: 'Outside', + path: '/outside', + redirect: '/outside/iframe', + children: [ + { + name: 'iframe', + path: 'iframe', + meta: { + icon: 'mdi:newspaper-variant-outline', + title: $t('page.outside.embedded'), + }, + redirect: '/outside/iframe/vue-document', + children: [ + { + name: 'VueDocument', + path: 'vue-document', + component: IFrameView, + meta: { + icon: 'logos:vue', + iframeSrc: 'https://cn.vuejs.org/', + keepAlive: true, + title: 'Vue', + }, + }, + { + name: 'Tailwindcss', + path: 'tailwindcss', + component: IFrameView, + meta: { + icon: 'devicon:tailwindcss', + iframeSrc: 'https://tailwindcss.com/', + // keepAlive: true, + title: 'Tailwindcss', + }, + }, + ], + }, + { + name: 'ExternalLink', + path: 'external-link', + meta: { + icon: 'mdi:newspaper-variant-multiple-outline', + title: $t('page.outside.external-link'), + }, + redirect: '/outside/external-link/vite', + children: [ + { + name: 'Vite', + path: 'vite', + component: IFrameView, + meta: { + icon: 'logos:vitejs', + link: 'https://vitejs.dev/', + title: 'Vite', + }, + }, + { + name: 'VueUse', + path: 'vue-use', + component: IFrameView, + meta: { + icon: 'logos:vueuse', + link: 'https://vueuse.org', + title: 'VueUse', + }, + }, + ], + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-antd/src/router/routes/dynamic/vben.ts b/apps/web-antd/src/router/routes/modules/vben.ts similarity index 69% rename from apps/web-antd/src/router/routes/dynamic/vben.ts rename to apps/web-antd/src/router/routes/modules/vben.ts index 0035c7a9..f0d5d812 100644 --- a/apps/web-antd/src/router/routes/dynamic/vben.ts +++ b/apps/web-antd/src/router/routes/modules/vben.ts @@ -1,7 +1,6 @@ import type { RouteRecordRaw } from 'vue-router'; -import { VBEN_GITHUB_URL } from '@vben/constants'; -import { preferences } from '@vben-core/preferences'; +import { VBEN_GITHUB_URL, VBEN_LOGO } from '@vben/constants'; import { BasicLayout, IFrameView } from '@/layouts'; import { $t } from '@vben/locales/helper'; @@ -10,7 +9,8 @@ const routes: RouteRecordRaw[] = [ { component: BasicLayout, meta: { - icon: preferences.logo.source, + icon: VBEN_LOGO, + order: 9999, title: 'Vben', }, name: 'AboutLayout', @@ -18,32 +18,32 @@ const routes: RouteRecordRaw[] = [ redirect: '/vben-admin/about', children: [ { - name: 'About', + name: 'VbenAbout', path: 'about', - component: () => import('@/views/about/index.vue'), + component: () => import('@/views/_essential/vben/about/index.vue'), meta: { icon: 'mdi:creative-commons', - title: $t('page.about'), + title: $t('page.vben.about'), }, }, { - name: 'AboutDocument', + name: 'VbenDocument', path: 'document', component: IFrameView, meta: { icon: 'mdi:flame-circle', iframeSrc: 'https://doc.vvbin.cn/', keepAlive: true, - title: $t('page.document'), + title: $t('page.vben.document'), }, }, { - name: 'Github', + name: 'VbenGithub', path: 'github', component: IFrameView, meta: { icon: 'mdi:github', - target: VBEN_GITHUB_URL, + link: VBEN_GITHUB_URL, title: 'Github', }, }, diff --git a/apps/web-antd/src/router/routes/static/.gitkeep b/apps/web-antd/src/router/routes/static/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/web-antd/src/views/_essential/fallback/forbidden.vue b/apps/web-antd/src/views/_essential/fallback/forbidden.vue index e69de29b..e6c47bae 100644 --- a/apps/web-antd/src/views/_essential/fallback/forbidden.vue +++ b/apps/web-antd/src/views/_essential/fallback/forbidden.vue @@ -0,0 +1,7 @@ + + + diff --git a/apps/web-antd/src/views/_essential/fallback/internal-error.vue b/apps/web-antd/src/views/_essential/fallback/internal-error.vue index e69de29b..bca08e3d 100644 --- a/apps/web-antd/src/views/_essential/fallback/internal-error.vue +++ b/apps/web-antd/src/views/_essential/fallback/internal-error.vue @@ -0,0 +1,7 @@ + + + diff --git a/apps/web-antd/src/views/_essential/fallback/not-found.vue b/apps/web-antd/src/views/_essential/fallback/not-found.vue index f0edc0ba..cdc5a331 100644 --- a/apps/web-antd/src/views/_essential/fallback/not-found.vue +++ b/apps/web-antd/src/views/_essential/fallback/not-found.vue @@ -3,5 +3,5 @@ import { Fallback } from '@vben/common-ui'; diff --git a/apps/web-antd/src/views/about/index.vue b/apps/web-antd/src/views/_essential/vben/about/index.vue similarity index 100% rename from apps/web-antd/src/views/about/index.vue rename to apps/web-antd/src/views/_essential/vben/about/index.vue diff --git a/internal/vite-config/src/plugins/inject-app-loading/loading-antd.html b/internal/vite-config/src/plugins/inject-app-loading/loading-antd.html index 44bdd91a..c770e313 100644 --- a/internal/vite-config/src/plugins/inject-app-loading/loading-antd.html +++ b/internal/vite-config/src/plugins/inject-app-loading/loading-antd.html @@ -23,6 +23,8 @@ justify-content: center; width: 100%; height: 100%; + overflow: hidden; + pointer-events: none; background-color: #f4f7f9; } diff --git a/internal/vite-config/src/plugins/inject-app-loading/loading.html b/internal/vite-config/src/plugins/inject-app-loading/loading.html index 8833fb3c..0e0802d9 100644 --- a/internal/vite-config/src/plugins/inject-app-loading/loading.html +++ b/internal/vite-config/src/plugins/inject-app-loading/loading.html @@ -15,12 +15,14 @@ justify-content: center; width: 100%; height: 100%; + overflow: hidden; background-color: #f4f7f9; /* transition: all 0.8s ease-out; */ } .loading.hidden { + pointer-events: none; visibility: hidden; opacity: 0; transition: all 0.6s ease-out; diff --git a/packages/@vben-core/forward/helpers/src/generator-menus.ts b/packages/@vben-core/forward/helpers/src/generator-menus.ts index ae0d2ca6..432df3ff 100644 --- a/packages/@vben-core/forward/helpers/src/generator-menus.ts +++ b/packages/@vben-core/forward/helpers/src/generator-menus.ts @@ -30,8 +30,8 @@ async function generatorMenus( badgeVariants, hideChildrenInMenu = false, icon, + link, order, - target, title = '', } = meta || {}; @@ -50,7 +50,7 @@ async function generatorMenus( }); } // 隐藏子菜单 - const resultPath = hideChildrenInMenu ? redirect || path : target || path; + const resultPath = hideChildrenInMenu ? redirect || path : link || path; return { badge, badgeType, diff --git a/packages/@vben-core/shared/typings/src/vue-router.d.ts b/packages/@vben-core/shared/typings/src/vue-router.d.ts index e1d4b8f2..dd35f2fc 100644 --- a/packages/@vben-core/shared/typings/src/vue-router.d.ts +++ b/packages/@vben-core/shared/typings/src/vue-router.d.ts @@ -68,6 +68,10 @@ interface RouteMeta { * 开启KeepAlive缓存 */ keepAlive?: boolean; + /** + * 外链-跳转路径 + */ + link?: string; /** * 路由是否已经加载过 */ @@ -80,10 +84,6 @@ interface RouteMeta { * 用于路由->菜单排序 */ order?: number; - /** - * 外链-跳转路径 - */ - target?: string; /** * 标题名称 diff --git a/packages/business/common-ui/src/fallback/fallback.ts b/packages/business/common-ui/src/fallback/fallback.ts new file mode 100644 index 00000000..d8daae87 --- /dev/null +++ b/packages/business/common-ui/src/fallback/fallback.ts @@ -0,0 +1,31 @@ +interface FallbackProps { + /** + * 描述 + */ + description?: string; + /** + * @zh_CN 首页路由地址 + * @default / + */ + homePath?: string; + /** + * @zh_CN 默认显示的图片 + * @default pageNotFoundSvg + */ + image?: string; + + /** + * @zh_CN 是否显示返回首页按钮 + * @default true + */ + showBack?: boolean; + /** + * @zh_CN 内置类型 + */ + status?: '403' | '404' | '500'; + /** + * @zh_CN 页面提示语 + */ + title?: string; +} +export type { FallbackProps }; diff --git a/packages/business/common-ui/src/fallback/fallback.vue b/packages/business/common-ui/src/fallback/fallback.vue index 26d5c54f..e317ce3d 100644 --- a/packages/business/common-ui/src/fallback/fallback.vue +++ b/packages/business/common-ui/src/fallback/fallback.vue @@ -1,4 +1,6 @@