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 @@
-
+
-
+
-
+
{{ titleText }}
-
+
{{ descText }}
-
+
{{ $t('common.back-to-home') }}
diff --git a/packages/business/common-ui/src/fallback/icons/icon-403.vue b/packages/business/common-ui/src/fallback/icons/icon-403.vue
index 8f1aaef1..1afdb6ae 100644
--- a/packages/business/common-ui/src/fallback/icons/icon-403.vue
+++ b/packages/business/common-ui/src/fallback/icons/icon-403.vue
@@ -1,7 +1,151 @@
-
+
+
+
diff --git a/packages/business/common-ui/src/fallback/icons/fallback-icon.vue b/packages/business/common-ui/src/fallback/icons/icon-404.vue
similarity index 100%
rename from packages/business/common-ui/src/fallback/icons/fallback-icon.vue
rename to packages/business/common-ui/src/fallback/icons/icon-404.vue
diff --git a/packages/business/common-ui/src/fallback/icons/icon-500.vue b/packages/business/common-ui/src/fallback/icons/icon-500.vue
index 52f6b690..6bb5a1c3 100644
--- a/packages/business/common-ui/src/fallback/icons/icon-500.vue
+++ b/packages/business/common-ui/src/fallback/icons/icon-500.vue
@@ -1,7 +1,215 @@
-
+
+
+
diff --git a/packages/business/common-ui/src/fallback/index.ts b/packages/business/common-ui/src/fallback/index.ts
index c9b4086b..f56f6651 100644
--- a/packages/business/common-ui/src/fallback/index.ts
+++ b/packages/business/common-ui/src/fallback/index.ts
@@ -1 +1,2 @@
+export type * from './fallback';
export { default as Fallback } from './fallback.vue';
diff --git a/packages/business/layouts/src/basic/content/content.vue b/packages/business/layouts/src/basic/content/content.vue
index f255ab36..b030fa32 100644
--- a/packages/business/layouts/src/basic/content/content.vue
+++ b/packages/business/layouts/src/basic/content/content.vue
@@ -52,7 +52,6 @@ function getTransitionName(route: RouteLocationNormalizedLoaded) {
v-if="renderRouteView"
v-show="!route.meta.iframeSrc"
:key="route.fullPath"
- class="h-[1000px]"
/>
diff --git a/packages/constants/src/_essentials.ts b/packages/constants/src/_essentials.ts
index 48845616..8d5dfd94 100644
--- a/packages/constants/src/_essentials.ts
+++ b/packages/constants/src/_essentials.ts
@@ -4,8 +4,8 @@
const LOGIN_PATH = '/auth/login';
/**
- * @zh_CN 登陆页面路由名称
+ * @zh_CN 默认首页地址
*/
-const LOGIN_NAME = 'Login';
+const DEFAULT_HOME_PATH = '/welcome';
-export { LOGIN_NAME, LOGIN_PATH };
+export { DEFAULT_HOME_PATH, LOGIN_PATH };
diff --git a/packages/constants/src/vben.ts b/packages/constants/src/vben.ts
index ce774444..05e350c3 100644
--- a/packages/constants/src/vben.ts
+++ b/packages/constants/src/vben.ts
@@ -3,4 +3,9 @@
*/
const VBEN_GITHUB_URL = 'https://github.com/vbenjs/vue-vben-admin';
-export { VBEN_GITHUB_URL };
+/**
+ * @zh_CN Vben Logo
+ */
+const VBEN_LOGO =
+ 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.0/source/logo-v1.webp';
+export { VBEN_GITHUB_URL, VBEN_LOGO };
diff --git a/packages/locales/src/langs/en-US.yaml b/packages/locales/src/langs/en-US.yaml
index 694f4685..06f242b7 100644
--- a/packages/locales/src/langs/en-US.yaml
+++ b/packages/locales/src/langs/en-US.yaml
@@ -15,8 +15,12 @@ layout:
align-right: Align Right
fallback:
- page-not-found: Page Not Found
- page-not-found-desc: Sorry, We couldn't find the page you are looking for.
+ page-not-found: Oops! Page Not Found
+ page-not-found-desc: Sorry, we couldn't find the page you were looking for.
+ forbidden: Oops! Access Denied
+ forbidden-desc: Sorry, but you don't have permission to access this page.
+ internal-error: Oops! Something Went Wrong
+ internal-error-desc: Sorry, but the server encountered an error.
widgets:
document: Document
@@ -83,13 +87,29 @@ authentication:
third-party-login: Or continue with
page:
- about: About
- document: Document
- login: Login
- register: Register
- code-login: Code Login
- qrcode-login: Qrcode Login
- forget-password: Forget Password
+ essentials:
+ login: Login
+ register: Register
+ code-login: Code Login
+ qrcode-login: Qrcode Login
+ forget-password: Forget Password
+ vben:
+ about: About
+ document: Document
+ outside:
+ page: External Page
+ embedded: embedded Page
+ external-link: External Link
+ nested:
+ page: Nested Menu
+ menu1: Menu 1
+ menu2: Menu 2
+ menu3: Menu 3
+ menu31: Menu 3-1
+ menu32: Menu 3-2
+ menu321: Menu 3-2-11
+ fallback:
+ page: Exception Page
preference:
preferences: Preferences
diff --git a/packages/locales/src/langs/zh-CN.yaml b/packages/locales/src/langs/zh-CN.yaml
index bd421a11..f1d25cb9 100644
--- a/packages/locales/src/langs/zh-CN.yaml
+++ b/packages/locales/src/langs/zh-CN.yaml
@@ -14,8 +14,12 @@ layout:
align-right: 居右
fallback:
- page-not-found: 未找到页面
- page-not-found-desc: 抱歉,我们找不到您要找的页面。
+ page-not-found: 哎呀!未找到页面
+ page-not-found-desc: 抱歉,我们无法找到您要找的页面。
+ forbidden: 哎呀!访问被拒绝
+ forbidden-desc: 抱歉,您没有权限访问此页面。
+ internal-error: 哎呀!出错了
+ internal-error-desc: 抱歉,服务器遇到错误。
widgets:
document: 文档
@@ -82,13 +86,29 @@ authentication:
third-party-login: 其他登录方式
page:
- about: 关于
- document: 文档
- login: 登陆
- register: 注册
- code-login: 验证码登陆
- qrcode-login: 二维码登陆
- forget-password: 忘记密码
+ essentials:
+ login: 登陆
+ register: 注册
+ code-login: 验证码登陆
+ qrcode-login: 二维码登陆
+ forget-password: 忘记密码
+ vben:
+ about: 关于
+ document: 文档
+ outside:
+ page: 外部页面
+ embedded: 内嵌
+ external-link: 外链
+ nested:
+ page: 嵌套菜单
+ menu1: 菜单1
+ menu2: 菜单2
+ menu3: 菜单3
+ menu31: 菜单31
+ menu32: 菜单32
+ menu321: 菜单321
+ fallback:
+ page: 异常页面
preference:
preferences: 偏好设置