Skip to content

动机(motive)

在后管系统开发中,菜单和按钮权限设置是一项基础但繁琐的工作。传统的权限管理流程如下:

  • 1.前端开发环节:

    • 开发人员需手动在路由配置中绑定access权限标识
    • 在src/access.ts中声明所有权限code
    • 对于按钮级权限,同样需要在access文件中预先定义
  • 2.后台配置环节:

    • 在资源管理页面逐个创建权限项
    • 为每个权限code设置名称和描述

权限配置示例 1

当项目规模较小时(3-5个页面),这种手动配置尚可接受。但面对中大型项目(50-80+页面)时,这种工作方式存在明显问题:

  • 时间成本高:大量重复性手动操作

  • 容易出错:人工配置难免出现code与权限不匹配的情况

  • 维护困难:权限变更时需要同步修改多处配置

秉承"能自动化绝不手动"的开发理念,我们设计了权限管理自动化方案,针对不同技术栈提供定制化实现:对于React 后管 和 Vue 后管我们各自有不同的实现方案。下面会详细讲述

React 使用 umi-plugin-access-code

信息

基于umi框架体系编写的一个帮助开发人员管理权限code的插件

UMI有提供一个开箱即用的权限插件 当你需要配置路由权限。你只需要再路由中加上access参数。就像这样

typescript
// config/route.ts
export const routes =  [
  {
    path: '/pageA',
    component: 'PageA',
    access: 'canReadPageA', // 权限定义返回值的某个 key
  }
]

然后你需要同时在src/access.ts同时声明这个canReadPageA为false。如果你需要关联按钮权限。上面的链接也提供的相应的方案去解决。

接下来来看下umi-plugin-access-code插件是如何将这些动作自动化的

使用

插件默认内置到框架中并且在 pnpm dev 时会自动启动。当你修改了 config/routes 下的内容。它会自动生在 src/access.ts 文件中生成相关的权限内容

手动运行

你也可以在项目目录下运行命令 来手动执行生成

bash
  pnpm code

  npm run code

当你运行命令 yarn code 时,这将会在src/access.ts中根据路由路径以及额外信息。生成所有的access code。并且会有一段CODE_START的标注。像这样:

2

注意

CODE_START 与 CODE_END 中的内容都是自动生成的。请不要修改或者在里面写入任何内容。因为他会在你重新运行 yarn code 时覆盖掉!!

并且如果你的sql设置为true。会同时在src目录下生成一份access.sql文件。下面我们也会详细解释

配置参数

这个插件很简单。只有三个参数配置。在 config/config.ts 中你会看到这样的配置

typescript
// ...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 配置来解决这里的手动编写的问题

让我们来举个例子。让你直观的理解这个过程。假设我们有这么一个路由

typescript
// 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参数了

typescript
// 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.

警告

注意排除的是 code 不是 path

sql

上面的操作。我们解决了手动编写路由表中 accesssrc/access.ts这两处的工作。那么。在资源管理页面手动创建code的工作。我们还没解决。所以,这个配置参数就是用来解决这最后问题的。

当你设置sql: true时。 运行 yarn code 会在src/access.ts中生成一份code。同时会在同级下生成一份access.sql脚本文件。

此时你可以将这份脚本文件提供给后端同学。让他在数据库中运行一下。 这时候。你再去刷新一下资源管理页面。 你会惊奇的发现。所有的资源都已经创建好了。并且帮你正确的关联了父子级关系!

按钮级权限绑定

有时候你不仅只是需要绑定菜单路由权限。业务需要更加细粒度的控制。比如说到按钮基本的操作权限。甚至对于接口资源也需要绑定相关的权限控制

此时,我们就需要扩展这一需求。如何来做呢?其实也非常简单。我们只需要在页面路由中加入operationAccess扩展参数即可。

ts
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。并帮你完成注入。

ts
// src/access.ts
export const codes = [
  'basicSetting',
  'basicSetting-materialLibrary',
  'basicSetting-materialLibrary-add',
  'basicSetting-materialLibrary-edit',
  'basicSetting-materialLibrary-delete',
  'basicSetting-materialLibrary-view',
]

警告

当然按钮的权限 你依然需要配合UMI框架中的 <Access> 组件或者 useAccesshook来使用

Vue 使用 vite-plugin-access-code

Vue + Vite 后管系统也提供了 React类似的 插件包 vite-plugin-access-code

信息

此插件是跟随在项目中并且没有发布到 npm 平台

Vue 如果要配置路由权限。需要在路由配置中加入权限配置 access

typescript
{
  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 参数即可

ts
{
  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

ts
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-authhasPermission函数 来鉴权

写在最后

至此,我们已经完整介绍了本插件的使用方法和实现原理。正如开篇所言,这套自动化方案的核心价值在于提升开发效率——它为您提供了一个可选的提效工具,而非强制性规范。

如果您更倾向于传统的手动配置方式,或者项目有特殊需求,您完全可以:

  • 继续沿用原有的权限管理方式

  • 参考官方文档进行手动配置

  • 自由选择部分自动化功能与手动配置相结合