动机(motive)
在后管系统开发中,菜单和按钮权限设置是一项基础但繁琐的工作。传统的权限管理流程如下:
1.前端开发环节:
- 开发人员需手动在路由配置中绑定access权限标识
- 在src/access.ts中声明所有权限code
- 对于按钮级权限,同样需要在access文件中预先定义
2.后台配置环节:
- 在资源管理页面逐个创建权限项
- 为每个权限code设置名称和描述
权限配置示例
当项目规模较小时(3-5个页面),这种手动配置尚可接受。但面对中大型项目(50-80+页面)时,这种工作方式存在明显问题:
时间成本高:大量重复性手动操作
容易出错:人工配置难免出现code与权限不匹配的情况
维护困难:权限变更时需要同步修改多处配置
秉承"能自动化绝不手动"的开发理念,我们设计了权限管理自动化方案,针对不同技术栈提供定制化实现:对于React 后管 和 Vue 后管我们各自有不同的实现方案。下面会详细讲述
React 使用 umi-plugin-access-code
信息
基于umi框架体系编写的一个帮助开发人员管理权限code的插件
UMI有提供一个开箱即用的权限插件 当你需要配置路由权限。你只需要再路由中加上access
参数。就像这样
// config/route.ts
export const routes = [
{
path: '/pageA',
component: 'PageA',
access: 'canReadPageA', // 权限定义返回值的某个 key
}
]
然后你需要同时在src/access.ts
同时声明这个canReadPageA为false。如果你需要关联按钮权限。上面的链接也提供的相应的方案去解决。
接下来来看下umi-plugin-access-code
插件是如何将这些动作自动化的
信息
umi3 的权限插件地址在这里: https://v3.umijs.org/zh-CN/plugins/plugin-access。使用方式是一样的
使用
插件默认内置到框架中并且在 pnpm dev 时会自动启动。当你修改了 config/routes 下的内容。它会自动生在 src/access.ts 文件中生成相关的权限内容
手动运行
你也可以在项目目录下运行命令 来手动执行生成
pnpm code
或
npm run code
当你运行命令 yarn code
时,这将会在src/access.ts
中根据路由路径以及额外信息。生成所有的access code。并且会有一段CODE_START
的标注。像这样:
注意
并且如果你的sql设置为true。会同时在src
目录下生成一份access.sql
文件。下面我们也会详细解释
配置参数
这个插件很简单。只有三个参数配置。在 config/config.ts 中你会看到这样的配置
// ...ignore others
accessCodes: {
// routeInejct 路由注入
routeInject: REACT_APP_ENV !== 'dev',
// 排除的code
exclude: ['home', 'login', 'user-setting', 'user-notices', 'sysSetting-resourcesManagement'],
// 是否生成sql文件
sql: true
},
routeInejct 路由注入
上面我们提到。如果你需要配置路由级的权限。那你就要在路由上写上access: xxx
来绑定对应的code。所以首先就通过 routeInejct 配置来解决这里的手动编写的问题
让我们来举个例子。让你直观的理解这个过程。假设我们有这么一个路由
// config/route.ts
export const routes = [
{
path: '/page',
component: 'Page',
access: 'page', // 权限定义返回值的某个 key
children: [{
path: '/page/child',
component: 'Page/child',
access: 'pageChild', // 权限定义返回值的某个 key
}]
}
]
我们发现。我们完全可以将access的值按照特殊的规则(即:组合path,删除斜杠并且子级首字母大写的方式)来定义。这样既直观。而且也非常可靠好记。
既然有这种规律的模式。那我们是不是可以将这个行为自动化? 所以。当你设置 routeInejct: true
时。那么在项目启动编译时。我们可以动态的改写运行时路由代码。将access参数按照特定的规则动态写入。这样你就不用手动的一个一个的编写access参数了
// config/route.ts
export const routes = [
{
path: '/page',
component: 'Page',
// access: 'page', // 不用写了。插件会帮你写上
children: [{
path: '/page/child',
component: 'Page/child',
// access: 'pageChild', // 不用写了。插件会帮你写上
}]
}
]
信息
事实上。我们设置的是 routeInject: REACT_APP_ENV !== 'dev'。表示开发环境时不注入。所有权限都会开放。这样方便开发工作
exclude 排除
有了上面的例子。我们知道。所有的path都会被绑定access
参数。但是有些公共页面。比如登录注册等不需要绑定权限的路由页面也会被关联照顾。为了解决误伤的问题。你可以通过exclude
参数。传递不需要绑定的code.
警告
sql
上面的操作。我们解决了手动编写路由表中 access
与src/access.ts
这两处的工作。那么。在资源管理页面手动创建code的工作。我们还没解决。所以,这个配置参数就是用来解决这最后问题的。
当你设置sql: true
时。 运行 yarn code
会在src/access.ts
中生成一份code。同时会在同级下生成一份access.sql
脚本文件。
此时你可以将这份脚本文件提供给后端同学。让他在数据库中运行一下。 这时候。你再去刷新一下资源管理页面。 你会惊奇的发现。所有的资源都已经创建好了。并且帮你正确的关联了父子级关系!
按钮级权限绑定
有时候你不仅只是需要绑定菜单路由权限。业务需要更加细粒度的控制。比如说到按钮基本的操作权限。甚至对于接口资源也需要绑定相关的权限控制
此时,我们就需要扩展这一需求。如何来做呢?其实也非常简单。我们只需要在页面路由中加入operationAccess
扩展参数即可。
export default [
{
name: '基础设置',
path: '/basicSetting',
routes: [
{
name: '素材库',
path: '/basicSetting/materialLibrary',
component: './basicSetting/materialLibrary',
// 按钮级权限绑定
operationAccess: [
{name:'新增', code: 'add'},
{name:'编辑', code: 'edit'},
{name:'删除', code: 'delete'},
{name:'查看', code: 'view'}
]
}
]
}
]
上面的示例最终会在路径的基础上扩展出四个按钮权限code。并帮你完成注入。
// src/access.ts
export const codes = [
'basicSetting',
'basicSetting-materialLibrary',
'basicSetting-materialLibrary-add',
'basicSetting-materialLibrary-edit',
'basicSetting-materialLibrary-delete',
'basicSetting-materialLibrary-view',
]
警告
当然按钮的权限 你依然需要配合UMI框架中的 <Access>
组件或者 useAccess
hook来使用
Vue 使用 vite-plugin-access-code
Vue + Vite 后管系统也提供了 React类似的 插件包 vite-plugin-access-code
信息
此插件是跟随在项目中并且没有发布到 npm 平台
Vue 如果要配置路由权限。需要在路由配置中加入权限配置 access。
{
path: 'operation-log',
meta: {
title: '操作日志',
access: 'operation-log', // 配置权限code
icon: 'ant-design:desktop-outlined',
keepAlive: false
},
component: () => import('@/pages/sys-setting/operation-log/index.vue')
}
同时需要在 src/permission/permCode.ts 文件中声明权限code 。如果有按钮权限也需要一并在文件中声明。
接下来看下插件如何将此动作自动化
使用
插件默认内置到框架中并且在 pnpm dev 时会自动启动。当你修改了 src/router/routes 下的内容。它会自动生在 src/permission/permCode.ts 文件中生成相关的权限内容
配置参数
插件同样有三个参数。相关配置内容。同上面一样。此处不再赘述
按钮权限
同React插件一样。按钮级别权限也是在路由配置中加入 operationAccess
参数即可
{
path: 'operation-log',
meta: {
title: '操作日志',
access: 'operation-log',
operationAccess: [
{ name: '新增', code: 'add' },
{ name: '编辑', code: 'edit' },
],
icon: 'ant-design:desktop-outlined',
keepAlive: false
},
component: () => import('@/pages/sys-setting/operation-log/index.vue')
}
同样,也会在 src/permission/permCode.ts 中扩展出操作权限code
const permissions = [
// CODE_START
/**
* 权限code
* 以下内容均为access-code插件生成(CODE_START至CODE_END部分)
* 所以请勿在此区域内写入内容。
*/
'sys-setting-operation-log',
'sys-setting-operation-log-add'
'sys-setting-operation-log-edit'
// CODE_END
] as const
关于按钮权限的绑定。提供了一个全局 指令 v-auth
和 hasPermission
函数 来鉴权
写在最后
至此,我们已经完整介绍了本插件的使用方法和实现原理。正如开篇所言,这套自动化方案的核心价值在于提升开发效率——它为您提供了一个可选的提效工具,而非强制性规范。
如果您更倾向于传统的手动配置方式,或者项目有特殊需求,您完全可以:
继续沿用原有的权限管理方式
参考官方文档进行手动配置
自由选择部分自动化功能与手动配置相结合