一、專案主體
- 管理平臺(代稱為ManagePlatform、MP)
- 一級選單(代稱M)
- 二級選單(代稱m)
結構圖:
二、應用場景
不同使用者擁有不同的選單許可權:
- 管理員(manageUser)擁有可見全部選單的許可權
- 使用者1(user1)擁有可見M1下的全部選單的許可權
- 使用者2(user2)擁有可見M1和M2下的全部選單的許可權
- 使用者3(user3)擁有可見M1、M2下全部及M3的m31選單許可權
三、實現思路
許可權控制:
- 導航欄選單是否可見
- 校驗url能否跳轉
服務端:
- 介面返回當前使用者的許可權資料,並實際選單結構保持一致(MP中包含M1、M2、M3,M1中包含m11、m12,...)
- 其中每個選單包含id(選單id)、name(選單名稱)、children(子集選單)等必要屬性
前端:
- 路由預設配置全部的選單,但均為隱藏狀態(登入和首頁無許可權,無需限制)
- 通過介面獲取到該使用者的許可權資料,並與預設路由進行比對,將對應選單部分設定為可顯示(有許可權)
- 將選單所有id儲存到本地list,在路由跳轉之前校驗此路由的id是否包含在list中,如果有,則執行跳轉,否則進入到首頁(表示沒有許可權)
四、程式碼模擬
預設路由routes:
export default [
{
path: '/M1',
redirect: '/M1/m11',
component: Layout,
name: 'M1選單',
meta: {
extraMenuId: 1,
hidden: true
},
children: [{
path: '/M1/m11',
name: 'm11選單',
component(resolve) {
require(['@views/M1/m11'], resolve);
},
meta: {
extraMenuId: 2,
hidden: true,
}
}, {
path: '/M1/m12',
name: 'm12選單',
component(resolve) {
require(['@views/M1/m12'], resolve);
},
meta: {
extraMenuId: 3,
hidden: true,
}
}]
},
{
path: '/M2',
redirect: '/M2/m21',
component: Layout,
name: 'M2選單',
meta: {
extraMenuId: 4,
hidden: true
},
children: [{
path: '/M2/m11',
name: 'm21選單',
component(resolve) {
require(['@views/M2/m21'], resolve);
},
meta: {
extraMenuId: 5,
hidden: true,
}
}, {
path: '/M2/m22',
name: 'm22選單',
component(resolve) {
require(['@views/M2/m22'], resolve);
},
meta: {
extraMenuId: 6,
hidden: true,
}
}]
},
{
path: '/M3',
redirect: '/M3/m31',
component: Layout,
name: 'M3選單',
meta: {
extraMenuId: 7,
hidden: true
},
children: [{
path: '/M3/m31',
name: 'm31選單',
component(resolve) {
require(['@views/M3/m31'], resolve);
},
meta: {
extraMenuId: 8,
hidden: true,
}
}, {
path: '/M3/m32',
name: 'm32選單',
component(resolve) {
require(['@views/M3/m32'], resolve);
},
meta: {
extraMenuId: 9,
hidden: true,
}
}, {
path: '/M3/m33',
name: 'm33選單',
component(resolve) {
require(['@views/M3/m33'], resolve);
},
meta: {
extraMenuId: 9,
hidden: true,
}
}]
},
{
path: '/login',
name: '登入',
component(resolve) {
require(['@views/login'], resolve);
},
meta: {
hidden: true
}
},
{
path: '/home',
name: '首頁',
component(resolve) {
require(['@views/home'], resolve);
},
meta: {
hidden: true
}
},
{
path: '*',
redirect: '/home',
meta: {
hidden: true
}
}
]
複製程式碼
選單id資料menuIdList與路由routes匹配:
// 因管理端選單展示只展示兩層,故只需遍歷前兩層路由
routes.forEach((item) => {
if (menuIdList.indexOf(item.meta.extraMenuId) >= 0) {
item.meta.hidden = false;
if (item.children && item.children.length) {
item.children.forEach((child) => {
if (menuIdList.indexOf(child.meta.extraMenuId) >= 0) {
child.meta.hidden = false;
}
})
}
}
});
複製程式碼
公共方法判斷id是否存在:
/**
* 判斷menuId是否存在與Localtorage中
* @param menuId
*/
export function getMenuAuth(menuId) {
const menuIdList = JSON.parse(getMenuIdList());
return menuIdList.indexOf(menuId) >= 0;
}
複製程式碼
路由守衛校驗:
router.beforeEach((to, from, next) => {
// 判斷是否已登入,未登入則進入登入頁面
if (getToken()) {
if (to.path === '/login') {
next();
} else {
if (to.path === '/' || to.path === '/home') {
next();
return;
}
// url路由許可權校驗,沒有許可權則進入home頁面
if (getMenuAuth(to.meta.extraMenuId)) {
next();
} else {
next('/home');
}
}
} else {
next('/login');
}
})
複製程式碼
以上僅為專案開發過程中的個人思路,如有更好的想法思路請在評論區留言,謝謝!