Vue实战:基于Vue-ElementUI的权限管理系统之动态路由和动态按钮显示

2022年8月8日09:16:38

1.首先登录

2.调用permission.js 的router.beforeEach((to, from, next)

to:进入到哪个路由去
from:从哪个路由离开
next:路由的控制参数,常用的有next(true)和next(false)
首先判断进入的是否是login页面?然后再判断是否已经登陆?
已经登陆了就进入你要跳转的页面,没登录就进入login页面

为了更加明显一点,我将页面命名的简单一些,ps:

Login.vue是登陆页面
Index.vue是全局页面(包含公共导航组件)
A.vue是普通页面(此处我做为首页)
B.vue是普通页面

permission.js
router.beforeEach(async(to, from, next) => {
  NProgress.start()
  document.title = getPageTitle(to.meta.title)
  const hasToken = getToken()
  // 判断是否存在token,没有就重新登陆
  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      // 这里指的是src/store/getters.js的roles
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          // 获取roles
          // get user info 获取当前登录用户的Button按钮列表,和当前用户角色名
          store.dispatch('user/getInfo') 
          // generate accessible routes map based on roles 获取后端角色列表 
          const DbRoutes = await store.dispatch('permission/getSideMenus')
          router.addRoutes(DbRoutes)
          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()
        }
      }
    }
  }
})

2.store.getter

const getters = {
  token: state => state.user.token,
  name: state => state.user.name,
  roles: state => state.user.roles,//角色名列表
  permission_routes: state => state.permission.routes,//页面路由
  permissions: state => state.user.permissions //菜单按钮列表
}
export default getters

3.store.dispatch('user/getInfo')调用 Store文件夹下user.js的 getInfo方法 获取当前登录用户的Button按钮列表,和当前用户角色名

import { login, logout, getInfo, getRoleList } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import router, { resetRouter } from '@/router'

const state = {
  token: getToken(),
  roles: []
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  //存储登录角色信息
  SET_ROLES: (state, roles) => {
    state.roles = roles
  },
 //存储按钮信息
  SET_PERMISSIONS: (state, permissions) => {
    state.permissions = permissions
  }
}

const actions = {
    // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response
        if (!data) {
          reject('Verification failed, please Login again.')
        }
        const { roles, permissions } = data
        console.error('roles' + roles)
        console.error('permissions' + permissions)
        // roles must be a non-empty array
        if (!roles || roles.length <= 0) {
          reject('getInfo: roles must be a non-null array!')
        }
        if (!permissions || permissions.length <= 0) {
          reject('getInfo: permissions must be a non-null array!')
        }

        commit('SET_ROLES', roles)
        commit('SET_PERMISSIONS', permissions)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  }
}

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

4. store.dispatch('permission/getSideMenus')调用 Store文件夹下psermission.js的 getSideMenus方法

const actions = {
  getSideMenus({ commit, state }) {
    return new Promise((resolve, reject) => {
       //import { listForRouter } from '@/api/user'
      listForRouter().then(response => {
        const menus = response.data
        //import { traverseRoutes } from '@/utils/router'
        const remoteroutes = traverseRoutes(menus)
        commit('SET_ROUTES', remoteroutes)
        resolve(remoteroutes)
      }).catch(error => {
        console.log('list', error)
        router.replace({
          path: '/login',
          query: { redirect: router.currentRoute.path }
        })
        // reject(error)
      })
    })
  }
}

import { traverseRoutes } from '@/utils/router'

export function traverseRoutes(menus) {
  const routes = menus.map(menu => {
    if (menu.children === null) {
      menu.children = []
    }
    if (menu.component) {
      const name = menu.component
      menu.component = (resolve) => require(['@/' + name], resolve)
      // menu.component = resolve => require(['@/views/UserManagement/user'], resolve)
    }

    if (menu.children && menu.children.length) {
      menu.children = traverseRoutes(menu.children)
    }
    return menu
  })
  return routes
}
api文件夹下user.js import { userInfo} from '@/api/user'
export function getInfo(token) {
  return request({
    url: '/admin/info',
    method: 'get',
    params: { token }
  })
}

