Browse Source

动态菜单路由

daxiongYang 7 years ago
parent
commit
353cfce0b9

+ 0 - 48
src/components/sub-menu-nav/index.vue

@ -1,48 +0,0 @@
1
<template>
2
  <el-submenu
3
    v-if="menuNav.list && menuNav.list.length >= 1"
4
    :data-idx="menuNav.menuId + ''"
5
    :index="menuNav.menuId + ''">
6
    <template slot="title">
7
      <icon-svg :name="menuNav.icon" class="site-sidebar__menu-icon"></icon-svg>
8
      <span>{{ menuNav.name }}</span>
9
    </template>
10
    <sub-menu-nav
11
      v-for="item in menuNav.list" 
12
      :key="item.menuId"
13
      :menu-nav="item">
14
    </sub-menu-nav>
15
  </el-submenu>
16
  <el-menu-item
17
    v-else
18
    :index="menuNav.menuId + ''"
19
    :data-idx="menuNav.menuId + ''"
20
    @click="gotoRouteHandle(menuNav.url)">
21
    <icon-svg :name="menuNav.icon" class="site-sidebar__menu-icon"></icon-svg>
22
    <span>{{ menuNav.name }}</span>
23
  </el-menu-item>
24
</template>
25
26
<script>
27
  import SubMenuNav from '../sub-menu-nav'
28
  import { getRouteNameByUrl } from '@/utils'
29
  export default {
30
    name: 'sub-menu-nav',
31
    props: {
32
      menuNav: Object,
33
      required: true
34
    },
35
    components: {
36
      SubMenuNav
37
    },
38
    methods: {
39
      // 跳转到菜单导航对应路由
40
      gotoRouteHandle (url) {
41
        var routeName = getRouteNameByUrl(url)
42
        if (/\S/.test(routeName)) {
43
          this.$router.push({ name: routeName })
44
        }
45
      }
46
    }
47
  }
48
</script>

+ 1 - 1
src/mock/create.js

@ -23,7 +23,7 @@ export default function (mods, isOpen = true) {
23 23
        console.log('\n')
24 24
25 25
        // 2种url拦截方式
26
        Mock.mock(http.adronUrl(mod.url), mod.type, mod.data)
26
        Mock.mock(http.adornUrl(mod.url), mod.type, mod.data)
27 27
        Mock.mock(new RegExp(mod.url, 'g'), mod.type, mod.data)
28 28
      }
29 29
    }

+ 52 - 17
src/router/index.js

