权限
# 权限
# 项目中集成了三种权限处理方式:
1、通过用户角色来过滤菜单(前端方式控制),路由在前端配置,通过API返回角色过滤
2、通过后台来动态生成路由表(后台方式控制)
3、通过后台返回所有权限集合(包括菜单和按钮),前端固定路由,进行过滤
# 权限测试
项目菜单权限-FIXED模式 随机(普通管理员/超级管理员)角色权限示例
项目菜单权限-BACK模式随机(普通管理员/超级管理员)角色权限示例
说明超级管理员拥有 主控台列表页面 权限,普通管理员拥有 主控台 权限
测试退出登录>重新登录 或者刷新页面>查看效果
# 前端固定路由
# 实现原理
在前端固定写死路由的权限,指定路由有哪些权限可以查看,只初始化通用的路由,需要权限才能访问的路由没有被加入路由表内,在登陆后或者其他方式获取用户角色后,通过角色去遍历路由表,获取该角色可以访问的路由表,生成路由表,再通过 router.addRoute 添加到路由实例,实现权限的过滤。
# 缺点
权限相对不自由,如果后台改动角色,前台也需要跟着改动,适合角色较固定的系统。
# 实现
在项目配置projectSetting.ts将系统内权限模式改为ROLE模式
# 后端动态路由
# 实现原理
在前端固定,路由表对应的组件映射map,通过API获取路由表,动态生成路由,再通过 router.addRoute 添加到路由实例,实现权限的过滤。
# 缺点
前端需要维护一个路由表,保持和后端一致,如果后台改动角色,前台也需要跟着改动
# 提示
多级路由,当没有配置时,redirect默认为第一个子路由,配置则优先按配置
# 实现
import { RouteRecordRaw } from 'vue-router';
import { Layout } from '@/router/constant';
import { DashboardOutlined } from '@vicons/antd';
import { renderIcon } from '@/utils/index';
const routeName = 'dashboard';
const routes: Array<RouteRecordRaw> = [
{
path: '/dashboard',
name: routeName,
redirect: '/dashboard/console',
component: Layout,
meta: {
title: 'Dashboard',
icon: renderIcon(DashboardOutlined),
//这里配置父级路由需要哪些权限可访问 这里是子路由权限集合
permissions: ['dashboard_console', 'dashboard_console', 'dashboard_workplace'],
sort: 0,
},
children: [
{
path: 'console',
name: `${ routeName }_console`,
meta: {
title: '主控台',
//配置该路由需要哪些权限可访问 这里是针对单个路由
permissions: ['dashboard_console'],
},
component: () => import('@/views/dashboard/console/console.vue'),
},
],
},
];
export default routes;
接口返回数据结构 请参考,/mock/user/menu.ts menusList
# 通过所有权限
# 实现原理
在前端固定路由表,并且配置路由所需的权限,实现权限的过滤。
# 缺点
权限过多,不易维护,毕竟权限集合不在前端定义
# 优点
简单,实用,菜单,按钮,等所有权限都可以通吃
import { RouteRecordRaw } from 'vue-router';
import { Layout } from '@/router/constant';
import { DashboardOutlined } from '@vicons/antd';
import { renderIcon } from '@/utils/index';
const routeName = 'dashboard';
const routes: Array<RouteRecordRaw> = [
{
path: '/dashboard',
name: routeName,
redirect: '/dashboard/console',
component: Layout,
meta: {
title: 'Dashboard',
icon: renderIcon(DashboardOutlined),
//这里配置父级路由需要哪些权限可访问 这里是子路由权限集合
permissions: ['dashboard_console', 'dashboard_console', 'dashboard_workplace'],
sort: 0,
},
children: [
{
path: 'console',
name: `${ routeName }_console`,
meta: {
title: '主控台',
//配置该路由需要哪些权限可访问 这里是针对单个路由
permissions: ['dashboard_console'],
},
component: () => import('@/views/dashboard/console/console.vue'),
},
],
},
];
export default routes;
# 细粒度权限
# 函数方式
usePermissions 还提供了按钮级别的权限控制。
<template>
<n-button v-if="hasPermissions([RoleEnum.ADMIN, RoleEnum.NORMAL])">
拥有[admin,normal]权限可见
</n-button>
</template>
<script lang="ts">
import { usePermissions } from '@/hooks/web/usePermissions';
import { RoleEnum } from '@/enums/roleEnum';
export default defineComponent({
setup() {
const { hasPermissions } = usePermissions();
return { hasPermissions, RoleEnum };
},
});
</script>
# 指令方式
<!-- seffect参数 'disabled' 禁用按钮 不传 默认移除按钮 -->
<n-button v-permissions="{action:['RoleEnum.ADMIN, RoleEnum.NORMAL'], effect:'disabled'}" type="primary" class="mx-4"> 拥有admin,normal角色权限可见</n-button>