Vue项目 针对角色配置权限之菜单权限

11 篇文章 0 订阅
3 篇文章 0 订阅


前言

通过自定义指令控制按钮权限,菜单权限需要综合权限数据和本地路由信息进行过滤

提示:以下是本篇文章正文内容,下面案例可供参考

一、菜单权限

获取权限数据,与本地路由对比筛选,将数据保存在vuex

1. 在store目录下建立permission.js

在这里插入图片描述

  • 后台返回数据格式:
  • path代表菜单路由path,与前端路由文件对应,作为唯一标识
  • parentId代表父级ID,0 代表一级菜单
  • type代表菜单级别,0 代表一级菜单,1 代表二级菜单,2 代表按钮
[{
	"id": 1000,
	"name": "生产订单",
	"path": "/order-model",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 0,
	"type": 0,
}, {
	"id": 1010,
	"name": "销售订单",
	"path": "/order-model/salesOrder",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1000,
	"type": 1
}, {
	"id": 1011,
	"name": "新增",
	"path": "sales.order:add",
	"description": null,
	"status": "enable",
	"method": "POST",
	"parentId": 1010,
	"type": 2
}, {
	"id": 1012,
	"name": "编辑",
	"path": "sales.order:update",
	"description": null,
	"status": "enable",
	"method": "PUT",
	"parentId": 1010,
	"type": 2
}, {
	"id": 1013,
	"name": "详情",
	"path": "sales.order:select",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1010,
	"type": 2
}, {
	"id": 1014,
	"name": "删除",
	"path": "sales.order:delete",
	"description": null,
	"status": "enable",
	"method": "DELETE",
	"parentId": 1010,
	"type": 2
}, {
	"id": 1018,
	"name": "审核",
	"path": "sales.order:review",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1010,
	"type": 2
}, {
	"id": 1019,
	"name": "批准",
	"path": "sales.order:approval",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1010,
	"type": 2
}, {
	"id": 1050,
	"name": "辅助计划",
	"path": "/order-model/auxiliary_plan",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1000,
	"type": 1
}, {
	"id": 1051,
	"name": "导入",
	"path": "auxiliary.plan:import",
	"description": null,
	"status": "enable",
	"method": "POST",
	"parentId": 1050,
	"type": 2
}, {
	"id": 1052,
	"name": "导出",
	"path": "auxiliary.plan:export",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1050,
	"type": 2
},{
	"id": 1056,
	"name": "编辑",
	"path": "auxiliary.plan:update",
	"description": null,
	"status": "enable",
	"method": "GET",
	"parentId": 1050,
	"type": 2
}]
  • permission.js
import { asyncRoutes, constantRoutes } from '@/router'
import { getUserAuth } from '@/api/user'
/**
 * @param {Array} list 后端权限数据
 * @param {*} route 本地路由
 */
function hasPermission2(list, route) {
  if (route.path) {
    return list.some(el => route.path === el.path || route.hidden)
  } else {
    return true
  }
}
/**
 * 设置路由重定向
 * @param {*} routes
 * @returns
 */
export function loadRedirect(routes) {
  const res = []
  routes.forEach(el => {
    if (!el.redirect) {
      if (el.children) {
        el.children = loadRedirect(el.children)
        if (el.children.length !== 0) {
          el.redirect = el.children[0].path
        }
      }
    }
    res.push(el)
  })

  return res
}

/**
 * 根据权限列表匹配路由列表
 * @param {*} routes
 * @param {*} list
 * @returns
 */
export function filterAsyncRoutes2(routes, list) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission2(list, tmp)) {
      if (tmp.children) {
        if (tmp.children.filter(el => !el.hidden).length !== 1) {
          tmp.children = filterAsyncRoutes2(tmp.children, list)
        }
      }
      res.push(tmp)
    }
  })
  return res
}
const state = {
  // 前台路由信息
  routes: [],
  // 按钮信息
  authList: [],
  // 前台路由
  frontRoutes: []
}

const mutations = {
  SET_AUTHLIST: (state, authList) => {
    state.authList = authList
  },
  FRONT_ROUTES: (state, routes) => {
    state.frontRoutes = routes
    state.routes = routes
  }
}

const actions = {
  generateRoutes({ commit }, homeScreen = []) {
    return new Promise((resolve, reject) => {
      getUserAuth()
        .then(result => {
          const list = result.data.data
          const authList = list.filter(el => el.path.indexOf('/') === -1)
          // 后端返回数据 myRouter代表前台信息,myBackRouter代表后台信息
          const myRouter = list.filter(
            el => el.path.indexOf('/') !== -1
          )
          const accessedRoutes = loadRedirect(
            filterAsyncRoutes2(asyncRoutes, myRouter)
          )
          commit('FRONT_ROUTES', accessedRoutes)
          commit('SET_AUTHLIST', authList)
          resolve(accessedRoutes)
        })
        .catch(err => {
          reject(err)
        })
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

  • getters.js
const getters = {
  token: state => state.user.token,
  userInfo: state => state.user.userInfo,
  roles: state => state.user.roles,
  permission_routes: state => state.permission.routes,
  front_routes: state => state.permission.frontRoutes,
  authList: state => state.permission.authList
}
export default getters
  • index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'

Vue.use(Vuex)

const modulesFiles = require.context('./modules', true, /\.js$/)

const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

const store = new Vuex.Store({
  modules,
  getters
})

export default store

2.在main.js文件同级新建permission.js权限控制文件

  • router的导航守卫beforeEach中判断是否有token,是否有权限列表
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' 
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist

router.beforeEach(async (to, from, next) => {
  NProgress.start()
  document.title = getPageTitle(to.meta.title)
  const hasToken = getToken()
  if (hasToken) {
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done() 
    } else {
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        if (to.path === '/') {
          const frontRoutes = store.getters.front_routes
          const toPath =
            frontRoutes.find(route => {
              return (
                route.path !== '/process/production/line' &&
                route.path !== '/device/module/screen' &&
                route.path !== '/current/process/oad/line/index' &&
                route.path !== '/setting/screen/line'
              )
            })?.path || '/profile'
          next(toPath)
        } else {
          next()
        }
      } else {
        try {
        //获取用户信息
          await store.dispatch('user/getInfo')
          //获取权限列表
          const accessRoutes = await store.dispatch('permission/generateRoutes')
          router.addRoutes(accessRoutes)
          next({ ...to, replace: true })
        } catch (error) {
        //清除token
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done()
})

3.在main.js文件中引用permission.js

import './permission' 

二、按钮权限

参考:https://blog.csdn.net/Julia_0502/article/details/121822566

总结

提示:
本文章只是记录权限控制菜单的方法,避免忘记,若有不足,欢迎指教

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值