vue-admin-element 精确到按钮的权限管理

vue-admin-element 权限管理

  • 菜单栏权限问题

    • router/index.js 中 添加需要的动态路由,其它不变

      export const asyncRoutes = [{
          path: '/form',
          name: 'Form',
          component: Layout,
          meta: {
            title: 'Form',
            icon: 'lock',
            roles: ['admin', 'editor'] // 角色信息
          },
          children: [{
            path: 'index',
            component: () => import('@/views/form/index'),
            name: 'Form',
            meta: {
              title: 'Form',
              icon: 'icon',
              roles: ['admin', 'editor'] // 角色信息
            }
          }]
        }
      ]
      
    • src/permission.js 中根据角色获取异步的路由信息

      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' // get token from cookie
      import getPageTitle from '@/utils/get-page-title'
      
      //----- 添加的内容 开始 -------------
      import { constantRoutes } from '@/router'
      //----- 添加的内容 结束 -------------
      
      
      NProgress.configure({ showSpinner: false }) // NProgress Configuration
      
      const whiteList = ['/login'] // no redirect whitelist
      
      router.beforeEach(async(to, from, next) => {
        // start progress bar
        NProgress.start()
      
        // set page title
        document.title = getPageTitle(to.meta.title)
      
        // determine whether the user has logged in
        const hasToken = getToken()
      
        if (hasToken) {
          if (to.path === '/login') {
            // if is logged in, redirect to the home page
            next({ path: '/' })
            NProgress.done()
          } else {
            const hasGetUserInfo = store.getters.name
            if (hasGetUserInfo) {
              next()
            } else {
              try {
                // 获取用户角色 
                // ----------添加内容开始 ------------------
                const {rules} =  await store.dispatch('user/getInfo')
                const accessRoutes = await store.dispatch('user/generateRoutes', rules)
                const routes = constantRoutes.concat(accessRoutes)
                router.options.routes = routes // 拼接數組
                router.addRoutes(routes)
                next({ ...to, replace: true })
                // ----------添加内容结束 ------------------
              } catch (error) {
                // remove token and go to login page to re-login
                await store.dispatch('user/resetToken')
                Message.error(error || 'Has Error')
                next(`/login?redirect=${to.path}`)
                NProgress.done()
              }
            }
          }
        } else {
          /* has no token*/
      
          if (whiteList.indexOf(to.path) !== -1) {
            // in the free login whitelist, go directly
            next()
          } else {
            // other pages that do not have permission to access are redirected to the login page.
            next(`/login?redirect=${to.path}`)
            NProgress.done()
          }
        }
      })
      
      router.afterEach(() => {
        // finish progress bar
        NProgress.done()
      })
      
    • src/store/modules/user.js 文件中添加 generateRoutes 方法

      import {
        login,
        logout,
        getInfo
      } from '@/api/user'
      import {
        getToken,
        setToken,
        removeToken
      } from '@/utils/auth'
      // -------添加 导入路由 信息 开始 ---------
      import {
        resetRouter,
        asyncRoutes,
        constantRoutes
      } from '@/router'
      
      // -------添加 导入路由 信息 结束 ---------
      
      const getDefaultState = () => {
        return {
          token: getToken(),
          name: '',
          avatar: '',
          rules: [],
          routes: [], // 该角色拥有的权限信息
          addRoutes: [] // 该角色新增的权限信息
        }
      }
      
      const state = getDefaultState()
      
      const mutations = {
        RESET_STATE: (state) => {
          Object.assign(state, getDefaultState())
        },
        SET_TOKEN: (state, token) => {
          state.token = token
        },
        SET_NAME: (state, name) => {
          state.name = name
        },
        SET_AVATAR: (state, avatar) => {
          state.avatar = avatar
        },
        // -----------添加 mutations 开始 -------------------
        SET_RULES: (state, rules) => {
          state.rules = rules
        },
        SET_ROUTES: (state, routes) => {
          state.addRoutes = routes
          state.routes = constantRoutes.concat(routes)
        }
        // -----------添加 mutations 结束 -------------------
      
      }
      
      // ------------------添加 是否有权限 方法开始------------------------------
      function hasPermission(rules, route) {
        if (route.meta && route.meta.roles) {
          return roles.some(rules => route.meta.roles.includes(rules))
        } else {
          return true
        }
      }
      // ------------------添加 是否有权限 方法结束------------------------------
      
      
      // ------------------添加 根据角色过滤动态路由 方法开始------------------------------
      export function filterAsyncRoutes(routes, rules) {
        const res = []
        routes.forEach(route => {
          const tmp = {
            ...route
          }
          if (hasPermission(rules, tmp)) {
            if (tmp.children) {
              tmp.children = filterAsyncRoutes(tmp.children, rules)
            }
            res.push(tmp)
          }
        })
        return res
      }
      // ------------------添加 根据角色过滤动态路由 方法结束------------------------------
      
      const actions = {
        // user login
        login({
          commit
        }, userInfo) {
          const {
            username,
            password
          } = userInfo
          return new Promise((resolve, reject) => {
            login({
              username: username.trim(),
              password: password
            }).then(response => {
              const {
                data
              } = response
              commit('SET_TOKEN', data.token)
              setToken(data.token)
              resolve()
            }).catch(error => {
              reject(error)
            })
          })
        },
      
        // get user info
        getInfo({
          commit,
          state
        }) {
          return new Promise((resolve, reject) => {
            getInfo().then(response => {
              const {
                data
              } = response
      
              if (!data) {
                return reject('Verification failed, please Login again.')
              }
      
              const {
                name,
                avatar,
                rules
              } = data
      
              commit('SET_NAME', name)
              commit('SET_RULES', rules)
              commit('SET_AVATAR', avatar)
              resolve(data)
            }).catch(error => {
              reject(error)
            })
          })
        },
      
        // user logout
        logout({
          commit,
          state
        }) {
          return new Promise((resolve, reject) => {
            logout(state.token).then(() => {
              removeToken() // must remove  token  first
              resetRouter()
              commit('RESET_STATE')
              resolve()
            }).catch(error => {
              reject(error)
            })
          })
        },
      
        // remove token
        resetToken({
          commit
        }) {
          return new Promise(resolve => {
            removeToken() // must remove  token  first
            commit('RESET_STATE')
            resolve()
          })
        },
        // ------------------添加 生成动态路由 方法开始------------------------------
        generateRoutes({
          commit
        }, rules) {
          return new Promise(resolve => {
            let accessedRoutes = filterAsyncRoutes(asyncRoutes, rules)
            commit('SET_ROUTES', accessedRoutes)
            resolve(accessedRoutes)
          })
        }
        // ------------------添加 生成动态路由 方法结束------------------------------
      }
      
      export default {
        namespaced: true,
        state,
        mutations,
        actions
      }
      
    • src/store/getters.js

      const getters = {
        sidebar: state => state.app.sidebar,
        device: state => state.app.device,
        token: state => state.user.token,
        avatar: state => state.user.avatar,
        name: state => state.user.name,
        addRoutes: state => state.user.addRoutes,
        routes: state => state.user.routes,
        rules: state => state.user.rules
      }
      export default getters
      
  • 精确到按钮级别

    • src/store/modules 创建 js文件 btnPermission.js

      import Vue from 'vue'
      
      import store from '../index'
      
      /**权限指令**/
      Vue.directive('has', {
        bind: function (el, binding) {
          console.log(binding);
          let Permissions = binding.value; // v-has 绑定的属性,也就是按钮权限值
          console.log('permission', Permissions)
          if (!Vue.prototype.$_has(Permissions)) {
            let className = el.getAttribute("class")
            className = className ? className.concat(" wuxiaoshi-btn-hidden") : "wuxiaoshi-btn-hidden";
            el.setAttribute("class", className)
          }
        }
      });
      //权限检查方法
      Vue.prototype.$_has = function (value) {
        let isExist = false;
        let buttonpermsStr = store.getters.roles;
        if (buttonpermsStr == undefined || buttonpermsStr == null) {
          return false;
        }
        for (let i = 0; i < buttonpermsStr.length; i++) {
          if (value == buttonpermsStr[i]) {
            isExist = true;
            break;
          }
        }
        return isExist;
      };
      
      
    • src/store/modeles/user.js 中 将权限规则添加到 vuex

      const mutations = {
        RESET_STATE: (state) => {
          Object.assign(state, getDefaultState())
        },
        SET_TOKEN: (state, token) => {
          state.token = token
        },
        SET_NAME: (state, name) => {
          state.name = name
        },
        SET_AVATAR: (state, avatar) => {
          state.avatar = avatar
        },
        SET_RULES:(state,rules)=>{
        state.rules = rules;
        }
      }
      
    • src/store/modeles/user.js 文件中 定义按钮级别权限

      // 请求后端接口,需要将rules作为一个键将所有的权限信息添加到vuex中  
      getInfo({ commit, state }) {
          return new Promise((resolve, reject) => {
            getInfo(state.token).then(response => {
              const { data } = response
      
              if (!data) {
                return reject('Verification failed, please Login again.')
              }
              const { name, avatar,rules } = data // 将权限导出来
              commit('SET_NAME', name)
              commit('SET_AVATAR', avatar)
              commit('SET_RULES', rules) // 添加权限
              resolve(data)
          }).catch(error => {
              reject(error)
          })
          })
        },
      
    • src/store/getters.js 文件中 定义按钮级别权限

      const getters = {
        sidebar: state => state.app.sidebar,
        device: state => state.app.device,
        token: state => state.user.token,
        avatar: state => state.user.avatar,
        name: state => state.user.name,
        rules: state => state.user.rules //获取vuex中的权限信息
      }
      export default getters
      
    • main.js 导入

      import has from '@/store/modules/btnPermission.js'
      
    • App.vue 中 添加样式

      <style>
      .wuxiaoshi-btn-hidden {
        display: none;
      }
      </style>
      
posted @ 2020-08-29 14:40  巫小诗  阅读(1711)  评论(0编辑  收藏  举报