基于vue3的后台管理权限划分

  一、获取token    1.根据登录获取token账号token,请求登录接口,后端返回token,前端保存本地和vuex

 二、请求角色菜单列表

     2.根据token获取账号所对应的角色和菜单列表,请求角色菜单接口,后端返回角色类型和菜单列表,前端保存vuex,这种方法一般都放在vuex的action里,store.dispatch('getUserInfo'),方便其他地方调用

三、路由处理

    3.前端根据后端返回的菜单数组进行循环,同时使用vue-router的addRouter方法,把每一项放入路由表里,再拼接上初始的路由(例如登录页的路由等) 菜单路由的处理思路 3.1 一般会定义两个路由,一个是初始的路由,用来存放登录页,404等,即不需要权限,每个用户都可以进入的页面; 3.2 一般会对后端返回的路由再做一层处理,例如加一些属性,例如菜单对象的每一项一般后端会返回一个type来让你区分,比如type为1时代表是菜单,type为2时代表是页面,type为3是代表是按钮,那么前端在处理是需要判断,例如

    const RouteView = {
        render() {
            return h(resolveComponent('router-view'))
        },
    }
    // webpack读取../views下所有vue文件的方法
    const modules = require.context('../views', true, /.vue$/);
    const permissionCodeList = []
    
    async function handleMenuList(menuList){
        recursionHandleRoute(menuList)
        return Promise.resolve({totalMenuList:menuList,permissionCodeList})
    }
    
    // 递归的处理路由信息
    function recursionHandleRoute(menu){
            // 先对菜单进行排序
            menu = menu.sort((a,b)=>a.sort-b.sort)
            menu.forEach(item=>{
             // 把所有的权限code都放进一个数组里,然后存到vuex里,方便写自定义指令的时候读取
              permissionCodeList.push(item.code)
              if([1,2].includes(item.type)){
                  item.routerInfo = {
                    children:item.children,
                    path:item.url,
                    name:item.name,
                    code:item.code,
                    key:item.key,
                    component:menu.type === 1 ?RouteView:modules[`../views${item.url}.vue`],
                    meta:{
                        name:item.name,
                        key:item.key,
                        title:item.name,
                        icon:item.icon,
                        patentId:item.parentId,
                        //...其他你想加的属性
                    },
                    // ...其他你想加的属性
                }
              }
                // 如果还有children属性,就递归的再处理一遍
                if(item.children?.length){
                    recursionHandleRoute(item.children)
                }
                
                if(item.routerInfo){
                    Object.assign(item,item.routerInfo)
                    // 这个对象只是做一层处理,用完可以删掉了
                    delete item.routerInfo
                }
            })
      }
    
    //3.3 处理完菜单后,把两个路由拼接起来,[...初始路由,...菜单路由]
        export const constantRoute = [
          {
            path: '/login',
            name: 'login',
            component: () => import('@/views/login.vue'),
          },
        ]       

        const asyncRouter = handleMenuList(menuList)
        // 总路由
        const totalRoute = [...constantRoute,...asyncRouter.totalMenuList]
        // 把最后经过处理的所有路由信息用vuex存起来
        store.commit('SET_MENULIST',totalRoute)
        // 把所有的权限code用vuex存起来
        store.commit('SET_PERMISSION',asyncRouter.permissionCodeList)
      
    // 3.4  处理完所有的路由后添加到路由表里
     totalRoute.forEach(item=>{
             router.addRoute(item)
        })
    
    按钮权限的处理思路
    
    上面路由处理完毕后我们可以在store中拿到所有的permissionCodeList,里面放的就是每个权限代表的code,
    这时我们可以写一个自定义指令。
    
    例如:菜单里只有用户管理,这个页面对应的code为2,他的children有4个按钮,分别为创建用户,删除用户,修改用户,查询用户,每个按钮对应的code为5,6,7,8,见图1-3
那么上面我们路由处理完之后,我们的总路由表应该是只有登录页和用户管理菜单能看到,所有的权限code数组里应该是[2,5,6,7,8],那么如果我想给这四个按钮增加按钮权限控制,应该判断他们对应的权限代码值在不在上面定义的数组里,如果不在就让他的display为none就隐藏掉了,自定义指令实现如下:

  <el-button  v-auth='5' v-xxx='xxx'> 创建用户 </el-button>

  app.directive('auth', {
    mounted(dom, binding) {
        // 如果从所有的权限数组里没找到当前绑定的权限值,那么说明你没有这个按钮权限
      if (!store.state.permissionCodeList.includes(binding.value)) {
        //这里的dom就是上面的el-button,binding.value就是指令绑定的值,自己可以打印一下
        // 这个值不能乱绑,要跟后端返回的对应起来,见图1-3
        dom.style.display = 'none'
      }
    },
  })

// 那既然上面存在vuex里,那么就意味着刷新页面后就没有权限了,那么如何处理?
//处理思路:在路由导航守卫处理,因为前面存储了token,所以可以在导航守卫重新根据token获取菜单权限
// 这里有个问题,为什么不把权限数组存到本地,每次从本地拿,因为如果你改了这个角色的菜单,存本地下次来拿还是之前存的,相当于没改,所以不能存本地,只能每次刷新后从新请求新的菜单