api文件夹下role.js import { listForRouter } from '@/api/role'

export function listForRouter() {
  return request({
    url: '/admin/getLoginSideBarMenus',
    method: 'get'
  })
}

后端admin/Info 返回给前端信息

{
"code":200,
"msg":"成功",
"data":
{"permissions":["userAdd","userDeleted","userUpdated","userReset","userSetRole","roleAdd","userDeleted",
"roleUpdated","authAdd","authDeleted","authUpdated"],
"roles":["超级管理员"]
}
}

后端admin/getLoginSideBarMenus返回给前端信息

{"code":200,"msg":"成功",
"data":[{"id":1,"parentId":0,"path":"/system","component":"layout","name":"系统管理","num":1,"hidden":false,"url":"/system","meta":{"title":"系统管理","icon":"form"},"children":[{"id":2,"parentId":1,"path":"/user","component":"views/UserManagement/user.vue","name":"用户管理","num":1,"hidden":false,"url":"/user","meta":{"title":"用户管理","icon":"user"},"children":null},{"id":8,"parentId":1,"path":"/role","component":"views/UserManagement/role.vue","name":"角色管理","num":1,"hidden":false,"url":"/role","meta":{"title":"角色管理","icon":"international"},"children":null},{"id":14,"parentId":1,"path":"/auth","component":"views/UserManagement/auth.vue","name":"资源管理","num":1,"hidden":false,"url":"/auth","meta":{"title":"资源管理","icon":"list"},"children":null},{"id":18,"parentId":1,"path":"/test","component":"views/test/index.vue","name":"测试菜单","num":1,"hidden":false,"url":"/test","meta":{"title":"测试菜单","icon":"lock"},"children":[{"id":19,"parentId":18,"path":"/children1","component":"views/test/children/children1.vue","name":"测试菜单1","num":2,"hidden":false,"url":"/children1","meta":{"title":"测试菜单1","icon":"icon"},"children":null}]}]}]}

动态按钮显示

main.js

// main.js
import { checkArray } from './utils/btnPermission.js'
Vue.directive('permission', {
  inserted(el, binding) {
    const permission = binding.value // 获取到 v-permission的值
    if (permission) {
      const hasPermission = checkArray(permission) // 检测是否有权限
      if (!hasPermission) { // 没有权限 移除Dom元素
        el.parentNode && el.parentNode.removeChild(el)
      }
    }
  }
})

./utils/btnPermission.js

import store from '@/store'
export function checkArray(key) {
  // store.dispatch('user/getInfo') 
  const arr = store.getters.permissions //store文件下getter.
  const index = arr.indexOf(key)
  if (index > -1) {
    return true // 有权限
  } else {
    return false // 无权限
  }
}

界面使用方法 auth.js

界面使用方法 auth.js
 <el-table-column fixed="right" label="操作" width="300px">
          <template slot-scope="scope">
            <el-button
              v-permission="'authAdd'"
              icon="el-icon-plus"
              type="success"
              size="small"
              @click="add(scope.row.code,scope.row.pcodes)"
            >
              新增子级
            </el-button>
            <el-button
              v-permission="'authUpdated'"
              type="primary"
              icon="el-icon-edit"
              size="small"
              @click="handleEdit(scope.row.id, scope.row)"
            >编辑</el-button>
            <el-button
              v-permission="'authDeleted'"
              type="danger"
              icon="el-icon-delete"
              size="small"
              @click.native.prevent="deleted(scope.row.id)"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
  • 作者:王小柯_0314
  • 原文链接:https://blog.csdn.net/wwwkm123/article/details/120821644
    更新时间:2022年8月8日09:16:38 ,共 6220 字。