zoukankan      html  css  js  c++  java
  • vue后台管理系统权限处理

    vue后台管理系统权限

     

    1.权限问题用户和管理员进入管理系统看到的模块是不一样的,管理员看的的要比用户看到的多。需要用到动态加载路由,router.addRouters()来动态的挂载路由

    // 1.先登录将获取到的用户的token存储起来
    
    // store/index.js
    
    // 封装的api接口方法
    import { getLogin, getUserInfo } from '../api/index'
    
    
    state: {
        roles: [],
        token: window.localStorage.getItem('token') || ''
    },
    
    
    mutations: {
    
        // 将获取到的token存储到本地
        SET_TOKEN (state, token) {
          state.token = token
          window.localStorage.setItem('token', state.token)
        }
    },
    
    
    actions: {
    
       userLogin ({ commit }, userInfo) {
    
          // 返回一个异步回调,promise
          return new Promise((resolve, reject) => {
    
            // 调用封装好的请求数据的方法
            getLogin(userInfo).then(res => {
              const data = res.data
              if (data.code === 200) {
        
                // 调用mutations中的方法,将token存储到本地中
                commit('SET_TOKEN', data.token)
              }
              resolve(res.data)
            }).catch(error => {
              reject(error)
            })
          })
        },
    
        
        // 根据用户的token获取用户的个人信息,里面包含了权限信息
    
        getUserInfo ({ state }) {
    
            // 返回一个异步回调,promise
          return new Promise((resolve, reject) => {
    
            // 调用接口方法获取数据
            getUserInfo(state).then(res => {
        
                // 将获取到的信息放到数组中存储
              state.roles.push(res.data)
              resolve(res.data)
            }).catch(error => {
              reject(error)
            })
          })
        }
    }
    
    
    // 在login/index.vue中使用,点击按钮触发
    userLogin () {
    
          this.$store.dispatch('userLogin', this.userInfo).then(res => {
            // 登陆成功跳转主页
            this.$router.push('/home')
          }).catch(error => {
            console.log(error)
          })
    }
    
    
    // vuex的计算属性
    
    getters: {
        // 将用户数据放到计算属性中,一旦数据发生变化,可以重新计算
        roles (state) {
          return state.roles
        },
        token (state) {
          return state.token
        }
    },
    
    
    
    // 权限模块的处理
    
    
    
    // router/index.js
    
    // 路由中的配置
    
    // 静态路由,没有权限的所有用户都可以看到
    
    // 引入登陆页面
    import Login from '../views/Login'
    
    export const staticRoutes = [
      {
        path: '/login',
        name: 'login',
        component: Login
      },
      {
        path: '/home',
        name: 'home',
        component: () => import('../views/Home')
      }
    ]
    
    
    // 异步(动态)挂载的路由,根据权限展示
    export const asyncRouteMap = [
      {
        path: '/details',
        name: 'details',
        component: () => import('../views/Details'),
        meta: {
          role: ['admin', 'super_editor'] // 页面需要的权限
        },
        children: [
          {
            path: 'index',
            name: 'index',
            component: () => import('../views/Details/Child'),
            meta: {
              role: ['admin', 'super_editor'] // 页面需要的权限
            },
            children: [
              {
                path: '/next',
                name: 'next',
                meta: {
                  role: ['admin', 'super_editor'] // 页面需要的权限
                }
              }
            ]
          }
        ]
      },
      {
        path: '/error',
        component: () => import('../views/404'),
        name: 404
      },
      { path: '*', redirect: '/error', hidden: true }
    ]
    
    // 因为可以动态的挂载路由,但是不能动态删除路由。所以才考略到,
    // 在需要动态清空动态挂载路由的话,直接将一个新的路由对象赋值给旧的路由对象,这样就可以达到动态清除的工作
    
    const createRouter = () => new VueRouter({
      scrollBehavior: () => ({ y: 0 }),
      routes: staticRoutes
    })
    
    
    const router = createRouter()
    
    // 调用该方法动态清除动态挂载路由
    export function resetRouter () {
      const newRouter = createRouter()
      router.matcher = newRouter.matcher // reset router
    }
    
    export default router
    
    
    
    // store/permission.js
    
    // 引入权限路由,和公共路由
    import { staticRoutes, asyncRouteMap } from '../router/index' 
    
    // 用来筛选后端返回来的权限数据,和权限路由中的meta里面的数据匹配,匹配成功返回true,失败为false
    
    function hasPerMission (roles, route) {
      if (route && route.meta.role) {
        return roles.some(role => route.meta.role.indexOf(role) >= 0)
      } else {
        return true
      }
    }
    
    
    const permission = {
      state: {
        routers: staticRoutes,
        addRouters: []
      },
      mutations: {
    
        // 将匹配成功的权限路由拼接到公共路由中
        SET_ROUTERS (state, routers) {
          state.addRouters = routers
          state.routers = staticRoutes.concat(routers)
        }
      },
      actions: {
    
        // 对后台返回来的权限和动态路由权限匹配
        GenerateRoutes ({ commit }, data) {
    
            // 返回一个异步回调promise
          return new Promise((resolve, reject) => {
    
            // 遍历权限路由数组
            const accessedRoutes = asyncRouteMap.filter(v => {
    
                // 判断如果后台返回的权限中包含admin就是管理员,可以进入权限路由页面
              if (data.indexOf('admin') >= 0) return true
    
               // 之后就是调用hasPerMission函数对象权限动态路由和后台返回的用户权限进行严格匹配
              if (hasPerMission(data, v)) {
                
                // 判断是否有权限路由是否有子路由,有子路由继续遍历
                if (v.children && v.children.length > 0) {
                  v.children = v.children.filter(child => {
    
                    // 对权限子路由和后台返回的用户权限数据,在进行匹配,匹配成功返回
                    if (hasPerMission(data, child)) {
                      return child
                    }
                    
                    // 失败返回false
                    return false
                  })
    
                    // 并且要把权限的父路由返回来,不光要把权限子路由返回,无论权限子路有还是没有,都应该把权限父路由返回来
                  return v
                } else {
        
                    // 权限父路由匹配成功返回
                  return v
                }
              }
        
               // 如果每一个判断都没有进,说明该用户没有任何权限,返回false
              return false
            })
            commit('SET_ROUTERS', accessedRoutes)
            resolve()
          })
        }
      },
      getters: {
    
        // 只要权限路由数组发生变化就重新计算
        addRouters (state) {
          return state.addRouters
        }
      }
    }
    export default permission
    
    
    // 在store/index.js
    
    // 引入另一个模块使用
    import permission from './permission'
    
    modules: {
    
        // 我们还需要用到另一个模块配合完成
        permission
    }
    
    
    
    
    // 之后创建一个js文件单独放到全局路由导航,之后在main.js中引入执行
    
    // gloab/index.js
    
    // 先把路由和vuex引进来使用
    import router from '../router'
    import store from '../store'
    
    const whiteList = ['/login'] // 不重定向白名单
    
    router.beforeEach((to, from, next) => {
      if (store.getters.token) {
        // 判断如果是去登陆页面的话,返回主页,不让他返回登录页
        if (to.path === '/login') {
          next({ path: '/home' })
        } else {
          // 否则判断一下用户的个人信息是否已经拉取完毕
          if (store.getters.roles.length === 0) {
            // 拉取用户个人信息
            store.dispatch('getUserInfo').then(res => {
              // 拿到用户后台返回的权限数据
              const roles = res.role
              // 调用 permission.js方法中的GenerateRoutes方法,将后台返回的用户的权限数据,传递回去进行筛选处理
              store.dispatch('GenerateRoutes', roles).then(() => { // 生成可访问的路由表
                // 将筛选的权限路由数组动态挂载
                router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
                next({ ...to, replace: true }) // hack方法 确保addRoutes添加完成
              })
            }).catch(error => {
              console.log(error)
              // 验证失败重新登陆
              next({ path: '/login' })
            })
          } else {
            next() // 当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的页面会自动进入404页面
          }
        }
      } else {
        // 如果已经去了登陆页面了,就不需要再next到登陆页面了,这就是重定向白名单
        if (whiteList.indexOf(to.path) !== -1) {
          next()
        } else {
          next('/login') // 否则全部重定向到登录页
        }
      }
    })
  • 相关阅读:
    CocoaPods安装使用及配置私有库及注意点
    CocoaPods 错误 target overrides the `OTHER_LDFLAGS`...
    如何判断ios设备中是否安装了某款应用
    symbol(s) not found for architecture arm64
    所有iOS设备的屏幕分辨率
    iOS禁止多点操作(按钮和Table项)
    计算日期时间间隔:
    "library not found for
    Undefined symbols for architecture i386:和"_OBJC_CLASS_$_xx", referenced from:问题解决方法
    oracle游标(转载)
  • 原文地址:https://www.cnblogs.com/zxuedong/p/12561963.html
Copyright © 2011-2022 走看看