總結一下最近學習的後臺管理系統的前端權限設計

剛到新公司,領導交代給了一個新項目,就是很是簡易的後臺管理系統,後端因爲是剛畢業的,因此沒有用什麼已經搭建好的後臺管理系統的框架,好比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();
    }
  }
});
複製代碼

才疏學淺,請各位大神多多指教,若是有哪裏寫的很差或者不詳細的,請評論區留言數組

相關文章
相關標籤/搜索