本文主要想对前端权限管理功能实现作一个分享,因此并不会对后台管理的框架结构作太详细介绍,若是有朋友对其余有兴趣能够留言。前端
打开思否页面,根据页面的功能点,设计出相关的数据表,和管理系统须要的相关页面。
计划后台管理须要完成的功能:vue
模块 | 功能 | 页面编码 | 描述 |
---|---|---|---|
登陆 | 登陆 | login | 菜单中不显示 |
401 | 401 | 401 | 角色无访问权限时进入这个页面 |
404 | 404 | 404 | 访问菜单不存在时进入这个页面 |
首页 | 首页 | home | |
运维中心 | opsCenter | ||
- | 问答管理 | questionMan | |
- | 专栏管理 | blogMan | |
- | 文章管理 | articleMan | |
- | 讲堂管理 | liveMan | |
- | 活动管理 | activityMan | |
- | 广告位 | advertising | |
工做流 | workflow | ||
- | 流程设计 | processDesign | |
- | 业务管理 | businessMan | |
- | 已办事项 | finishedItems | |
- | 未办事项 | unfinishedItems | |
文件库 | library | ||
- | 图片管理 | imgMan | |
- | 文件管理 | fileMan | |
论坛配置 | bbsConfig | ||
- | 轮播 | carousel | |
- | 技术频道 | techSquare | |
- | 通知 | notices | |
- | 标签类型管理 | tagTypeMan | |
- | 标签管理 | tagMan | |
系统管理 | sysMan | ||
- | 用户管理 | userMan | |
- | 角色管理 | roleMan | |
- | 菜单管理 | menuMan | |
- | 区域管理 | areaMan | |
- | 图表配置 | chartConfig | |
- | 系统日志 | log |
├── admin // 打包产出文件 ├── node_module // npm加载所需的项目依赖模块 ├── public // 静态入口 ├── src // 源代码 │ ├── api // 全部请求 │ ├── assets // 主题 字体 图片等静态资源 │ ├── common // 全局公用配置 │ │ ├── config // 配置全局路由权限和错误捕获 │ │ ├── mixin // 一些vue公用的mixin │ │ ├── js // 编写公有的方法 │ │ └── style // 编写公有的样式 │ ├── components // 全局公用组件 │ ├── directive // 自定义指令 │ ├── router // 路由 │ ├── store // 全局 store管理 │ ├── views // view │ ├── App.vue // 入口页面 │ └── main.js // 入口 加载组件 初始化等 ├── static // 第三方不打包资源 ├── .babelrc // babel-loader 配置 ├── eslintrc.js // eslint 配置项 ├── .gitignore // git 忽略项 ├── vue.config.js // vue-cli@3.0+ 配置文件 └── package.json // package.json
进入正文,关于权限设计,围绕的是前端页面,可是会将前端和后端的逻辑都讲出来。node
看图中圈起来的地方,前端看到的逻辑是这样的:mysql
就是建立了一个用户,这个用户建立的用户以及建立用户建立的用户,均可以被当前建立者管理。nginx
经过这个逻辑,能够获得全部当前用户建立的子集,可是第一步有很大的问题,一旦用户数量巨大,这样查询会很慢。母目前只是为了功能实现,暂未考虑到性能方面,若是有好的方法,但愿指点。git
菜单设计的时候分为三个类型,管理平台,论坛,移动端,可是不必定会写完,感受一我的写好累呀~~~~
经过菜单又分还有默认布局组件和页面组件的区分,布局组件为layout,页面组件则为他的子路由,经过嵌套的形式,组成一个完整的页面。github
目前页面上都是经过右键点击树组件,进入操做,如图所示,能够对菜单进行增删改查操做。sql
菜单字段的定义和相关用处
字段定义是这样的:
看到图中有这些字段,对主要字段说明:
-- ---------------------------- -- bbs_menu -- ---------------------------- DROP TABLE IF EXISTS `bbs_menu`; CREATE TABLE `bbs_menu` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `pid` INT(11) DEFAULT '0', `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '菜单类型: 1. 管理平台菜单 2. BBS菜单 3. 移动端菜单', `code` VARCHAR(48) NOT NULL COMMENT '菜单编码', `name` VARCHAR(48) NOT NULL COMMENT '菜单名称', `component` tinyint(4) NOT NULL COMMENT '对应组件: -1. 根节点 1. 页面组件 2.默认布局 3456...扩展布局', `icon` VARCHAR(128) DEFAULT NULL COMMENT '菜单图标', `alias` VARCHAR(128) DEFAULT NULL COMMENT '别名', `redirect` VARCHAR(128) DEFAULT NULL COMMENT '重定向路径: 配置菜单编码或URL', `sort` INT(11) NOT NULL, `desc` VARCHAR(128) DEFAULT NULL, `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态: 0:停用,1:启用(默认为1)', `create_user` INT(11) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `update_user` INT(11) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `delete_user` INT(11) DEFAULT NULL, `delete_time` datetime DEFAULT NULL, `flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态: 0:删除,1:可用(默认为1)', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
id: '', // *惟一ID pid: '', // *父ID type: '', // *菜单类型 code: '', // *菜单编码 name: '', // *菜单名称 component: '', // *菜单组件 icon: '', // 菜单图标 redirect: '', // 重定向路径 sort: '', // *排序 desc: '', // 描述 status: 1 // *状态: 0:停用,1:启用(默认为1)'
有什么用处呢和好处呢,就我的而言,就是以为把路由表放在数据库,让项目更易于维护,在页面中经过一个匹配逻辑,能够将全部字段组装成为可使用的路由表:vue-cli
// 获得页面路径 function getPath (arr, child, code) { const pItem = arr.find(item => child.pid === item.id) // 当前元素还存在父节点, 且父节点不为根节点 if (arr.find(item => pItem.pid === item.id && item.pid > -1)) { getPath(arr, pItem, `${pItem.code}/${code}`) } else { return `${pItem.code}/${code}` } } // 对基础数据的处理 item.meta = {} item.meta.title = item.name item.meta.icon = item.icon item.meta.id = item.id // 使路由名字具备惟一性 item.name = item.name + index // 设置对应的页面路径 item.path = '/' + item.code // 设置页面对应的组件 对应组件: -1. 根节点 1. 页面组件 2.默认布局 3456...扩展布局 switch (item.component) { case -1: console.log('根节点,已通过滤掉了') break case 1: item.component = resolve => require([`@/views/${getPath(menu, item, item.code)}/index`], resolve) break case 2: item.component = Layout break default: item.component = resolve => require(['@/views/errorPage/401'], resolve) break }
经过这种方式,在设置页面权限的时候,只须要接口设置当前角色对应的菜单,用户查询的时候能获取到的就是当前分配给他的权限,将这个权限组装成路由表,便可。数据库
上面说的是菜单的配置,以及生成。而后和每一个页面相关的数据权限,须要点击到页面级别的菜单才能够访问到,如图:
选中一个菜单以后,能够对这个菜单添加数据权限的控制,好比添加,编辑,删除等操做。
主要是字段设计,因此对图中字段(开发人员录入)详细说明:
分配完权限以后,前端页面在对应的按钮或要操做的dom上,经过v-if 功能编码是否存在来设置操做权限的显示隐藏。
可是前端的显隐一旦用户绕过页面去访问接口便可,因此数据权限前端只是操做显隐,具体实现还在后端。
用户存在了,菜单和数据权限也配置好了,可是须要角色去将他们关联到一块儿。
这里设置的逻辑是一个用户只能绑定一个角色。
角色管理页面,仍是右键树组件,能够看到绑定用户的选项
一样是右键,能够开始对角色进行分配权限的操做
左边是页面的权限分配,选中页面以后,右边会出现数据权限的分配:
建立用户
建立菜单
建立角色
用户绑定角色,角色分配权限
完成