告别权限判断烦恼:vue-vben-admin hooks体系之usePermission全解析

告别权限判断烦恼:vue-vben-admin hooks体系之usePermission全解析

【免费下载链接】vue-vben-admin 【免费下载链接】vue-vben-admin 项目地址: https://gitcode.com/gh_mirrors/vue/vue-vben-admin

在复杂的后台管理系统开发中,权限控制是一个绕不开的话题。你是否还在为如何优雅地实现按钮级别的权限控制而烦恼?是否还在为不同角色展示不同菜单而头疼?vue-vben-admin的usePermission钩子函数为这些问题提供了优雅的解决方案。本文将深入解析usePermission的实现原理和使用方法,帮助你轻松掌握权限判断逻辑。

权限体系概览

vue-vben-admin的权限系统基于RBAC(Role-Based Access Control,基于角色的访问控制)模型设计,通过钩子函数、状态管理和路由控制相结合的方式,实现了从路由到按钮的全链路权限控制。

权限控制主要涉及以下几个核心模块:

权限模式

vue-vben-admin支持三种权限模式,可在项目配置中设置:

// src/settings/projectSetting.ts
const setting: ProjectConfig = {
  // 权限模式
  permissionMode: PermissionModeEnum.ROUTE_MAPPING,
  // ...
}

三种权限模式分别是:

  1. ROUTE_MAPPING:路由映射模式,基于路由配置的角色信息进行权限控制
  2. ROLE:角色模式,直接通过角色判断权限
  3. BACK:后端模式,通过后端返回的权限码进行权限控制

默认使用ROUTE_MAPPING模式,这是一种灵活且易于维护的权限控制方式。

usePermission核心实现

usePermission钩子是权限判断的入口,提供了丰富的API来满足不同场景的权限判断需求。

核心API

usePermission主要提供了以下几个核心函数:

  • hasPermission:判断是否有权限
  • changeRole:切换角色
  • refreshMenu:刷新菜单
  • togglePermissionMode:切换权限模式

hasPermission实现原理

hasPermission是usePermission中最核心的函数,用于判断用户是否拥有某项权限。其实现逻辑如下:

// src/hooks/web/usePermission.ts
function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {
  // 默认可见
  if (!value) {
    return def;
  }

  const permMode = appStore.getProjectConfig.permissionMode;

  if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) {
    if (!isArray(value)) {
      return userStore.getRoleList?.includes(value as RoleEnum);
    }
    return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
  }

  if (PermissionModeEnum.BACK === permMode) {
    const allCodeList = permissionStore.getPermCodeList as string[];
    if (!isArray(value)) {
      const splits = ['||', '&&'];
      const splitName = splits.find((item) => value.includes(item));
      if (splitName) {
        const splitCodes = value.split(splitName);
        return splitName === splits[0]
          ? intersection(splitCodes, allCodeList).length > 0
          : intersection(splitCodes, allCodeList).length === splitCodes.length;
      }
      return allCodeList.includes(value);
    }
    return (intersection(value, allCodeList) as string[]).length > 0;
  }
  return true;
}

从代码中可以看出,hasPermission函数的逻辑主要分为以下几步:

  1. 如果没有传入权限判断条件,默认返回true(有权限)
  2. 根据当前权限模式,执行不同的权限判断逻辑
  3. 在ROUTE_MAPPING和ROLE模式下,通过角色列表判断权限
  4. 在BACK模式下,通过权限码列表判断权限

角色判断逻辑

在ROUTE_MAPPING和ROLE模式下,权限判断基于角色列表:

if (!isArray(value)) {
  // 单个角色判断
  return userStore.getRoleList?.includes(value as RoleEnum);
}
// 多个角色判断,只要有一个角色匹配即有权限
return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;

角色列表定义在src/enums/roleEnum.ts中:

// src/enums/roleEnum.ts
export enum RoleEnum {
  // 超级管理员
  SUPER = 'super',
  // 测试角色
  TEST = 'test',
}

实际项目中,你可以根据需要扩展更多角色。

权限码判断逻辑

在BACK模式下,权限判断基于后端返回的权限码:

const allCodeList = permissionStore.getPermCodeList as string[];
if (!isArray(value)) {
  // 支持"||"和"&&"逻辑运算符
  const splits = ['||', '&&'];
  const splitName = splits.find((item) => value.includes(item));
  if (splitName) {
    const splitCodes = value.split(splitName);
    return splitName === splits[0]
      ? // "||"逻辑,有一个权限码匹配即有权限
        intersection(splitCodes, allCodeList).length > 0
      : // "&&"逻辑,所有权限码都匹配才有权限
        intersection(splitCodes, allCodeList).length === splitCodes.length;
  }
  return allCodeList.includes(value);
}
return (intersection(value, allCodeList) as string[]).length > 0;

