刚到新公司,领导交代给了一个新项目,就是很是简易的后台管理系统,后端因为是刚毕业的,因此没有用什么已经搭建好的后台管理系统的框架,好比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();
}
}
});
复制代码
才疏学浅,请各位大神多多指教,若是有哪里写的很差或者不详细的,请评论区留言数组