vue 权限管理 动态路由(6)

1.动态生成路由

import Vue from 'vue'
import Router from 'vue-router'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'// progress bar style
import store from '@/store'
import api from '@/api'

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/home',
      name: 'home',
      component: () => import('@/views/home/home.vue'),
      children: [],
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('@/views/login/login.vue'),
    },
    {
      path: '/error',
      name: 'error',
      component: () => import('@/views/error.vue'),
    }
  ]
})
// const whiteList = ['/login', '/authredirect']// no redirect whitelist
// // 全局钩子
// router.beforeEach((to, from, next) => {
//     let token = localStorage.getItem('token');
//     let userName = localStorage.getItem('user')
//     NProgress.start() // start progress bar
//     console.info(token)
//     // 如果有token
//     // token = 'undefined'
//     if (token !== 'undefined') { // determine if there has token
//       // 登录后进入登录页
//       if (to.path === '/login') {
//         next({path: '/home'})
//         NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it
//       } else {
//         addDynamicMenuAndRoutes(userName, to, from)
//         NProgress.done()
//       }
//     } else {
//       /* has no token*/
//       if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
//         next()
//       } else {
//         next('/login') // 否则全部重定向到登录页
//         NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
//       }
//     }
//   }
// )
//
// router.afterEach(() => {
//   NProgress.done() // finish progress bar
// })
router.beforeEach((to, from, next) => {
  // 登录界面登录成功之后,会把用户信息保存在会话
  // 存在时间为会话生命周期,页面关闭即失效。
  let token = localStorage.getItem('token');
  let userName = localStorage.getItem('user')
  // token = ""
  if (to.path === '/login') {
    // 如果是访问登录界面,如果用户会话信息存在,代表已登录过,跳转到主页
    if (token) {
      next({path: '/home'})
    } else {
      next()
    }
  } else {
    if (!token) {
      // 如果访问非登录界面,且户会话信息不存在,代表未登录,则跳转到登录界面
      next({path: '/login'})
    } else {
      // 加载动态菜单和路由
      addDynamicMenuAndRoutes(userName, to, from)
      next()
    }
  }
})

/**
 * 加载动态菜单和路由
 */
function addDynamicMenuAndRoutes(userName, to, from) {
  // 处理IFrame嵌套页面
  // handleIFrameUrl(to.path)
  if (store.state.app.menuRouteLoaded) {
    console.log('动态菜单和路由已经存在.')
    return
  }
  api.user.findMenus({'username': userName}).then(res => {
    // 添加动态路由
    let dynamicRoutes = addDynamicRoutes(res.data)
    // 处理静态组件绑定路由
    handleStaticComponent(router, dynamicRoutes)
    router.addRoutes(router.options.routes)
    // console.info(JSON.stringify(router.options.routes))
    // 保存加载状态
    store.commit('menuRouteLoaded', true)
    // 保存菜单树
    store.commit('setNavTree', res.data)
  }).then(res => {
    api.user.findPermissions({'username': userName}).then(res => {
      // 保存用户权限标识集合
      console.info(JSON.stringify(res.data))
      store.commit('setPerms', res.data)
    })
  })
}

/**
 * 添加动态(菜单)路由
 * @param {*} menuList 菜单列表
 * @param {*} routes 递归创建的动态(菜单)路由
 */
