权限管理是 B 端系统中非常常见、但又容易出坑的模块。
一、权限管理核心思路🧠
权限控制通常包括三类:
权限类型 | 举例 | 控制方式 |
---|---|---|
路由权限 | 页面级访问(如 /admin) | 路由守卫(beforeEach) |
组件权限 | 页面中的某个功能区块 | v-if、组件显示与否 |
按钮权限 | 新增/编辑/删除按钮 | 自定义指令控制显示 / 禁用 |
二、按钮级权限控制的实现方案📦
常见做法:基于指令(v-permission)
你可以封装一个指令,判断当前用户是否具备某权限:
1)定义权限指令
// directives/permission.ts
import { DirectiveBinding } from 'vue'
import { useUserStore } from '@/stores/user'
export default {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const userStore = useUserStore()
const permission = binding.value
if (!userStore.permissions.includes(permission)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
2)注册全局指令
// main.ts
import permission from '@/directives/permission'
app.directive('permission', permission)
3)使用方式
<!-- 只有有 'user:add' 权限才显示 -->
<el-button v-permission="'user:add'">新增用户</el-button>
三、用户权限的来源 🧰
在项目中通常有几种方式获取当前用户权限:
来源 | 举例 |
---|---|
登录返回的用户权限码列表 | 如:[‘user:add’, ‘user:edit’] |
后台返回的菜单结构中嵌套权限 | 菜单中含按钮权限字段 |
动态角色切换后更新权限列表 | Admin / 普通用户 等切换场景 |
四、配合组件逻辑封装权限判断工具函数 🧩
// utils/permission.ts
export function hasPermission(code: string) {
const userStore = useUserStore()
return userStore.permissions.includes(code)
}
用在业务中:
<el-button v-if="hasPermission('user:delete')">删除</el-button>
<template>
<div>
<el-button v-permission="'patient:add'">新增患者</el-button>
<el-button v-if="hasPermission('patient:edit')">编辑</el-button>
<el-button :disabled="!hasPermission('patient:export')">导出数据</el-button>
</div>
</template>
五、最佳实践总结 ✨
建议 | 原因 |
---|---|
权限控制逻辑统一放到指令 / 方法中 | 避免业务中到处写重复逻辑 |
尽量控制在 DOM 层(隐藏/禁用) | 安全性更高,避免误操作 |
后台接口也要二次校验权限 | 前端控制 ≠ 安全控制 |
权限码统一管理为常量 or 枚举 | 避免写错权限码(如 USER_ADD) |
总结 🔚
- 按钮权限推荐使用指令 + 用户权限列表来控制;
- 提前在登录后拿到权限列表,保存在 Pinia;
- 页面中使用 v-permission 或 hasPermission() 函数判断是否可见;
- 可以扩展为禁用、隐藏、弹提示等多种行为;
- 后端配合更安全可靠,前后双重校验。