Vue3 + TypeScript 企业级中后台权限系统实践

共 2214字,需浏览 5分钟

 ·

2026-07-27 18:49

在企业级管理后台里,权限控制是绕不开的核心功能。本文聊聊我在实际项目中落地的一套 RBAC 权限方案,覆盖 菜单级、按钮级、数据级 三层控制。

整体思路

  1. 后端返回当前用户的权限列表(角色 → 菜单权限、按钮权限、数据范围)
  2. 前端根据权限动态生成路由、控制按钮显隐、过滤接口请求
  3. 权限数据存入 Pinia store,全局注入自定义指令和组合式函数

1. 菜单级权限:动态路由

核心是让路由表按权限动态生成,而不是写死在 router 配置里。

// router/permission.ts
import type { RouteRecordRaw } from 'vue-router'

// 所有路由定义,带 meta.roles
const allRoutes: RouteRecordRaw[] = [
{ path: '/dashboard', meta: { title: '仪表盘', roles: ['admin', 'operator'] } },
{ path: '/inventory', meta: { title: '库存管理', roles: ['admin', 'warehouse'] } },
{ path: '/finance', meta: { title: '财务报表', roles: ['admin'] } },
]

export function filterRoutesByRoles(routes: RouteRecordRaw[], roles: string[]) {
return routes.filter(route => {
const routeRoles = route.meta?.roles as string[] | undefined
return !routeRoles || routeRoles.some(r => roles.includes(r))
})
}

用户登录后调用 router.addRoute() 动态注册,侧边栏菜单也基于同一个过滤结果渲染。

2. 按钮级权限:自定义指令 + 组合式函数

页面上的按钮(新增、删除、审核等)按权限隐藏,用自定义指令最简洁:

// directives/permission.ts
import type { Directive } from 'vue'
import { useUserStore } from '@/stores/user'

export const vPermission: Directive = {
mounted(el, binding) {
const { value } = binding // 如 'inventory:delete'
const userStore = useUserStore()
if (!userStore.hasButtonPermission(value)) {
el.parentNode?.removeChild(el)
}
}
}

使用时:<el-button v-permission="'inventory:delete'">删除</el-button>

更灵活的场景用组合式函数:

// composables/usePermission.ts
import { computed } from 'vue'
import { useUserStore } from '@/stores/user'

export function usePermission() {
const userStore = useUserStore()
const can = (perm: string) => computed(() => userStore.hasButtonPermission(perm))
return { can }
}

3. 数据级权限:请求拦截器注入

不同角色看到的数据范围不同,比如普通操作员只能看自己仓库的库存。在 Axios 请求拦截器里统一处理:

// utils/request.ts
service.interceptors.request.use(config => {
const userStore = useUserStore()
if (config.url?.includes('/api/inventory/')) {
if (!userStore.isAdmin) {
config.params = { ...config.params, warehouseId: userStore.warehouseId }
}
}
return config
})

前端控制只是第一层(用户体验),真正的安全依赖后端。

总结

  • 菜单级用动态路由 + router.addRoute()
  • 按钮级用自定义指令 v-permission
  • 数据级用 Axios 拦截器注入过滤参数
  • 权限数据统一走 Pinia store,登录后一次性加载

这套方案在多个实际项目中稳定运行,开发效率和可维护性都不错。欢迎交流你们是如何处理权限管理的。


浏览 34
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报