这里使用的是 vue-admin-template 这个模板。可以从官网下载 vue-admin-template(基础模板)和 vue-template-admin(集成方案) 这两个模板,对照着修改。链接
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: '首页', icon: 'dashboard' }
}]
}
]
// 动态路由
export const asyncRoutes = []
// 错误路由
export const errorRoutes = [
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
// 获取左侧菜单导航
{
url: '/vue-admin-template/user/getMenuList',
type: 'get',
response: config => {
return {
code: 20000,
data: {
menu: [
{
path: '/admin',
component: '#',
redirect: '/roles',
title: '管理员设置',
icon: 'el-icon-s-help',
children: [
{
path: '/roles',
component: 'admin/roles',
title: '角色管理'
},
{
path: '/auth',
component: 'admin/auth',
title: '权限管理'
}
]
}
]
}
}
}
}
// 获取菜单的接口
export function getMenuList() {
return request({
url: '/vue-admin-template/user/getMenuList',
method: 'get'
})
}
在 vue-template-admin 中,找到 src/store/modules/permission.js 文件,复制到自己的项目 vue-admin-template 中,就行修改,修改之后,自己对比这看
import { asyncRoutes, constantRoutes } from '@/router'
import Layout from '@/layout' // 布局组件
import { firstUpperCase } from '@/utils' // 处理单词首字母大写的方法
import { getMenuList } from '@/api/user' // 获取菜单的方法
/**
* Use meta.role to determine if the current user has permission
* @param roles
* @param route
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
/**
* Filter asynchronous routing tables by recursion
* @param routes asyncRoutes
* @param roles
*/
export function filterAsyncRoutes(routes, roles) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})
return res
}
// 过滤获取到的菜单
export function generaMenu(routes, data) {
// console.log(routes);
let menu
data.forEach(item => {
menu = {
path: item.path,
name: firstUpperCase(item.path.substr(1)), // 单词首字母大写
component: item.component === '#' ? Layout : (resolve) => require([`@/views/${item.component}`], resolve),
children: [],
redirect: `${item.redirect}`,
meta: { title: item.title, icon: item.icon }
}
// 解决后台返回的数据 子级路由没有重定向这一属性
if (menu.redirect === 'undefined') {
delete menu.redirect
menu.meta.icon = 'el-icon-menu'
}
if (item.children) {
menu.children.map(v => delete v.redirect)
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 }, roles) {
return new Promise(async (resolve) => {
const loadMenuData = []
let menuList = []
// 从本地缓存获取菜单
const menuRouter = JSON.parse(localStorage.getItem('menuList'))
// 如果没有就发送请求获取菜单
if (!menuRouter) {
const res = await getMenuList()
// console.log(res)
menuList = res.data.menu
// 将菜单存入本地缓存
localStorage.setItem('menuList', JSON.stringify(menuList))
} else {
// 如果本地缓存有,就直接从本地缓存获取
menuList = menuRouter
}
Object.assign(loadMenuData, menuList)
// 将获取到的菜单格式化成标准的路由格式
generaMenu(asyncRoutes, loadMenuData)
let accessedRoutes
if (roles.includes('admin')) {
accessedRoutes = asyncRoutes || []
} else {
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
注意点
在 vue-template-admin 中,找到 src/permission.js 文件,复制到自己的项目 vue-admin-template 中,找到 src/permission.js 文件就行修改,修改之后,自己对比这看
import router from './router'
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'
import { errorRoutes } from '@/router'
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 (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
// get user info
const { roles } = await store.dispatch('user/getInfo')
let accessRoutes
accessRoutes = await store.dispatch('permission/generateRoutes', roles)
accessRoutes = accessRoutes.concat(errorRoutes)
// console.log(accessRoutes)
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} 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()
})
在 src/layout/components/Sidebar/index.vue 文件中,修改这段代码
async logout() {
await this.$store.dispatch('user/logout')
console.log(this.$store.getters.permission_routes)
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
// 清空本地存储 - 清除路由
localStorage.clear()
// 退出后刷新页面,防止从新登录重复菜单 - 此方法不是很完美
// 如果有更好的方法,可以在评论中提出
location.reload()
}