Skip to content

权限指令

概述

权限指令基于 Vue 自定义指令机制实现,提供细粒度的前端权限控制能力。系统内置两种权限指令:

  • v-has-role - 角色权限指令,根据用户角色控制元素显示
  • v-has-perm - 操作权限指令,根据权限标识控制按钮显示

技术实现

采用 Vue 原生的自定义指令(Custom Directives)机制,通过在元素挂载时检查用户权限,自动控制 DOM 元素的显示与隐藏。详细实现逻辑请参考 前端指南 - 权限控制系统

配置角色权限

1. 创建角色代码

角色代码是角色权限的唯一标识符,用于在前端代码中进行权限判断。

操作步骤:

  1. 进入 权限管理 > 角色管理 界面
  2. 点击 新增 或选择已有角色点击 编辑
  3. 角色代码 字段中填入角色标识(要求:英文字符,系统内唯一)
  4. 填写其他必要信息后,点击 确定 保存

角色代码配置

注意事项

  • 角色代码必须使用英文字符(建议小写,如:adminmanager
  • 角色代码在系统中必须唯一,不可重复
  • 角色代码一旦创建,建议不要随意修改,以免影响已有的权限配置

配置操作权限

1. 创建按钮权限标识

按钮权限标识用于细粒度的操作权限控制,通常对应具体的业务操作(如新增、编辑、删除等)。

操作步骤:

  1. 进入 权限管理 > 菜单管理 界面
  2. 点击 新增 或选择已有菜单点击 编辑
  3. 菜单类型 下拉框中选择 按钮
  4. 权限标识 字段中填入权限码(格式:模块:功能:操作,如:sys:user:add
  5. 填写其他必要信息后,点击 确定 保存

按钮权限标识配置

权限标识命名规范

建议采用三段式命名格式:模块:功能:操作

  • 模块:系统模块标识,如 sys(系统)、biz(业务)
  • 功能:具体功能模块,如 user(用户)、role(角色)
  • 操作:具体操作类型,如 add(新增)、edit(编辑)、delete(删除)、view(查看)

示例:sys:user:addsys:role:editbiz:order:delete

2. 为角色分配按钮权限

创建权限标识后,需要将其分配给相应的角色,用户才能拥有该操作权限。

操作步骤:

  1. 进入 权限管理 > 角色管理 界面
  2. 选择需要授权的角色,点击 设置权限
  3. 在弹出的对话框中,切换到 角色菜单 选项卡
  4. 在菜单树中找到刚才创建的按钮权限,勾选该选项
  5. 点击 确定 完成权限分配

角色权限分配

前端使用指南

配置完成后,即可在前端页面中使用权限指令控制元素的显示与隐藏。

使用角色权限指令 v-has-role

角色权限指令用于根据用户角色控制功能模块或页面区域的显示。

基础用法:

vue
<template>
  <!-- 单个角色判断 -->
  <el-button v-has-role="'admin'" type="primary"> 管理员专属功能 </el-button>

  <!-- 多个角色判断(满足任意一个角色即可显示) -->
  <el-button v-has-role="['admin', 'manager']" type="primary">
    管理功能
  </el-button>

  <!-- 控制整个功能区域 -->
  <div v-has-role="['admin']">
    <h3>管理员控制面板</h3>
    <p>此区域仅管理员可见</p>
  </div>
</template>

应用场景:

  • 控制管理后台的不同功能模块显示
  • 根据用户角色展示不同的操作面板
  • 隐藏普通用户不应看到的高级功能

使用操作权限指令 v-has-perm

操作权限指令用于细粒度的按钮级权限控制,精确控制用户的具体操作权限。

基础用法:

vue
<template>
  <!-- 单个权限判断 -->
  <el-button v-has-perm="'sys:user:add'" type="primary" @click="handleAdd">
    新增用户
  </el-button>

  <!-- 多个权限判断(满足任意一个权限即可显示) -->
  <el-button
    v-has-perm="['sys:user:edit', 'sys:user:update']"
    type="success"
    @click="handleEdit"
  >
    编辑
  </el-button>

  <!-- 组合使用多个权限按钮 -->
  <el-space>
    <el-button v-has-perm="'sys:user:add'" type="primary" icon="Plus">
      新增
    </el-button>
    <el-button v-has-perm="'sys:user:edit'" type="success" icon="Edit">
      编辑
    </el-button>
    <el-button v-has-perm="'sys:user:delete'" type="danger" icon="Delete">
      删除
    </el-button>
  </el-space>

  <!-- 在下拉菜单中使用 -->
  <el-dropdown>
    <el-button type="primary">
      更多操作 <el-icon class="el-icon--right"><arrow-down /></el-icon>
    </el-button>
    <template #dropdown>
      <el-dropdown-menu>
        <el-dropdown-item v-has-perm="'sys:user:export'">
          导出数据
        </el-dropdown-item>
        <el-dropdown-item v-has-perm="'sys:user:import'">
          导入数据
        </el-dropdown-item>
        <el-dropdown-item v-has-perm="'sys:user:reset'" divided>
          重置密码
        </el-dropdown-item>
      </el-dropdown-menu>
    </template>
  </el-dropdown>
</template>

应用场景:

  • 控制列表页的增删改查按钮显示
  • 限制敏感操作(如删除、导出)的执行权限
  • 在表格行操作列中动态显示可用操作按钮

权限指令与路由守卫的区别

  • 权限指令:控制页面内元素的显示与隐藏,属于前端视觉控制
  • 路由守卫:控制页面访问权限,属于页面级别控制

重要提示: 前端权限控制仅用于提升用户体验,真正的权限验证必须在后端进行。前端权限可以被绕过,因此后端 API 必须实施完整的权限校验机制。

最佳实践

1. 权限粒度建议

vue
<!-- ✅ 推荐:细粒度权限控制 -->
<el-button v-has-perm="'sys:user:add'">新增</el-button>
<el-button v-has-perm="'sys:user:edit'">编辑</el-button>
<el-button v-has-perm="'sys:user:delete'">删除</el-button>

<!-- ❌ 不推荐:权限过于粗糙 -->
<el-button v-has-perm="'sys:user'">所有操作</el-button>

2. 权限指令组合使用

vue
<template>
  <!-- 同时满足角色和操作权限 -->
  <div v-has-role="'admin'">
    <el-button v-has-perm="'sys:config:edit'" type="primary">
      系统配置
    </el-button>
  </div>
</template>

3. 权限缺失时的提示

vue
<template>
  <el-tooltip content="您没有删除权限" :disabled="hasDeletePerm">
    <span>
      <el-button
        v-has-perm="'sys:user:delete'"
        type="danger"
        :disabled="!hasDeletePerm"
      >
        删除
      </el-button>
    </span>
  </el-tooltip>
</template>

常见问题

Q1: 权限指令不生效,元素仍然显示?

可能原因:

  1. 用户权限未正确加载(检查 Pinia store 中的权限数据)
  2. 权限标识拼写错误(区分大小写)
  3. 用户未重新登录获取最新权限

解决方案:

javascript
// 在浏览器控制台检查用户权限
import { useUserStore } from "@/pinia/modules/user";
const userStore = useUserStore();
console.log("角色列表:", userStore.userInfo.roleCodes);
console.log("权限列表:", userStore.userInfo.authCodes);

Q2: 如何在 JavaScript 代码中判断权限?

解决方案:

javascript
import { useUserStore } from "@/pinia/modules/user";

const userStore = useUserStore();

// 判断是否拥有某个角色
const hasAdminRole = userStore.userInfo.roleCodes.includes("admin");

// 判断是否拥有某个权限
const hasAddPerm = userStore.userInfo.authCodes.includes("sys:user:add");

// 在方法中使用
const handleOperation = () => {
  if (!hasAddPerm) {
    ElMessage.warning("您没有新增权限");
    return;
  }
  // 执行操作...
};

Q3: 权限配置后需要多久生效?

权限配置修改后:

  • 后端权限:立即生效(下次 API 请求时验证)
  • 前端权限:需要用户重新登录或刷新页面以重新加载权限信息

版权所有 © 2021-2026 ApeVolo-Team