读书管理后台开发项目-6.管理后台前端权限

前端的权限管理通常是左侧菜单部分的展示权限,以及基于功能的权限
vben实际上是动态生成了路由,然后再展示在左边的菜单栏,所以要编写权限相关的代码可以从动态生成路由处着手

buildRoutesAction方法分析

vben通过动态生成路由,控制菜单栏展示权限。核心方法是buildRoutesAction,该方法根据路由的meta.role属性过滤路由,从而生成不同角色的菜单。
搜索这个方法的签名可以发现被多个地方调用
此外,该方法还将多级路由简化为两级路由。


通过调试路由生成过程可以发现方法会检查路由下的meta.role属性来过滤路由,最后生成菜单

并且还对路由进行了操作,将多级路由转为两级路由

首先我们获取角色信息,在user.ts下的getUserInfoAction中vben已经撰写好了用户信息的获取逻辑。我们从这里开始编写代码。
1.将roles改为role

后端动态生成前端菜单方案

由于前端路由列表中的component字段无法直接转换为JSON并传递给后端,我们需要在router/route-map.ts中映射路由与组件的关系。

如果把前端的routeList直接转换成JSON,由后端来下发数据会有一个component字段丢失的问题。所以我们可以在router下建立一个route-map.ts文件用于映射路由与组件的关系

1
2
3
4
5
6
7
8
9
import { EXCEPTION_COMPONENT, LAYOUT } from '@/router/constant';

export const ROUTE_MAP = {
Dashboard: LAYOUT,
Analysis: () => import('@/views/dashboard/analysis/index.vue'),
Workbench: () => import('@/views/dashboard/workbench/index.vue'),
NOT_FOUND: EXCEPTION_COMPONENT,
};

在user.ts文件中兼容数据库角色字段的逻辑

接下来,通过硬编码的方式配置路由,并使用wrapperRouteComponent函数,将路由的name与组件关联。parseRouteRoles函数则解析roles字段,将其转为数组。

用硬编码的方式写入路由配置,通过wrapperRouteComponent函数将路由配置中的name属性与route-map中的component属性关联起来。并通过parseRouteRoles函数将roles字段文本转数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const wrapperRouteComponent = (routes) => {
return routes.map((route) => {
if (route.children && route.children.length > 0) {
route.children = wrapperRouteComponent(route.children);
}
route.component = ROUTE_MAP[route.name] || ROUTE_MAP.NOT_FOUND;
return route;
});
};

const parseRouteRoles = (routes) => {
return routes.map((route) => {
if (route.children && route.children.length > 0) {
route.children = parseRouteRoles(route.children);
}
if (route?.meta?.roles) {
try {
route.meta.roles = JSON.parse(route.meta.roles)
} catch (e) {
console.error(e)
}
}
return route;
});
}

对于PAGE_NOT_FOUND这类父路由名与子路由名相同的情况,我们可以通过addPageNotFoundAtFirst函数特殊处理:

1
2
3
4
const addPageNotFoundAtFirst = (routes) => {
routes.unshift(PAGE_NOT_FOUND_ROUTE);
return routes;
};

优化:使用现有的路由映射

手动添加路由与组件的映射关系会很繁琐。为简化操作,我们可以利用asyncRoutes变量,该变量已经包含了完整的路由和组件映射信息。通过遍历asyncRoutes,我们可以自动生成ROUTE_MAP。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import {asyncRoutes} from "@/router/routes";

// export const ROUTE_MAP = {
// PageNotFound: () => import('@/views/sys/exception/Exception.vue'),
// Dashboard: LAYOUT,
// Analysis: () => import('@/views/dashboard/analysis/index.vue'),
// Workbench: () => import('@/views/dashboard/workbench/index.vue'),
// NOT_FOUND: EXCEPTION_COMPONENT,
// Charts: LAYOUT,
// BaiduMap: () => import('@/views/demo/charts/map/Baidu.vue'),
// AMap: () => import('@/views/demo/charts/map/Gaode.vue'),
// GoogleMap: () => import('@/views/demo/charts/map/Google.vue'),
//
// };
const flatRoutes = {};

function generateRouteMap(routes) {
return routes.map((item) => {
if (item.children && item.children.length > 0) {
generateRouteMap(item.children);
}
flatRoutes[item.name] = item['component'];
});
}

generateRouteMap(asyncRoutes);

export const ROUTE_MAP = flatRoutes

后端菜单数据查询API开发

在menu目录下建立好menu entity、module、data文件并做好接口开发,然后在前端中对接

src/api/sys/menu 目录下现有获取菜单接口,所以在此处改造即可


读书管理后台开发项目-6.管理后台前端权限
https://nanxfu.github.io/2024/09/25/读书管理后台开发项目-6-管理后台前端权限/
Beitragsautor
nanxfu
Veröffentlicht am
September 25, 2024
Urheberrechtshinweis