// 白名单页面:不需要token的页面
const whiltList = ['/login']
router.beforeEach(async (to,from,next)=>{
    const token = sessionStorage.getItem('token')
    if(token){
        // vuex里面的permissionCodeList数组为空了重置了,说明页面刷新了,这个时候回到第二部即可,重新根据token发起权限菜单请求
        if(!store.state.permissionCodeList.length){
            // 这种方法一般都放在vuex的action里,直接调用就好了
            await store.dispatch('getUserInfo')
            // 拿到新权限后继续跳转到对应的页面
           if (to.path === '/') {
            next({ path: '/home', replace: true })
          } else {
            next({ path: to.path, query: to.query, params: to.params, replace: true })
          }
        }
    }else{
      // 如果去白名单页面,就直接放行。否则跳转到登录
        if(whiltList.includes(to.path)){
            next()
        }else{
            next('/login')
        }
    }
})

四、vuex代码示例

import router from '@/router'
import { constantRouter } from '@/router/config'
const test = {
  state: {
    token: '',
    menuList: [],
    permissionCodeList: [],
  },
  mutations: {
    /**
     * @method 设置token
     */
    SET_TOKEN(state, token) {
      state.token = token
    },
    /**
     * @method 设置理由菜单
     */
    SET_MENULIST(state, menuList) {
      state.menuList = menuList
    },
    /**
     * @method 设置所有权限数组
     */
    SET_PERMISSION_LIST(state, permissionCodeList) {
      state.permissionCodeList = permissionCodeList
    },
  },
  actions: {
    /**
     * @method 登录
     */
    async login({ commit, dispatch }, params) {
      try {
        const { Success, Tag } = await userLogin(params)
        if (Success) {
          commit('SET_TOKEN', Tag.token)
          sessionStorage.setItem('token', Tag.token)
          await dispatch('getUserInfo')
          return Promise.resolve()
        }
      } catch (error) {
        console.log('error-登录', error)
        return Promise.reject(error)
      }
    },

    /**
     * @method 获取用户对应的菜单
     */
    async getUserInfo({ commit }) {
      try {
        const { Success, Tag } = await getUserMenu()
        if (Success) {
          const asyncRouter = handleMenuList(Tag.menuList)
          const totalRoute = [...constantRouter, ...asyncRouter.totalMenuList]
          totalRoute.forEach((item) => {
            router.addRouter(item)
          })
          commit('SET_MENULIST', totalRoute)
          commit('SET_PERMISSION_LIST', asyncRouter.permissionCodeList)
          return Promise.resolve()
        }
      } catch (error) {
        console.log('error-获取用户菜单', error)
        return Promise.reject(error)
      }
    },
    
    /**
     * @method 退出登录,清空本地存储
     */
    logout({commit}){
       commit('SET_TOKEN','')
       commit('SET_MENULIST', [])
       commit('SET_PERMISSION_LIST', [])
    }
       
  },
}

export default test


  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Novel是基于SpringBoot的前后端分离权限管理系统,易读易懂、界面简洁美观。 采用SpringBoot+Vue前后端分离模式开发,后端主要采用SpringBoot+mysql+mybatis+druid+shiro+redis,前端主要采用vue+TypeScript+Sass+element-ui+vuex+axios。 它可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。 Novel内置功能: 1、用户管理:用户是系统操作者,该功能主要完成系统用户配置。 2、部门管理:配置系统组织机构(公司、部门、小组),树结构展现。 3、岗位管理:配置系统用户所属担任职务。 4、菜单管理:配置系统菜单,操作权限,按钮权限标识等。 5、角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 6、操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 7、登录日志:系统登录日志记录查询包含登录异常。 8、服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 9、在线用户:当前系统中活跃用户状态监控。 10、连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 11、定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 12、代码生成:前后端代码的生成支持CRUD下载。 13、参数管理:对系统动态配置常用参数。
前端采用Vue、Element UI。 后端采用Spring Boot、Spring Security、Redis & Jwt。 权限认证使用Jwt,支持多终端认证系统。 支持加载动态权限菜单,多方式轻松权限控制。 高效率开发,使用代码生成器可以一键生成前后端代码。 提供了单应用版本RuoYi-Vue-fast,Oracle版本RuoYi-Vue-Oracle,保持同步更新。 内置功能 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 岗位管理:配置系统用户所属担任职务。 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 参数管理:对系统动态配置常用参数。 通知公告:系统通知公告信息发布维护。 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 登录日志:系统登录日志记录查询包含登录异常。 在线用户:当前系统中活跃用户状态监控。 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 系统接口:根据业务代码自动生成相关的api接口文档。 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 缓存监控:对系统的缓存信息查询,命令统计等。 在线构建器:拖动表单元素生成相应的HTML代码。 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
Vue3后台管理系统权限可以通过动态路由的方式进行管理。首先,将路由进行分类,分为动态路由和静态路由。需要权限管理的菜单路由分配给动态路由,而不需要权限管理的菜单分配给静态路由。动态路由的配置思想是,根据用户登录接口返回的数据中包含的权限路由,将这些路由保存到Vuex的menu数组中,再通过menu数组生成动态路由。具体的步骤如下: 1. 安装js-cookie插件,用来保存menu数据。 2. 在Vuex的tab.js文件中的mutations对象中新建setMenu方法,该方法实现将接口返回的路由数据赋值给menu数组,并将接口返回的数据存放到Cookie中。 3. 登录后,根据用户权限生成对应的菜单路由。 4. 退出登录时,清除menu和cookie数据。 此外,在Login组件中,可以调用store来保存menu数据。在tab.js文件中,新增addMenu方法,将menu中的数据按照路由映射表的格式拼接路由,并传给router。 通过以上步骤,可以实现Vue3后台管理系统权限管理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [P21-Vue3后台管理系统-权限管理-权限管理实现](https://blog.csdn.net/m0_38039437/article/details/113931567)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值