Vue3 + Pinia 实现企业级 RBAC 权限控制系统(学生实战笔记)

📅 2026/7/12 11:23:17 👁️ 阅读次数 📝 编程学习
Vue3 + Pinia 实现企业级 RBAC 权限控制系统(学生实战笔记)

大家好,我是一名正在学习前端开发的大二学生。最近在做Vue3 能源管理平台项目时,遇到了权限控制这个核心难点。为了真正理解并掌握它,我把实现过程、踩过的坑、完整代码都整理成这篇笔记,既方便自己回顾,也分享给同样在学习的同学~

在企业后台管理系统里,RBAC 基于角色的权限控制是必考点,也是真实项目里最常用的方案。这篇文章完全按照学生学习视角,从思路到代码一步步写,不搞复杂术语,能直接看懂、直接用在自己的项目里。

项目完整源码我已放到 GitHub:https://github.com/HY-koi/Vue3-Energy-Management-Platform

欢迎大家 Star、Fork,一起学习交流~


一、为什么要做权限控制?

在做后台管理项目时,我们经常需要:

  • 不同角色看到不同菜单
  • 未登录不能进页面
  • 某些按钮只有管理员能看见
  • 刷新页面不能白屏、不能丢失权限

这些需求,靠简单的判断根本不够用,必须用一套完整的 RBAC 权限方案


二、我的实现思路(学生易懂版)

  1. 用户登录拿到 token
  2. 根据 token 请求用户信息与菜单列表
  3. 把后端返回的菜单转成前端路由
  4. router.addRoute动态挂载路由
  5. 用 Pinia 保存权限、菜单、用户信息
  6. 路由守卫做登录判断与权限恢复
  7. 自定义指令实现按钮级权限

三、完整实现代码(可直接复制到项目)

1. 路由基础配置

typescript

运行

// src/router/index.ts import { createRouter, createWebHistory } from 'vue-router' const routes = [ { path: '/login', component: () => import('@/views/login/index.vue') }, { path: '/:pathMatch(.*)*', component: () => import('@/views/404.vue') } ] const router = createRouter({ history: createWebHistory(), routes }) export default router

2. Pinia 权限仓库(核心)

typescript

运行

// src/store/auth.ts import { defineStore } from 'pinia' import { ref } from 'vue' import router from '@/router' export const useAuthStore = defineStore('auth', () => { const token = ref('') const userInfo = ref(null) const menuList = ref([]) const permissions = ref([]) // 保存 token const setToken = (val) => { token.value = val localStorage.setItem('token', val) } // 动态添加路由 const addRoutes = (menus) => { menus.forEach((item) => { if (item.path && item.component) { router.addRoute({ path: item.path, name: item.name, component: () => import(`@/views/${item.component}`), meta: { title: item.title, icon: item.icon } }) } if (item.children) { item.children.forEach((child) => { router.addRoute(item.name, { path: child.path, name: child.name, component: () => import(`@/views/${child.component}`), meta: { title: child.title } }) }) } }) } return { token, userInfo, menuList, permissions, setToken, addRoutes } })

3. 路由守卫(解决刷新丢失)

typescript

运行

// src/router/guard.ts import router from './index' import { useAuthStore } from '@/store/auth' import { getUserInfo } from '@/api/user' router.beforeEach(async (to, from, next) => { const store = useAuthStore() const token = store.token || localStorage.getItem('token') // 未登录 if (!token) { return to.path === '/login' ? next() : next('/login') } // 刷新后重新获取权限 if (store.menuList.length === 0) { const { data } = await getUserInfo() store.menuList = data.menuList store.permissions = data.permissions store.addRoutes(data.menuList) return next({ ...to, replace: true }) } next() })

4. 按钮权限指令 v-permission

typescript

运行

// src/directives/permission.ts import { useAuthStore } from '@/store/auth' export default { mounted(el, binding) { const store = useAuthStore() if (!store.permissions.includes(binding.value)) { el.style.display = 'none' } } }

typescript

运行

// main.ts 全局注册 import permission from '@/directives/permission' app.directive('permission', permission)

使用:

html

预览

<el-button v-permission="'station:add'">新增充电站</el-button>

四、我踩过的坑(给同学避坑)

  1. 刷新页面路由丢失解决:在路由守卫里判断菜单是否为空,为空就重新获取。

  2. 404 页面把正常路由挡住解决:404 路由放在最后。

  3. Vite 不能用变量直接 import解决:使用字符串映射或提前配置组件路径。

  4. 按钮权限不生效解决:检查权限标识是否完全一致。


五、学习总结(学生视角)

通过这次实战,我真正掌握了:

  • 什么是 RBAC 权限系统
  • 动态路由如何实现
  • 路由守卫的实际使用
  • Pinia 状态管理
  • 自定义指令的应用
  • 企业项目的常见问题处理

这套代码我已经用在自己的Vue3 能源管理平台中,运行稳定,逻辑清晰,非常适合学生用来学习、做课程设计、写简历项目。

项目源码:https://github.com/HY-koi/Vue3-Energy-Management-Platform

如果你也在做后台管理系统,希望这篇笔记能帮到你~