@ -1,16 +1,20 @@
1
// 路由定义使用说明:
2
// 1. 代码中路由统一使用name属性跳转.
3
// 2. 开放path属性用做简短路由, 比如: '/a1', 访问地址: www.renren.io/#/a1
1 4
import Vue from 'vue'
2 5
import Router from 'vue-router'
6
import { currentRouteIsDefault, addMenuListRoutes } from './utils'
7
import http from '@/utils/http'
8
9
Vue.use(Router)
3 10
4 11
// 开发环境不使用懒加载, 因为懒加载页面太多的话会造成webpack热更新太慢, 所以只有开发环境使用懒加载
5 12
const _import = require('./import-' + process.env.NODE_ENV)
6 13
7
Vue.use(Router)
8
9
// 路由定义使用说明:
10
// 1. 代码中路由统一使用name属性跳转.
11
// 2. 开放path属性用做简短路由, 比如: '/a1', 访问地址: www.renren.io/#/a1
12
export default new Router({
14
const router = new Router({
13 15
  mode: 'hash',
16
  scrollBehavior: () => ({ y: 0 }),
17
  isAddMenuListRoutes: false,
14 18
  routes: [
15 19
    { path: '/404', component: _import('error/404'), name: '404', desc: '404未找到' },
16 20
    { path: '/login', component: _import('login/index'), name: 'login', desc: '登录' },
@ -21,16 +25,15 @@ export default new Router({
21 25
      redirect: { name: 'home' },
22 26
      desc: '主入口整体布局',
23 27
      children: [
24
        // 通过isTab属性, 设定是否通过tab标签页展示内容
25 28
        { path: '/home', component: _import('home/index'), name: 'home', desc: '首页' },
26
        { path: '/theme', component: _import('theme/index'), name: 'theme', desc: '主题' },
27
        { path: '/schedule', component: _import('modules/schedule/index'), name: 'schedule', desc: '定时任务', meta: { isTab: true } },
28
        { path: '/oss', component: _import('modules/oss/index'), name: 'oss', desc: '文件上传', meta: { isTab: true } },
29
        { path: '/config', component: _import('modules/config/index'), name: 'config', desc: '参数管理', meta: { isTab: true } },
30
        { path: '/log', component: _import('modules/log/index'), name: 'log', desc: '系统日志', meta: { isTab: true } },
31
        { path: '/menu', component: _import('modules/menu/index'), name: 'menu', desc: '菜单管理', meta: { isTab: true } },
32
        { path: '/role', component: _import('modules/role/index'), name: 'role', desc: '角色管理', meta: { isTab: true } },
33
        { path: '/user', component: _import('modules/user/index'), name: 'user', desc: '管理员管理', meta: { isTab: true } }
29
        { path: '/theme', component: _import('theme/index'), name: 'theme', desc: '主题' }
30
        // { path: '/schedule', component: _import('modules/schedule/index'), name: 'schedule', desc: '定时任务', meta: { isTab: true } },
31
        // { path: '/oss', component: _import('modules/oss/index'), name: 'oss', desc: '文件上传', meta: { isTab: true } },
32
        // { path: '/config', component: _import('modules/config/index'), name: 'config', desc: '参数管理', meta: { isTab: true } },
33
        // { path: '/log', component: _import('modules/log/index'), name: 'log', desc: '系统日志', meta: { isTab: true } },
34
        // { path: '/menu', component: _import('modules/menu/index'), name: 'menu', desc: '菜单管理', meta: { isTab: true } },
35
        // { path: '/role', component: _import('modules/role/index'), name: 'role', desc: '角色管理', meta: { isTab: true } },
36
        // { path: '/user', component: _import('modules/user/index'), name: 'user', desc: '管理员管理', meta: { isTab: true } }
34 37
      ],
35 38
      beforeEnter (to, from, next) {
36 39
        let token = Vue.cookie.get('token')
@ -39,7 +42,39 @@ export default new Router({
39 42
        }
40 43
        next()
41 44
      }
42
    },
43
    { path: '*', redirect: { name: '404' } }
45
    }
46
    // { path: '*', redirect: { name: '404' } }
44 47
  ]
45 48
})
49
50
console.log(router)
51
52
router.beforeEach((to, from, next) => {
53
  console.log(router.options.isAddMenuListRoutes)
54
  if (router.options.isAddMenuListRoutes || currentRouteIsDefault(to, router.options.routes.filter(item => item.path !== '/'))) {
55
    next()
56
  } else if (sessionStorage.getItem('menuList')) {
57
    router.addRoutes(addMenuListRoutes(JSON.parse(sessionStorage.getItem('menuList'))))
58
    router.options.isAddMenuListRoutes = true
59
    next({ ...to, replace: true })
60
  } else {
61
    http({
62
      url: http.adornUrl('/sys/menu/nav'),
63
      method: 'get',
64
      params: http.adornParams()
65
    }).then(({data}) => {
66
      if (data && data.code === 0) {
67
        router.addRoutes(addMenuListRoutes(data.menuList))
68
        router.options.isAddMenuListRoutes = true
69
        sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]'))
70
        sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
71
      } else {
72
        sessionStorage.setItem('menuList', '[]')
73
        sessionStorage.setItem('permissions', '[]')
74
      }
75
      next({ ...to, replace: true })
76
    })
77
  }
78
})
79
80
export default router

+ 67 - 0
src/router/utils.js

@ -0,0 +1,67 @@
1
import Vue from 'vue'
2
const _import = require('./import-' + process.env.NODE_ENV)
3
4
/**
5
 * 判断当前路由是否为默认路由
6
 * true: 默认路由, false: 动态菜单路由
7
 * @param {*} currentRoute
8
 * @param {*} defaultRouteList
9
 */
10
export function currentRouteIsDefault (currentRoute, defaultRouteList) {
11
  var temp = []
12
  for (var i = 0; i < defaultRouteList.length; i++) {
13
    if (currentRoute.path === defaultRouteList[i].path) {
14
      return true
15
    } else if (defaultRouteList[i].children && defaultRouteList[i].children.length >= 1) {
16
      temp = temp.concat(defaultRouteList[i].children)
17
    }
18
  }
19
  return temp.length >= 1 ? currentRouteIsDefault(currentRoute, temp) : false
20
}
21
22
/**
23
 * 添加动态菜单路由
24
 * @param {*} menuList
25
 */
26
export function addMenuListRoutes (menuList = [], routes = []) {
27
  var temp = []
28
  var tempRouteName = ''
29
  for (var i = 0; i < menuList.length; i++) {
30
    if (menuList[i].list && menuList[i].list.length >= 1) {
31
      temp = temp.concat(menuList[i].list)
32
    } else {
33
      tempRouteName = getRouteNameByUrl(menuList[i].url)
34
      if (/\S/.test(tempRouteName) && tempRouteName !== 'sql') {
35
        routes.push({
36
          path: tempRouteName,
37
          component: _import(`modules/${tempRouteName}/index`),
38
          name: tempRouteName,
39
          desc: tempRouteName,
40
          meta: { isTab: true }
41
        })
42
      }
43
    }
44
  }
45
  return temp.length >= 1 ? addMenuListRoutes(temp, routes) : [
46
    {
47
      path: '/',
48
      component: _import('main'),
49
      redirect: { name: 'home' },
50
      desc: '主入口整体布局',
51
      children: routes,
52
      beforeEnter (to, from, next) {
53
        let token = Vue.cookie.get('token')
54
        if (!token || !/\S/.test(token)) {
55
          next({ name: 'login' })
56
        }
57
        next()
58
      }
59
    },
60
    { path: '*', redirect: { name: '404' } }
61
  ]
62
}
63
64
function getRouteNameByUrl (url) {
65
  let val = /.*\/(.*)\.html/.exec(url)
66
  return val && val.length >= 1 ? val[1] : ''
67
}

+ 49 - 0
src/views/main-sidebar-sub-menu-nav.vue

@ -0,0 +1,49 @@
1
<template>
2
  <el-submenu
3
    v-if="menuNav.list && menuNav.list.length >= 1"
4
    :data-idx="menuNav.menuId + ''"
5
    :index="menuNav.menuId + ''">
6
    <template slot="title">
7
      <icon-svg :name="menuNav.icon" class="site-sidebar__menu-icon"></icon-svg>
8
      <span>{{ menuNav.name }}</span>
9
    </template>
10
    <sub-menu-nav
11
      v-for="item in menuNav.list" 
12
      :key="item.menuId"
13
      :menu-nav="item">
14
    </sub-menu-nav>
15
  </el-submenu>
16
  <el-menu-item
17
    v-else
18
    :index="menuNav.menuId + ''"
19
    :data-idx="menuNav.menuId + ''"
20
    @click="gotoRouteHandle(menuNav.url)">
21
    <icon-svg :name="menuNav.icon" class="site-sidebar__menu-icon"></icon-svg>
22
    <span>{{ menuNav.name }}</span>
23
  </el-menu-item>
24
</template>
25
26
<script>
27
  import SubMenuNav from './main-sidebar-sub-menu-nav'
28
  import { getRouteNameByUrl } from '@/utils'
29
  export default {
30
    name: 'sub-menu-nav',
31
    props: {
32
      menuNav: Object,
33
      required: true
34
    },
35
    components: {
36
      SubMenuNav
37
    },
38
    methods: {
39
      // 跳转到菜单导航对应路由
40
      gotoRouteHandle (url) {
41
        console.log(url)
42
        var routeName = getRouteNameByUrl(url)
43
        if (/\S/.test(routeName)) {
44
          this.$router.push({ name: routeName })
45
        }
46
      }
47
    }
48
  }
49
</script>

+ 1 - 1
src/views/main-sidebar.vue

@ -21,7 +21,7 @@
21 21
</template>
22 22
23 23
<script>
24
  import SubMenuNav from '@/components/sub-menu-nav'
24
  import SubMenuNav from './main-sidebar-sub-menu-nav'
25 25
  import { mapMutations } from 'vuex'
26 26
  import { getRouteNameByUrl } from '@/utils'
27 27
  import isEmpty from 'lodash/isEmpty'