vue-element-template改为从后台获取菜单
一、后端接口获取菜单信息
1、返回数据样式
{
"code": 20000,
"data": [{
"menuId": "2000000000000001",
"parentMenuId": "0",
"name": "Json工具",
"menuType": 2,
"component": "#",
"redirect": "",
"alwaysShow": true,
"hidden": false,
"sort": 0,
"level": 0,
"children": [{
"menuId": "2210574586898432",
"parentMenuId": "2000000000000001",
"name": "Json校验格式化工具",
"menuType": 2,
"component": "/amis/index",
"redirect": "",
"alwaysShow": true,
"hidden": false,
"sort": 0,
"level": 0,
"children": [],
"meta": {
"title": "Json校验格式化工具",
"icon": "",
"roles": null
}
}],
"meta": {
"title": "Json工具",
"icon": "user",
"roles": null
}
}],
"msg": "操作成功",
"pager": null
}
2、调整src/router/index.js文件内容
const createRouter = ()上面增加动态路由默认配置
// asyncRoutes 是动态的,后台返回哪些就只有哪些。
export const asyncRoutes = [
// 404 必须添加
{ path: '*', redirect: '/404', hidden: true }
]
3、增加permission处理
创建 src/store/modules/permission.js 文件
import { constantRoutes } from '@/router' // 引入路由表里的固定路由
import { getMenu } from '@/api/user' // 引入第一步创建的获取权限信息的接口
import Layout from '@/layout' // 引入布局
/**
* 后台查询的菜单数据拼装成路由格式的数据
*/
export function generaMenu(routes, data) {
data.forEach(item => {
console.log('菜单信息', JSON.stringify(item))
const menu = {
path: '/page/' + item.menuId,
component: item.component === '#' ? Layout : () => import('@/views/amis/index'),
hidden: item.hidden,
redirect: item.redirect,
children: [],
name: 'menu_' + item.menuId,
meta: item.meta
}
if (item.children) {
generaMenu(menu.children, item.children)
}
routes.push(menu)
})
}
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes // 路由访问
state.routes = constantRoutes.concat(routes) // 菜单显示
}
}
const actions = {
generateRoutes({ commit }) {
return new Promise(async resolve => {
const routes = await getMenu({menuType: 2}) // 接口获取到后台返回的权限信息,包含路由
console.log("查询的菜单信息",routes)
const asyncRoutes = []
generaMenu(asyncRoutes, routes.data)
commit('SET_ROUTES', asyncRoutes)
resolve(asyncRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
4、把自定义的permission挂在到store上面
修改src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
// !!!!增加内容开始
import permission from './modules/permission'
// !!!!增加内容结束
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
settings,
user,
// !!!!增加内容开始
permission
// !!!!增加内容结束
},
getters
})
export default store
5、权限拦截
修改src/permission.js文件,注意路径: 不是上面新增的文件
// 修改内容开始
import router,{ constantRoutes } from './router' // 这里把constantRoutes 引入进来
// 修改内容结束
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
// 修改内容开始
//去除权限,如果不去除权限,把下面的if(token)放开就可以
next()
const accessRoutes = await store.dispatch('permission/generateRoutes')
router.addRoutes(accessRoutes)
// if (hasToken) {
// if (to.path === '/login') {
// // if is logged in, redirect to the home page
// next({ path: '/' })
// NProgress.done()
// } else {
// const hasGetUserInfo = store.getters.name
// if (hasGetUserInfo) {
// next()
// } else {
// try {
// // get user info
// await store.dispatch('user/getInfo')
// // 这里调用的就是第三步新建的generateRoutes
// const accessRoutes = await store.dispatch('permission/generateRoutes')
// router.options.routers = constantRoutes.concat(accessRoutes) // 这一步必须写,不然会出现左侧菜单空白、刷新空白等问题
// router.addRoutes(accessRoutes)
// next({ ...to, replace: true })
// // next()
// } 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()
// }
// }
// }
// } else {
// /* has no token*/
// if (whiteList.indexOf(to.path) !== -1) {
// // in the free login whitelist, go directly
// next()
// } else {
// // other pages that do not have permission to access are redirected to the login page.
// next(`/login?redirect=${to.path}`)
// NProgress.done()
// }
// }
// 修改内容结束
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})
6、修改src/store/getters.js文件,增加动态路由
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
// 增加内容开始
// 动态路由
permission_routes: state => state.permission.routes
// 增加内容结束
}
export default getters
7、修改菜单组件vue文件
修改src/layout/components/Sidebar/index.vue
<template>
<div :class="{'has-logo':showLogo}">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
>
<!-- <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /> -->
<!-- 修改内容开始 -->
<!-- 动态路由 -->
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
<!-- 修改内容结束 -->
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'
export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
//修改内容开始
'permission_routes', // 动态路由
//修改内容结束
'sidebar'
]),
routes() {
return this.$router.options.routes
},
activeMenu() {
const route = this.$route
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
},
showLogo() {
return this.$store.state.settings.sidebarLogo
},
variables() {
return variables
},
isCollapse() {
return !this.sidebar.opened
}
}
}
</script>
参考文档:https://blog.csdn.net/qq_36873710/article/details/124430511