剛到新公司,領導交代給了一個新項目,就是很是簡易的後臺管理系統,後端因爲是剛畢業的,因此沒有用什麼已經搭建好的後臺管理系統的框架,好比renren-fast啥的,後端都沒有用,我天然只能陪他一點點的從新寫,恰好我對這一塊也不熟,正好用來練練手,學習一下,如下就是我本次開發總結的一點體會,記錄一下。本文以思路爲主,不會寫出所有代碼javascript
首先仍是後臺管理系統的基礎工做,登陸,側邊欄,導航欄什麼的,由於給的時間實在太緊,我就直接用的網上已經有的基礎框架 vue-admin-template 的,這些東西也不必重複寫,直接用現成的就好,主要仍是總結一下權限相關。前端
由於 vue-admin-template 框架中,側邊欄是根據路由生成的,因此咱們只要用一個菜單表維護路由就好了,不須要單獨再搞一個側邊欄管理,爲了知足渲染路由所必須的參數,咱們須要告訴後端咱們都須要什麼參數,通常狀況下,具備必定開發經驗的後端都知道要返回什麼參數,但若是對方碰巧沒啥經驗,咱們就要主動提出來了。vue
字段 | 含義 | 備註 |
---|---|---|
title | 標題 | 用於側邊欄標題展現 |
icon | 圖標 | 用於側邊欄圖標展現 |
type | 類型 | 區分目錄/菜單/按鈕 |
parentId | 父級id | 記錄父子關係 |
name | 路由name | 路由必備 |
path | 地址 | 地址欄的地址,用於跳轉和展現 |
url | 模塊路徑 | 模塊位於文件夾的路徑 |
identification | 受權標識 | 用於權限判斷,常見格式 crm:customer:list |
hidden | 是否渲染在側邊欄 | 有一些路由咱們須要能夠訪問,又不想讓它出如今側邊欄 |
*以上僅列出咱們所必須的字段,像建立時間,建立人,排序等能夠與後端協商按需求添加java
菜單表搞好以後,咱們就能夠開始開發角色列表,角色列表無非就是增刪查改,這裏僅記錄本身碰到的幾個小知識點。node
大部分後臺管理系統都是用的element-ui,而菜單展現通常會用element的el-tree組件,由於渲染路由的時候,須要有父子結構,我這裏保存的時候會把選中的節點this.$refs.menuListTree.getCheckedKeys()
和半選中的節點this.$refs.menuListTree.getHalfCheckedKeys()
都保存下來git
由於保存的時候半選中的節點也給保存了下來,回顯的時候若是給半選中的節點選中,它的子節點也會所有選中,若是要解決這個問題,咱們只須要判斷該節點是不是子節點就能夠了github
let menuId = res.data.menuId // 後端返回的id字符串 '1,3,4,5,8,9'
let _arr = menuId.split(",").map(item => {
return +item; // 用加號是由於字符串分割的數組每一項都是字符串,須要轉成數字
});
_arr.map(item => {
//獲取該id對應的tree節點
let node = this.$refs.menuListTree.getNode(item);
//判斷該節點是不是子節點(即該節點是不是末級節點),是的話就設置選中狀態
if (node.isLeaf) {
this.$refs.menuListTree.setChecked(node, true);
}
});
複製代碼
前端作權限,主要靠的就是操做路由,這一塊想了很久,事實證實,好記性不如賴筆頭,想半天想不明白,寫下來一下子就搞明白了。element-ui
這裏貼上個人代碼,裏面註釋了一些遇到的小難點後端
router.beforeEach(async (to, from, next) => {
// vue-admin-template自帶的進度條
NProgress.start();
// 設置瀏覽器標籤標題
document.title = getPageTitle(to.meta.title);
// 獲取token
const hasToken = getToken();
if (hasToken) {
if (to.path === "/login") {
// 若是已經登陸,重定向至首頁
next({ path: "/" });
NProgress.done();
} else {
const hasGetUserInfo = store.getters.name;
if (!hasGetUserInfo) {
try {
// 若是沒有用戶信息則獲取用戶信息
await store.dispatch("user/getInfo");
} catch (error) {
// 獲取用戶信息失敗則清除token並跳轉至首頁
await store.dispatch("user/resetToken");
Message.error(error || "獲取用戶信息失敗");
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
// 判斷是否已經加載路由或者是否要訪問白名單內的頁面
if (
router.options.isAddDynamicMenuRoutes ||
whiteList.indexOf(to.path) !== -1
) {
next();
} else {
// 獲取用戶權限信息及菜單列表
menuApi
.getListById({ id: store.getters.userId })
.then(res => {
console.log(res);
let menuList = res.data.menuList;
let permissions = res.data.permission;
// 我這裏是後端返回全部的菜單,而後前端根據權限篩選出有權限的菜單
// 篩選出有權限的路由或者是目錄
menuList = menuList.filter(item => {
return (
permissions.indexOf(item.identifying) > -1 ||
item.parentId === 0
);
});
// 將數據轉化成路由結構
menuList.map(item => {
if (item.parentId === 0) {
item.component = Layout;
} else {
item.component = _import(item.url);
}
item.meta = {
title: item.title,
icon: item.icon
};
});
// 將路由轉換成父子結構
menuList = treeDataTranslate(menuList);
console.log(menuList);
menuList = menuList.filter(item => {
return item.children;
});
// 在添加完動態路由以後再添加404路由,以防止頁面在匹配動態路由以前先匹配404
menuList.push({ path: "*", redirect: "/404", hidden: true });
router.options.isAddDynamicMenuRoutes = true;
router.addRoutes(menuList);
// this.$router不是響應式的,因此手動將路由元注入路由對象
router.options.routes.push(...menuList);
// 下面這個我也不知道爲何要加,可是我知道不加刷新就會404😅
if (from.name == null) {
next(to);
} else {
next();
}
})
.catch(err => {
console.log(err);
next(`/login?redirect=${to.path}`);
});
}
}
} 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();
}
}
});
複製代碼
才疏學淺,請各位大神多多指教,若是有哪裏寫的很差或者不詳細的,請評論區留言數組