vue 路由权限管理小记

权限部分详解

本文章不讲具体实现方式,只说实现思路,如需具体实现形式可查阅别的文章

  1. 权限管理⼀般需求是⻚⾯权限和按钮权限的管理
  2. 具体实现的时候分后端和前端两种⽅案

目前权限区分可分为前端和后端来处理:

后端处理:把所有⻚⾯路由信息存在数据库中,⽤户登录的时候根据其⻆⾊查询得到其能访问的所有⻚⾯路由信息返回给前端,前端再通过 addRoutes 动态添加路由信息。

前端处理:

统一将固定路由放在constantRoutes,固定通过如下处理

const createRouter = () =>
  new Router({
    // mode: 'history', // require service support
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRoutes
  })

const router = createRouter()

登录后,通过后台数据比对 asyncRoutes 获取前端应该展示的路由数据 accessRoutes

最后通过如下代码,增加到路由中。

router.addRoutes(accessRoutes)

其中有三种处理方案:

  1. ① 后台返回的角色信息,如[‘admin’,‘editor’]。

    ② 路由meta中如配置

      {
        path: 'rights',
        name: 'rights',
        component: () => import('@/views/rights/index.vue'),
        meta: {
          title: 'Page Reports',
          roles: ['admin'] // or you can only set roles in sub nav
        }
      },

​ ③ 根据后台返回的角色信息,进行路由信息比对,获得最终应动态addRoutes的路由accessRoutes。

  1. ① 后台返回当前登录人携带的所有auth信息

    ② 路由meta中如配置

export default {
  meta: {
    // auth: '智慧航显',
    auth: '宣传通知',
    icon: 'el-icon-setting',
    type: 'menu',
    iconType: 'class',
    sort: 3
  },
  path: '/broadcastNotice',
  // 外层不需要其他处理,只是区分父子关系,采用这种写法。
  component: { render: e => e('router-view') },
  children: [
    {
      path: '/broadcastNotice/broadcastNotice',
      name: 'BroadcastNotice',
      component: () =>
        import(
          /* webpackChunkName: "UserRoleManagement" */ '@/views/BroadcastNotice/NoticeList/NoticeList.vue'
        ),
      meta: {
        breadcrumb: '通知列表',
        // menuIndex: '/flightDisplay/StaticModel',
        auth: '通知列表'
      }
    }
  ]
};

③ 根据后台返回的auth信息,进行路由meta中name信息比对,获得最终应动态addRoutes的路由accessRoutes。

[
    {
        "id": "02a3b989-0b7a-4011-b4d2-1a842f6a83cf",
        "name": "查询服务管理",
        "description": null,
        "type": "menu,page",
        "parentId": null,
        "enabled": true,
        "apiInfos": [],
        "children": []
    },
    {
        "id": "06c02de0-f111-4a39-a83b-23644993758d",
        "name": "综合演练",
        "description": null,
        "type": "menu,page",
        "parentId": null,
        "enabled": true,
        "apiInfos": [],
        "children": []
    },
]
  1. ① 后台直接返回路由信息

    ② 直接通过addRoutes添加路由信息即可。

整体流程梳理:

  1. login.vue页面登录调用sotre中的登录dispatch,主要用于

    ① 设置token

    ② 异步存储一些vuex的信息

    ③ 完事进行路由跳转

    ④ 触发permission.js,根据后台返回的权限信息,生成路由

        login({ commit }, userInfo) {
          return new Promise((resolve, reject) => {
            loginApi(userInfo)
              .then((res) => {
                commit('setToken', res.token)
                setToken(res.token)
                setTokenTime()
                router.replace('/')
                resolve()
              })
              .catch((err) => {
                reject(err)
              })
          })
        },
    
    1. 进入permission.js

      ① app/getInfo 获取权限信息 [‘admin’] [‘developer’,‘editor’]

      ② 按照权限信息生成路由 generateRoutes

      ③ addRoutes增加路由信息

      ④ 作跳转处理

      // permission.js
      // get user info
      // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
      // 获取权限信息
      const { roles } = await store.dispatch('app/getInfo')
      
      // 生成动态路由
      // generate accessible routes map based on roles
      const accessRoutes = await store.dispatch(
          'permission/generateRoutes',
          roles
      )
      
      // addRoutes增加路由信息
      // dynamically add accessible routes
      router.addRoutes(accessRoutes)
      
      // 作跳转处理
      // hack method to ensure that addRoutes is complete
      // set the replace: true, so the navigation will not leave a history record
      next({ ...to, replace: true })
      
      // sotre/permission.js
        generateRoutes({ commit }, roles) {
          return new Promise((resolve) => {
            let accessedRoutes
            if (roles.includes('admin')) {
              accessedRoutes = asyncRoutes || []
            } else {
              accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
            }
            commit('SET_ROUTES', accessedRoutes)
            resolve(accessedRoutes)
          })
        }
      
      commit('SET_ROUTES', accessedRoutes)
      一旦触发,会调整menulist,渲染左侧的列表。
      

其他编码信息:

// get user info
    getInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        const roles = ['editor']
        commit('SET_ROLES', roles)
        resolve({ roles })
      })
    },
    resetToken({ commit }) {
      return new Promise((resolve) => {
        commit('setToken', '')
        localStorage.clear()
        removeToken()
        router.replace('/login')
        resolve()
      })
    },
    logout({ commit }) {
      commit('setToken', '')
      localStorage.clear()
      removeToken()
      router.replace('/login')
    }

/**
 * 过滤数组 将树状结构转换为平铺数组
 * @param data 树形结构的数据
 */
export const treeToArray = (data) => {
  const arr = []
  const expanded = (datas) => {
    if (datas && datas.length > 0) {
      datas.forEach((item) => {
        arr.push(item)
        if (item.children) {
          expanded(item.children)
          // eslint-disable-next-line no-param-reassign
          delete item.children
        }
      })
    }
  }
  expanded(data)
  return arr
}

/**
 * 过滤数组 去掉不需要的部分
 * @param data 树形结构的数据
 */
export const deleteArray = (data, referList) => {
  const len = data.length
  for (let i = 0; i < len; i++) {
    if (data[i]) {
      if (!referList.includes(data[i].path)) {
        delete data[i]
        i -= 1
        continue
      }
      if (data[i].children && data[i].children.length) {
        deleteArray(data[i].children, referList)
      }
    }
  }
  return data.filter(Boolean)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值