function addDynamicRoutes(menuList = [], routes = []) {
  var temp = []
  for (var i = 0; i < menuList.length; i++) {
    if (menuList[i].menuChild && menuList[i].menuChild.length >= 1) {
      temp = temp.concat(menuList[i].menuChild)
    } else if (menuList[i].path && /\S/.test(menuList[i].path)) {
      menuList[i].path = menuList[i].path.replace(/^\//, '')
      // 创建路由配置
      var route = {
        path: "/" + menuList[i].path,
        component: null,
        name: menuList[i].menuName,
        meta: {
          icon: menuList[i].icon,
          index: menuList[i].menuId,
        }
      }
      try {
        // 根据菜单URL动态加载vue组件,这里要求vue组件须按照url路径存储
        // 如url="sys/user",则组件路径应是"@/views/sys/User.vue",否则组件加载不到
        let array = menuList[i].path.split('/')
        let url = ''
        for (let i = 0; i < array.length; i++) {
          url += array[i].substring(0, 1).toUpperCase() + array[i].substring(1) + '/'
        }
        url = url.substring(0, url.length - 1)
        // console.log(url)
        route['component'] = resolve => require([`@/views/${url}.vue`], resolve)
      } catch (e) {
      }
      routes.push(route)
    }
  }
  if (temp.length >= 1) {
    addDynamicRoutes(temp, routes)
  } else {
    console.log('动态路由加载...')
    // console.log(routes)
    console.log('动态路由加载完成.')
  }
  return routes
}

/**
 * 处理路由到本地直接指定页面组件的情况
 * 比如'代码生成'是要求直接绑定到'Generator'页面组件
 */
function handleStaticComponent(router, dynamicRoutes) {
  // console.info(JSON.stringify(router.options))
  router.options.routes[0].children = router.options.routes[0].children.concat(dynamicRoutes)
}

export default router

 动态生成路由 并将菜单信息保存到stroe中去

 

后台数据为:

[{"menuId":1,"parentId":0,"menuName":"系统管理","path":"/system","component":"/system","perms":null,"icon":"el-icon-s-platform","type":"0","orderNum":2,"createTime":"2017-12-27T08:39:07.000+0000","modifyTime":"2019-01-05T03:13:14.000+0000","menuChild":[{"menuId":3,"parentId":1,"menuName":"用户管理","path":"/system/user","component":"/system/user","perms":"user:view","icon":"el-icon-user-solid","type":"0","orderNum":1,"createTime":"2017-12-27T08:47:13.000+0000","modifyTime":"2019-01-21T22:45:55.000+0000","menuChild":null},{"menuId":4,"parentId":1,"menuName":"角色管理","path":"/system/role","component":"/system/role","perms":"role:view","icon":"el-icon-user","type":"0","orderNum":2,"createTime":"2017-12-27T08:48:09.000+0000","modifyTime":"2018-04-25T01:01:12.000+0000","menuChild":null},{"menuId":6,"parentId":1,"menuName":"部门管理","path":"/system/dept","component":"/system/dept","perms":"dept:view","icon":"iconfont iconzuzhijiagou","type":"0","orderNum":4,"createTime":"2017-12-27T08:57:33.000+0000","modifyTime":"2018-04-25T01:01:40.000+0000","menuChild":null},{"menuId":5,"parentId":1,"menuName":"菜单管理","path":"/system/menus","component":"/system/menus","perms":"menu:view","icon":"el-icon-menu","type":"0","orderNum":3,"createTime":"2017-12-27T08:48:57.000+0000","modifyTime":"2018-04-25T01:01:30.000+0000","menuChild":null},{"menuId":64,"parentId":1,"menuName":"字典管理","path":"/system/dict","component":"/system/dict","perms":"dict:view","icon":"el-icon-tickets","type":"0","orderNum":5,"createTime":"2018-01-18T02:38:25.000+0000","modifyTime":"2018-04-25T01:01:50.000+0000","menuChild":null}]},{"menuId":2,"parentId":0,"menuName":"系统监控","path":"/monitor","component":"/monitor","perms":null,"icon":"el-icon-s-order","type":"0","orderNum":6,"createTime":"2017-12-27T08:45:51.000+0000","modifyTime":"2019-01-22T22:27:12.000+0000","menuChild":[{"menuId":127,"parentId":2,"menuName":"服务器信息","path":"/monitor/systemInfo","component":"/monitor/systemInfo","perms":null,"icon":null,"type":"0","orderNum":3,"createTime":"2019-01-20T23:53:43.000+0000","modifyTime":"2019-01-20T23:57:00.000+0000","menuChild":null},{"menuId":124,"parentId":2,"menuName":"JVM信息","path":"/monitor/jvminfo","component":"/monitor/jvminfo","perms":null,"icon":null,"type":"0","orderNum":1,"createTime":"2019-01-17T18:33:30.000+0000","modifyTime":"2019-01-17T18:46:51.000+0000","menuChild":null},{"menuId":8,"parentId":2,"menuName":"在线用户","path":"/monitor/online","component":"/monitor/online","perms":"user:online","icon":"","type":"0","orderNum":1,"createTime":"2017-12-27T08:59:33.000+0000","modifyTime":"2018-04-25T01:02:04.000+0000","menuChild":null},{"menuId":122,"parentId":2,"menuName":"系统信息","path":"/monitor/system","component":"/monitor/system","perms":null,"icon":null,"type":"0","orderNum":5,"createTime":"2019-01-17T18:31:48.000+0000","modifyTime":"2019-01-17T18:39:46.000+0000","menuChild":null},{"menuId":113,"parentId":2,"menuName":"Redis监控","path":"/monitor/redis","component":"/monitor/redis","perms":"redis:view","icon":null,"type":"0","orderNum":3,"createTime":"2018-06-28T06:29:42.000+0000","modifyTime":null,"menuChild":null},{"menuId":121,"parentId":2,"menuName":"请求追踪","path":"/monitor/httptrace","component":"/monitor/httptrace","perms":null,"icon":null,"type":"0","orderNum":4,"createTime":"2019-01-17T18:30:29.000+0000","modifyTime":null,"menuChild":null},{"menuId":123,"parentId":2,"menuName":"Tomcat信息","path":"/monitor/tomcatinfo","component":"/monitor/tomcatinfo","perms":null,"icon":null,"type":"0","orderNum":2,"createTime":"2019-01-17T18:32:53.000+0000","modifyTime":"2019-01-17T18:46:57.000+0000","menuChild":null}]},{"menuId":144,"parentId":0,"menuName":"坐席服务管理","path":"/service","component":"/service","perms":null,"icon":"el-icon-menu","type":"0","orderNum":4,"createTime":"2017-12-27T08:39:07.000+0000","modifyTime":"2019-01-05T03:13:14.000+0000","menuChild":null},{"menuId":145,"parentId":0,"menuName":"规则管理","path":"/rule","component":"/rule","perms":null,"icon":"el-icon-document","type":"0","orderNum":5,"createTime":"2017-12-27T08:39:07.000+0000","modifyTime":"2019-01-05T03:13:14.000+0000","menuChild":null},{"menuId":142,"parentId":0,"menuName":"主页","path":"/home","component":"/home","perms":null,"icon":"el-icon-s-home","type":"0","orderNum":1,"createTime":"2017-12-27T08:39:07.000+0000","modifyTime":"2019-01-05T03:13:14.000+0000","menuChild":null},{"menuId":143,"parentId":0,"menuName":"知识管理","path":"/knowology","component":"/knowology","perms":null,"icon":"el-icon-location","type":"0","orderNum":3,"createTime":"2017-12-27T08:39:07.000+0000","modifyTime":"2019-01-05T03:13:14.000+0000","menuChild":null}] 

路由加载完成以后通过 菜单管理显示

<template>
  <el-submenu v-if="menu.menuChild && menu.menuChild.length >= 1" :index="menu.parentId+'-'+menu.orderNum">
    <template slot="title">
      <i :class="menu.icon"></i>
      <span slot="title">{{menu.menuName}}</span>
    </template>
    <MenuTree v-for="item in menu.menuChild" :key="item.menuId" :menu="item"></MenuTree>
  </el-submenu>
  <el-menu-item v-else :index="menu.parentId+'-'+menu.orderNum" @click="handleRoute(menu)">
    <i :class="menu.icon"></i>
    <span slot="title">{{menu.menuName}}</span>
  </el-menu-item>
</template>

<script>
  export default {
    name: 'MenuTree',
    props: {
      menu: {
        type: Object,
        required: true
      }
    },
    methods: {
      handleRoute(menu) {
        // 通过菜单URL跳转至指定路由
        this.$router.push("/" + menu.path)
      }
    }
  }
</script>
<style>

</style>

遍历所有的路由并显示后  在需要显示的地方调用

<template>
  <div :style="{'background':themeColor}" :class="collapse?'menu-bar-collapse-width':'menu-bar-width'"
       @mouseenter="collapseOpen" @mouseleave="collapseClose">
    <el-menu default-active='0' collapse-transition  :style="{'background':themeColor}"
             :collapse="collapse" :class="collapse?'menu-bar-collapse-width':'menu-bar-width'">
      <menu-tree v-for="item in navTree" :key="item.menuId" :menu="item"></menu-tree>
    </el-menu>
  </div>
</template>

<script src="@/views/asideContainer/asideContainer.js"></script>
<style scoped src="@/views/asideContainer/asideContainer.scss">
</style>
import {mapState} from 'vuex'
import MenuTree from "@/components/MenuTree"

export default {
  components: {
    MenuTree
  },
  methods: {
    collapseOpen() {
      this.$store.commit('collapseOpen')
    },
    collapseClose() {
      this.$store.commit('collapseClose')
    }
  },
  computed: {
    ...mapState({
      themeColor: state => state.app.themeColor,
      oldThemeColor: state => state.app.oldThemeColor,
      collapse: state => state.app.collapse,
      navTree: state => state.menu.navTree
    })
  }
}

 

<template>
  <div class="wrapper">
    <header-container></header-container>
    <aside-container></aside-container>
    <main-container></main-container>
  </div>
</template>

<script src="@/views/home/home.js"></script>
<style src="@/views/home/home.scss"></style>

 显示效果为:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值