完善平台角色菜单树与授权登录导航
This commit is contained in:
85
frontend/platform_admin/src/router/authorized-landing.ts
Normal file
85
frontend/platform_admin/src/router/authorized-landing.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 功能:为平台管理员选择安全的登录落点。
|
||||
* 版本:v1.0.0
|
||||
*/
|
||||
import type {
|
||||
RouteLocationRaw,
|
||||
RouteMeta,
|
||||
RouteRecordName,
|
||||
Router,
|
||||
} from 'vue-router';
|
||||
|
||||
export const NO_PERMISSION_ROUTE_NAME = 'noPermission';
|
||||
|
||||
export interface AuthorizedMenuRoute {
|
||||
name?: RouteRecordName | null;
|
||||
meta?: RouteMeta;
|
||||
children?: AuthorizedMenuRoute[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 按服务端菜单顺序寻找首个可落地的叶子页面。
|
||||
* 父级分组和隐藏详情页不能成为默认首页。
|
||||
*/
|
||||
export function findFirstAuthorizedMenuRoute(
|
||||
routes: readonly AuthorizedMenuRoute[],
|
||||
): RouteLocationRaw | null {
|
||||
for (const route of routes) {
|
||||
if (route.children?.length) {
|
||||
const child = findFirstAuthorizedMenuRoute(route.children);
|
||||
if (child) return child;
|
||||
continue;
|
||||
}
|
||||
if (route.name && route.meta?.hideInMenu !== true) {
|
||||
return { name: route.name };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 仅允许恢复当前角色确实有权访问的叶子路由。 */
|
||||
export function isAuthorizedLoginTarget(
|
||||
router: Router,
|
||||
target: RouteLocationRaw,
|
||||
role: string,
|
||||
menuCodes: readonly string[],
|
||||
) {
|
||||
const resolved = router.resolve(target);
|
||||
const terminal = resolved.matched[resolved.matched.length - 1];
|
||||
if (
|
||||
!terminal ||
|
||||
resolved.name === 'login' ||
|
||||
resolved.name === 'notFound' ||
|
||||
resolved.name === NO_PERMISSION_ROUTE_NAME ||
|
||||
terminal.redirect ||
|
||||
terminal.children.length
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const menuCode = resolved.meta.menuCode;
|
||||
return (
|
||||
role === 'root' ||
|
||||
(typeof menuCode === 'string' && menuCodes.includes(menuCode))
|
||||
);
|
||||
}
|
||||
|
||||
/** 优先恢复有权历史地址,否则进入首个授权菜单或权限引导页。 */
|
||||
export function resolveAuthorizedLanding(
|
||||
router: Router,
|
||||
menus: readonly AuthorizedMenuRoute[],
|
||||
role: string,
|
||||
menuCodes: readonly string[],
|
||||
requested?: RouteLocationRaw,
|
||||
): RouteLocationRaw {
|
||||
if (
|
||||
requested &&
|
||||
isAuthorizedLoginTarget(router, requested, role, menuCodes)
|
||||
) {
|
||||
return requested;
|
||||
}
|
||||
return (
|
||||
findFirstAuthorizedMenuRoute(menus) ?? {
|
||||
name: NO_PERMISSION_ROUTE_NAME,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
export const WHITE_LIST = [
|
||||
{ name: 'notFound', children: [] },
|
||||
{ name: 'login', children: [] },
|
||||
{ name: 'noPermission', children: [] },
|
||||
];
|
||||
|
||||
export const NOT_FOUND = {
|
||||
|
||||
@@ -4,7 +4,11 @@ import 'nprogress/nprogress.css';
|
||||
|
||||
import createRouteGuard from './guard';
|
||||
import { appRoutes } from './routes';
|
||||
import { NOT_FOUND_ROUTE, REDIRECT_MAIN } from './routes/base';
|
||||
import {
|
||||
NOT_FOUND_ROUTE,
|
||||
NO_PERMISSION_ROUTE,
|
||||
REDIRECT_MAIN,
|
||||
} from './routes/base';
|
||||
|
||||
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
||||
|
||||
@@ -25,6 +29,7 @@ const router = createRouter({
|
||||
},
|
||||
...appRoutes,
|
||||
REDIRECT_MAIN,
|
||||
NO_PERMISSION_ROUTE,
|
||||
NOT_FOUND_ROUTE,
|
||||
],
|
||||
scrollBehavior() {
|
||||
|
||||
@@ -24,6 +24,17 @@ export const REDIRECT_MAIN: RouteRecordRaw = {
|
||||
],
|
||||
};
|
||||
|
||||
/** 已认证但暂无业务菜单时的独立引导页。 */
|
||||
export const NO_PERMISSION_ROUTE: RouteRecordRaw = {
|
||||
path: '/no-permission',
|
||||
name: 'noPermission',
|
||||
component: () => import('@/views/no-permission/index.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const NOT_FOUND_ROUTE: RouteRecordRaw = {
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'notFound',
|
||||
|
||||
Reference in New Issue
Block a user