这种方式支持复杂的权限判断逻辑,如"perm1||perm2"(拥有perm1或perm2权限)或"perm1&&perm2"(同时拥有perm1和perm2权限)。

权限判断实战

掌握了usePermission的实现原理后,让我们看看如何在实际项目中使用它进行权限判断。

基础使用方法

首先需要在组件中引入usePermission钩子:

import { usePermission } from '@/hooks/web/usePermission';

const { hasPermission } = usePermission();

然后就可以使用hasPermission函数进行权限判断了。

角色权限判断

判断用户是否为超级管理员:

const isSuper = hasPermission(RoleEnum.SUPER);

判断用户是否为超级管理员或测试角色:

const hasRole = hasPermission([RoleEnum.SUPER, RoleEnum.TEST]);

权限码判断

在BACK模式下,可以通过权限码判断权限:

// 判断是否有查看用户的权限
const canViewUser = hasPermission('user:view');

// 判断是否有编辑或删除用户的权限
const canEditOrDeleteUser = hasPermission('user:edit||user:delete');

// 判断是否同时有创建和审核用户的权限
const canCreateAndAuditUser = hasPermission('user:create&&user:audit');

组件级权限控制

在模板中,可以直接使用hasPermission进行条件渲染:

<template>
  <button v-if="hasPermission('user:create')">创建用户</button>
  <button v-if="hasPermission([RoleEnum.SUPER, RoleEnum.TEST])">测试按钮</button>
</template>

<script setup lang="ts">
import { usePermission } from '@/hooks/web/usePermission';
import { RoleEnum } from '@/enums/roleEnum';

const { hasPermission } = usePermission();
</script>

路由权限控制

在路由配置中,可以通过meta.roles指定访问该路由所需的角色:

// 示例路由配置
const routes: AppRouteRecordRaw[] = [
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('@/views/dashboard/index.vue'),
    meta: {
      roles: [RoleEnum.SUPER], // 只有超级管理员可以访问
      title: '仪表盘',
    },
  },
];

路由权限控制的实现逻辑在src/store/modules/permission.ts中,通过buildRoutesAction函数构建有权限访问的路由列表。

高级功能

切换角色

usePermission提供了changeRole函数,可以动态切换用户角色:

const { changeRole } = usePermission();

// 切换为测试角色
changeRole(RoleEnum.TEST);

// 切换为多个角色
changeRole([RoleEnum.SUPER, RoleEnum.TEST]);

切换角色后,系统会自动刷新路由和菜单,只显示当前角色有权限访问的内容。

刷新菜单

当权限发生变化时,可以使用refreshMenu函数刷新菜单:

const { refreshMenu } = usePermission();

// 刷新菜单
refreshMenu();

这在权限动态变化的场景下非常有用,如管理员修改了用户的权限后,用户无需重新登录即可看到权限变更后的菜单。

切换权限模式

usePermission还提供了切换权限模式的功能:

const { togglePermissionMode } = usePermission();

// 切换权限模式
togglePermissionMode();

切换后会自动刷新页面,应用新的权限模式。

权限状态管理

权限相关的状态通过permissionStore进行管理,位于src/store/modules/permission.ts

permissionStore核心状态

permissionStore定义了以下核心状态:

interface PermissionState {
  // 权限代码列表
  permCodeList: string[] | number[];
  // 路由是否动态添加
  isDynamicAddedRoute: boolean;
  // 触发菜单更新的时间戳
  lastBuildMenuTime: number;
  // 后台菜单列表
  backMenuList: Menu[];
  // 前端菜单列表
  frontMenuList: Menu[];
}

构建路由

buildRoutesAction是permissionStore中的核心函数,用于根据权限构建路由列表:

// src/store/modules/permission.ts
async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
  // 根据不同的权限模式构建路由
  // ...
}

该函数会根据当前的权限模式和用户角色,过滤出用户有权限访问的路由,并转换为菜单数据。

总结

vue-vben-admin的usePermission钩子为我们提供了一套完整而灵活的权限控制方案,通过角色和权限码的双重判断机制,可以满足各种复杂的权限需求。无论是简单的角色判断,还是复杂的权限码逻辑判断,usePermission都能轻松应对。

通过本文的介绍,相信你已经对usePermission的实现原理和使用方法有了深入的了解。在实际项目中,你可以根据需求选择合适的权限模式,并结合usePermission提供的API,快速实现从路由到按钮的全链路权限控制。

掌握usePermission,让权限控制变得简单而优雅,为你的项目保驾护航。

【免费下载链接】vue-vben-admin 【免费下载链接】vue-vben-admin 项目地址: https://gitcode.com/gh_mirrors/vue/vue-vben-admin

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值