总结一下最近学习的后台管理系统的前端权限设计

刚到新公司,领导交代给了一个新项目,就是很是简易的后台管理系统,后端因为是刚毕业的,因此没有用什么已经搭建好的后台管理系统的框架,好比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();
    }
  }
});
复制代码

才疏学浅,请各位大神多多指教,若是有哪里写的很差或者不详细的,请评论区留言数组

相关文章
相关标签/搜索