vue-admin-template新增permission模組實現動態路由
阿新 • • 發佈:2022-03-26
- 首先在src/permission.js 中修改登入許可權判斷,並根據許可權動態載入路由
router.beforeEach(async(to, from, next) => { // start progress bar NProgress.start() // set page title document.title = getPageTitle(to.meta.title) // 確定使用者是否已登入 const hasToken = getToken() if (hasToken) { if (to.path === '/login') { // 如果已登入,直接重定向到主頁 next({ path: '/' }) NProgress.done() } else { // 確定使用者是否已通過getInfo獲得其許可權角色 // 1. 這裡需要確定store.getter.roles在store中存在 要不會死迴圈的 const hasRoles = store.getters.roles && store.getters.roles.length > 0 if (hasRoles) { next() } else { try { //獲取使用者資訊 //注意:角色必須是物件陣列!例如:['admin']或,['developer','editor'] const { roles } = await store.dispatch('user/getInfo') //根據角色生成可訪問的路由 const accessRoutes = await store.dispatch('permission/generateRoutes', roles) //動態新增可訪問的路由 router.addRoutes(accessRoutes) // 設定replace:true,這樣導航就不會留下歷史記錄 以防使用者點選後退報錯 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() } } })
- 在store/moudel/user.js中 修改
import { login, logout, getInfo } from '@/api/user' import { getToken, setToken, removeToken } from '@/utils/auth' import { resetRouter } from '@/router' const getDefaultState = () => { return { token: getToken(), name: '', avatar: '', roles: [] //用於儲存使用者角色資訊 } } const state = getDefaultState() const mutations = { RESET_STATE: (state) => { Object.assign(state, getDefaultState()) }, SET_TOKEN: (state, token) => { state.token = token }, SET_NAME: (state, name) => { state.name = name }, SET_AVATAR: (state, avatar) => { state.avatar = avatar }, SET_ROLES: (state, roles) => { state.roles = roles } } const actions = { // user login login({ commit }, userInfo) { const { username, password } = userInfo return new Promise((resolve, reject) => { login({ username: username.trim(), password: password }).then(response => { const { data } = response commit('SET_TOKEN', data.token) setToken(data.token) resolve() }).catch(error => { reject(error) }) }) }, // get user info getInfo({ commit, state }) { return new Promise((resolve, reject) => { getInfo(state.token).then(response => { const { data } = response if (!data) { reject('Verification failed, please Login again.') } const { roles, name, avatar } = data // roles must be a non-empty array if (!roles || roles.length <= 0) { reject('getInfo: roles must be a non-null array!') } commit('SET_ROLES', roles) commit('SET_NAME', name) commit('SET_AVATAR', avatar) resolve(data) }).catch(error => { reject(error) }) }) }, // user logout logout({ commit, state }) { return new Promise((resolve, reject) => { logout(state.token).then(() => { removeToken() // must remove token first resetRouter() commit('RESET_STATE') resolve() }).catch(error => { reject(error) }) }) }, // remove token resetToken({ commit }) { return new Promise(resolve => { removeToken() // must remove token first commit('RESET_STATE') resolve() }) } } export default { namespaced: true, state, mutations, actions }
- 修改store/getter.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, roles: state => state.user.roles, permission_routes: state => state.permission.routes }
- 在router中設定需要動態新增的路由
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
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: 'Dashboard', icon: 'dashboard' }
}]
},
{
path: '/example',
component: Layout,
redirect: '/example/table',
name: 'Example',
meta: { title: 'Example', icon: 'el-icon-s-help' },
children: [
{
path: 'table',
name: 'Table',
component: () => import('@/views/table/index'),
meta: { title: 'Table', icon: 'table' }
},
{
path: 'tree',
name: 'Tree',
component: () => import('@/views/tree/index'),
meta: { title: 'Tree', icon: 'tree' }
}
]
},
{
path: '/form',
component: Layout,
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/form/index'),
meta: { title: 'Form', icon: 'form' }
}
]
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
{
path: '/nested',
component: Layout,
redirect: '/nested/menu1',
name: 'Nested',
meta: {
title: 'Nested',
icon: 'nested'
},
children: [
{
path: 'menu1',
component: () => import('@/views/nested/menu1/index'), // Parent router-view
name: 'Menu1',
meta: { title: 'Menu1' },
children: [
{
path: 'menu1-1',
component: () => import('@/views/nested/menu1/menu1-1'),
name: 'Menu1-1',
meta: { title: 'Menu1-1' }
},
{
path: 'menu1-2',
component: () => import('@/views/nested/menu1/menu1-2'),
name: 'Menu1-2',
meta: { title: 'Menu1-2' },
children: [
{
path: 'menu1-2-1',
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
name: 'Menu1-2-1',
meta: { title: 'Menu1-2-1' }
},
{
path: 'menu1-2-2',
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
name: 'Menu1-2-2',
meta: { title: 'Menu1-2-2' }
}
]
},
{
path: 'menu1-3',
component: () => import('@/views/nested/menu1/menu1-3'),
name: 'Menu1-3',
meta: { title: 'Menu1-3' }
}
]
},
{
path: 'menu2',
component: () => import('@/views/nested/menu2/index'),
meta: { title: 'menu2' }
}
]
},
{
path: 'external-link',
component: Layout,
children: [
{
path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
meta: { title: 'External Link', icon: 'link' }
}
]
},
// 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
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
- 至此動態路由大體完成,還差最後一步,讓自動生成的路由在頁面顯示,這裡需要修改
layout/sidebar/index.vue
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
computed: {
...mapGetters([
'permission_routes',
'sidebar'
]),
}
OK,側邊欄也好了!