bootstrap后台管理系统前后台实现(含数据库)
系统版本更新
版本 |
说明 |
时间 |
V1.0.0 |
菜单管理、角色用户、系统用户管理、权限分配、根据用户角色权限动态加载菜单、密码修改、插件整合等,详见本文说明 |
20190701 |
V1.1.0 |
相对上一版本:
|
20190703 |
V1.2.0 |
相对上一版本: 1.将项目服务端重构为springboot+mybatis架构; 2.整合wangeditor编辑器; 3.新增两个demo示例方便后续复制粘贴式并最少改动代码方式开发; 4.新增文件管理(普通上传文件与wangeditor编辑器上传与文件访问统一控制器) |
20210714 |
V1.2.1 |
相对上一版本: 2.添加图片压缩处理; |
20210720 |
撰写本文档目的是让后续开发者在理解该系统架构的基础上遵循一定规范保持系统架构的合理性;同时也能够达到允许没有开发经验仅有web基础的入门开发者能够通过复制粘贴的方式仿照demo示例进行开发的目的。
目 录
1 案例调研与选取... 3
1.1 案例调研... 3
1.2 UI选取... 4
2 系统实现... 4
2.1 实现效果... 4
2.2 开发规范... 9
3 详细设计... 10
3.1 框架介绍... 10
3.2 代码说明... 11
3.3 数据库设计... 13
3.4 菜单管理... 13
3.5 权限管理/角色管理... 17
3.6 权限管理/权限分配... 18
3.7 权限管理/用户管理... 19
3.8 Demo示例... 19
3.9 文件管理... 20
4 延伸思考... 20
5 致谢! 20
6 文档说明... 21
7 参考文献... 21
- 案例调研与选取
- 案例调研
1)easyUI(No1)
图片
2)easyUI(No2)
图片
3)Bootstrap
图片
4)vue/iview
图片
以上四套UI框架对比分析,可以得出如下结论
结论:
easyUI功能完善,界面简洁友好,非常方便后端开发人员开发,是优秀的前端开源框架,尤其适合后台管理,但是非响应式,页面不会随屏幕大小而变化,美观方面(仁者见仁);
bootstrap是响应式开源框架,支持插件广泛,界面相对酷炫,美观方面(有目共睹),同样也非常适合管理平台的开发;
至于Vue和其它一些前端人员自己写的UI框架,必须要承认Vue是不错的开源框架,但是个人感觉对管理平台来说Vue增加了开发人员的学习成本、兼容性、美观等方面的调试成本,开发周期偏长,至于是否适合管理品台开发就……;
综上分析,对于管理平台开发建议选用easyUI或基于bootstrap搭建好的管理平台,本文选择基于bootstrap的管理平台进行说明。
- UI选取
经过调研,选取了一套业内好评率较高的UI(ace-master),
Ace是一个基于Twitter bootstrap3开发的后台模板。
GitHub Ace地址:https://github.com/bopoda/ace
Ace演示:http://ace.jeka.by/
主体界面如下:
此框架功能多多,详细功能请看演示。
- 系统实现
- 实现效果
- 登录
2)首页
3)以下是权限管理的具体模块
- 开发规范
下图为框架的三个区域,其中主面板区域采用为一个div(没有采用iframe设计),每个菜单的内容均会更新主面板区域,故在主面板区域内容需要遵循一定的规范:
- 建议每个一级菜单在一个包中,每个包中的二级菜单均为一个单独的控制器。建议页面也需按同样方式设计。
- 每个页面中的字段必须全局唯一(very import)
每个页面中的字段可采用驼峰式也可用下划线式,但必须确保每个页面以及下面多级页面中的每个字段名必须不同(即使业务上为同一张表的同一个字段),不可在模态框与主面板区用同一个页面。(如此设计的原因是:由于主页面采用div设计,故为防止js检测异常)
- (important)由于主面板区域采用div设计,父页面(main.jsp)中已经有了
<script src="view/manage/assets/js/jquery-2.1.4.min.js"></script>
故子页面面不要引入这个js了(也无需引入),否则会引起密码修改的模态框无法弹出;
如果想要引入的话,请修改密码修改的模态框弹出效果。
命名规范示例:
每个页面中字段命名(包括方法名、表单字段、div等元素的id等): 模块名+页面名+数据库字段名
示例:userManageListAccountName
或者 user_manage_list_account_name
这样组成了全局唯一字段,防止浏览器缓存导致的页面插件功能异常和表单提交异常等问题;
此问题已经在最新版本中修复
- 详细设计
- 框架介绍
1)页面布局
页面布局见开发规范中截图,三个主要区域。
2)功能
功能上主要为权限管理和其它的项目相关的开发人员自定义的菜单模块。前后端交互采用ajax技术,页面核心的公共区域的交互在
<script src="view/manage/assets/js-ylz/utils.js"></script> ;该文件中封装了菜单url调用和菜单效果切花、主面板区域更新的ajax、菜单树的动态加载、解析、拼装等功能。
3)权限
权限管理中包括用户管理、菜单管理、角色管理、权限分配和密码修改。
4)菜单加载
用户状态为启用时可登录到系统,进入到主板面后根据用户对应角色查找相应的菜单加载到菜单区域,从而实现不同角色的用户能够看到不同的菜单权限。
5)插件
框架中整合的插件主要如下(部分):
Bootstrap-table、bootstrap-datetimepicker、jquery.gritter(右上角弹框插件)、bootstrap-treeview、bootstrap-switch、jQuery.ui(确认框)。
其中datetimepicker样式似乎并没有想象中的好,需要进一步确认原因还是切换其它插件,如果对样式要求不高可临时使用,但考虑到后续扩展,故而建议尽快确认(修复or更换)。
- 代码说明
- 数据库设计
数据库中权限管理模块设计了用户表、角色表、菜单表、用户角色关联表、角色菜单关联表,共计5张表,sql代码详见数据库文件。
用户表:
角色表:
菜单表:
用户角色关联表:
角色菜单关联表:
- 菜单管理
菜单包括主页面菜单区域的菜单也包含“权限管理à菜单管理”中的菜单。
1)主页菜单封装:
菜单表设计,见数据库设计。
菜单最大设计四级菜单,拼装的json格式(下文为大致示例,以实际为准);
读取库中菜单信息,拼接采用何种算法?
方案一:循环遍历,多重循环遍历
方案二:递归
此处选择递归,原因一是效率高(内存需要或许也高,完全可容忍),二是不受限于菜单级别,
递归核心代码如下(详见源码)
/*** 递归查找子菜单* @param id* @param rootMenu* @return*/private List<Map> getChilds(Long id, List<SysMenu> rootMenu){// 子菜单List<Map> childList = new ArrayList<Map>();Iterator<SysMenu> it = rootMenu.iterator();while(it.hasNext()) {SysMenu menu = it.next();// 遍历所有节点,将父菜单id与传过来的id比较if (String.valueOf(menu.getLong("menu_pa_id")).equals(String.valueOf(id))){Map<String,Object> mapcc = new HashMap<String,Object>();mapcc.put("id", menu.getLong("id"));mapcc.put("menu_name", menu.getStr("menu_name"));mapcc.put("menu_url", menu.getStr("menu_url"));childList.add(mapcc);it.remove();}}// 把子菜单的子菜单再循环一遍for (Map map : childList) {//递归map.put("childMenus", getChilds(Long.parseLong(map.get("id").toString()), rootMenu));}//递归退出条件if (childList.size() == 0) {return null;}return childList;}拼接得到json菜单格式为(如下为二级菜单示例,其它详见源码、界面操作):{"status":"200","data":[{"id":1,"childMenus":null,"menu_url":"/manage/systemInfo.do","menu_name":"系统信息"},{"id":2,"childMenus":[{"id":5,"childMenus":null,"menu_url":"/redis/main.do","menu_name":"查询redis"},{"id":6,"childMenus":null,"menu_url":"/redis/writeRdisPage.do","menu_name":"写redis"}],"menu_url":null,"menu_name":"redis管理"},{"id":3,"childMenus":[{"id":7,"childMenus":null,"menu_url":null,"menu_name":"榴莲短视频"},{"id":8,"childMenus":null,"menu_url":"/haohuolab/haohuoPage.do","menu_name":"东龙实验室"}],"menu_url":null,"menu_name":"东龙实验室"},{"id":4,"childMenus":[{"id":9,"childMenus":null,"menu_url":"/system/users/userPages.do","menu_name":"用户管理"},{"id":10,"childMenus":null,"menu_url":null,"menu_name":"角色管理"},{"id":11,"childMenus":null,"menu_url":null,"menu_name":"权限分配"},{"id":12,"childMenus":null,"menu_url":null,"menu_name":"菜单管理"},{"id":13,"childMenus":null,"menu_url":"/manage/updatePwdPages.do","menu_name":"密码修改"}],"menu_url":null,"menu_name":"权限管理"}],"msg":"success"
}
2)菜单解析
上面是拼接菜单代码,下面是解析菜单代码:
解析菜单的时候踩了一个坑,就是二级菜单在浏览器端始终无法打开,反复调试到晚上十一二点始终不知道什么原因,第二天来了之后继续调试,最终发现是a标签上缺少了一个属性(class='dropdown-toggle'),有时可能就是很小的一个问题让你耽误很长很长的时间还弄的自己焦头烂额,深感有时阻碍你前进的可能不是那万里征程(搭建整套完善框架),却可能是脚下的一粒沙子。
废话少说,直接上递归核心代码(实际略有改动,详见源码):
/*** 递归遍历子树* @param list*/function mainPageRecurSubTree(ctx,list){if(null==list || ""==list || "null"==list){return "";}var mainPageRecurSubTreeStr = "";mainPageRecurSubTreeStr +="<ul class='submenu'>";for(var m=0;m<list.length;m++){var menuSub = list[m];mainPageRecurSubTreeStr +="<li class='' id='mainPageMenuTreeId"+menuSub.id+"'>"+"<a onclick=\"javascript:updateMenuTree('mainPageMenuTreeId"+menuSub.id+"','"+ctx+"','"+menuSub.menu_url+"');\" class='dropdown-toggle'>"+"<i class='menu-icon fa fa-caret-right'></i>"+menuSub.menu_name;if(null!=menuSub.childMenus && ""!=menuSub.childMenus && "null"!=menuSub.childMenus){mainPageRecurSubTreeStr +="<b class='arrow fa fa-angle-down'></b>";}mainPageRecurSubTreeStr +="</a>"+"<b class='arrow'></b>"+mainPageRecurSubTree(ctx,menuSub.childMenus)+"</li>";}mainPageRecurSubTreeStr +="</ul>";return mainPageRecurSubTreeStr;}
3)权限管理/菜单管理
菜单插件采用bootstrap-treeview插件,
开关按钮采用bootstrap-switch插件;注意:将所需的开关插件放入到main.jsp中,开关样式方可正常引用,否则如果放到每个功能模块的子页面中会导致插件无法完全加载而导致的样式显示的问题。
菜单管理页面中添加根菜单,也可添加子菜单,选择/修改菜单的上级菜单,修改菜单信息等功能。
- 权限管理/角色管理
权限管理à角色管理:
角色管理中的菜单权限修改(修改角色对应的菜单信息):
也采用了bootstrap-TreeView插件,但是此原生的树菜单没有级联选项,故添加级联选择的js,核心代码如下:
//级联选择:选中$("#roleManageUpdateRoleMenuAllTreeMes").on('nodeChecked',function(event,node){roleManageUpdateRoleMenuNodeChecked(event, node);;});//级联选择:取消选中$("#roleManageUpdateRoleMenuAllTreeMes").on('nodeUnchecked',function(event,node){roleManageUpdateRoleMenuNodeUnchecked(event, node);;});//如下是响应菜单选中和取消选中的操作var roleManageUpdateRoleMenuNodeCheckedSilent = false;function roleManageUpdateRoleMenuNodeChecked(event, node){if(roleManageUpdateRoleMenuNodeCheckedSilent){return;}roleManageUpdateRoleMenuNodeCheckedSilent = true;roleManageUpdateRoleMenuCheckAllParent(node);roleManageUdpateRoleMenuCheckAllSon(node);roleManageUpdateRoleMenuNodeCheckedSilent = false;}var roleManageUpdateRoleMenuNodeUncheckedSilent = false;function roleManageUpdateRoleMenuNodeUnchecked(event, node){if(roleManageUpdateRoleMenuNodeUncheckedSilent){return;}roleManageUpdateRoleMenuNodeUncheckedSilent = true;roleManageUpdateRoleMenuUncheckAllParent(node);roleManageUpdateRoleMenuUncheckAllSon(node);roleManageUpdateRoleMenuNodeUncheckedSilent = false;}//选中全部父节点function roleManageUpdateRoleMenuCheckAllParent(node){$("#roleManageUpdateRoleMenuAllTreeMes").treeview('checkNode',node.nodeId,{silent:true});var parentNode = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getParent',node.nodeId);if(!("nodeId" in parentNode)){return;}else{roleManageUpdateRoleMenuCheckAllParent(parentNode);}}//取消全部父节点function roleManageUpdateRoleMenuUncheckAllParent(node){$("#roleManageUpdateRoleMenuAllTreeMes").treeview('uncheckNode',node.nodeId,{silent:true});var siblings = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getSiblings', node.nodeId);var parentNode = $("#roleManageUpdateRoleMenuAllTreeMes").treeview('getParent',node.nodeId);if(!("nodeId" in parentNode)) {return;}var isAllUnchecked = true; //是否全部没选中for(var i in siblings){if(siblings[i].state.checked){isAllUnchecked=false;break;}}if(isAllUnchecked){roleManageUpdateRoleMenuUncheckAllParent(parentNode);}}//级联选中所有子节点function roleManageUdpateRoleMenuCheckAllSon(node){$("#roleManageUpdateRoleMenuAllTreeMes").treeview('checkNode',node.nodeId,{silent:true});if(node.nodes!=null&&node.nodes.length>0){for(var i in node.nodes){roleManageUdpateRoleMenuCheckAllSon(node.nodes[i]);}}}//级联取消所有子节点function roleManageUpdateRoleMenuUncheckAllSon(node){$("#roleManageUpdateRoleMenuAllTreeMes").treeview('uncheckNode',node.nodeId,{silent:true});if(node.nodes!=null&&node.nodes.length>0){for(var i in node.nodes){roleManageUpdateRoleMenuUncheckAllSon(node.nodes[i]);}}}
- 权限管理/权限分配
权限管理à权限分配:为不同用户分配不同角色。
在权限分配è角色分配 页面中,使用了一个多选框的插件(用于选择多个角色),如下图:
在使用中发现这个选择框第一次打开时正常,之后再打开始终不正常,调试发现是因为select中动态添加了一个div并且这个div的style=“width:0px”;导致select的展示出现问题。试了各种方式,网上搜了各种方案均失败。最终万般无奈之下猜想可能是引用的js文件中生成这个内部div时导致宽度获取的问题,于是便修改引用的js源码,修改如下:
<script src="view/manage/assets/js/chosen.jquery.min.js"></script>
至此问题解决。
问:如何知道要修改这个宽度(如何定位到是要修改这个宽度的)?
答:在浏览器中调试时发现在select中生成的div的id是在select的id的基础之上添加了“_chosen”,于是搜索“_chosen”发现整个js源码中只有一个“_chosen”,于是在此附近寻找width相关的代码,终于发现了并尝试修改成功。
- 权限管理/用户管理
权限管理à用户管理:功能为对能够登录到系统的管理用户的增、查、修改、停用操作。
此页面中的table采用bootstrap原生表格,增改查的逻辑完全为自己实现。没有使用bootstrap-table插件。
本系统设计者建议使用bootstrap-table插件(why? 我也不知道,就是感觉成熟开源的业内小有名气的东东一定比自己写的好),插件demo见系统demo示例。
此模块中的用户为系统的管理人员。
- 文件管理
此项目将文件全部存储到了域项目同级目录下并提供文件访问的controller,这么设计的好处:1)避免因为项目发布导致文件误删;2)项目迁移同步拷贝文件即可,无需关心机器、地址等问题;
文件结构:
- 延伸思考
- Iframe为子页面,可不受父页面干扰,但是究竟用还是不用好,有待深思的问题;
- bootstrap-switch boostrap的开关按钮插件并未能初始化开或者关状态,此功能关乎开关的美观,需探究如何修改或选用其它插件待进一步深思。
3)系统待优化之处:
权限访问控制该如何优化(内存?redis?)
- 致谢!
初级入门:泽宇、老申、昊总
前端顾问:张走召
问题修复:金凤
问题修复:系统参与的全体java同仁
开发者:战神,彭玉,ylz,东龙;
零碎不重要的整理工作(高大上的名字:秘书):本人。
向以上四位开发者致敬!
- 文档说明
本文档由四位开发者在开发过程中心得记录,由秘书整理汇总而成。最终解释权归四位开发者所有。
- 参考文献
https://blog.csdn.net/weixin_41981080/article/details/81912941
文末福利:
想要与大家一起交流,可进企鹅群:589847567
群共享文件中有源码下载。
说明:该系统由以上四位开发者在工作之余抽时间分工开发完成,因工作较忙,时间有限等原因,系统中难免有瑕疵不足之处需进一步完善,望大家谅解,在后续版本中我们会不断完善。同时诚邀大才雄心的有志之士加入我们共同开发。
bootstrap后台管理系统前后台实现(含数据库)相关推荐
- bootstrap加载mysql数据库_bootstrap后台管理系统前后台实现(含数据库)
撰写本文档目的是让后续开发者在理解该系统架构的基础上遵循一定规范保持系统架构的合理性:同时也能够达到允许没有开发经验仅有web基础的入门开发者能够通过复制粘贴的方式仿照demo示例进行开发的目的. 目 ...
- Bootstrap后台管理系统收集
Bootstrap后台管理系统收集 bootstrap 8 一.框架整理 1.灰黑色后台框架 2.论如何把后台管理系统写出花(关于后台开发的相关技术) 3.最新的技术-Vue后台管理 4.AdminL ...
- java计算机毕业设计服装连锁店后台管理系统源码+mysql数据库+系统+lw文档+部署
java计算机毕业设计服装连锁店后台管理系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计服装连锁店后台管理系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目 ...
- java计算机毕业设计Vue框架电商后台管理系统源码+mysql数据库+系统+lw文档+部署
java计算机毕业设计Vue框架电商后台管理系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计Vue框架电商后台管理系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈 ...
- 多用途bootstrap后台管理系统模板企业统计管理界面模板
介绍: 基于bootstrap构建,响应式的电子商务后台管理系统ui页面模板. 适用于:电商销售统计.企业统计管理界面模板. 网盘下载地址: http://kekewl.net/yYrcYaCFVAU ...
- php图书管理系统源码(含数据库脚本)
别看他只是一个简单的图书管理系统,麻雀虽小,五张俱全,实现了常见字段比如字符串,整型,浮点型,日期型,图片型和文件型的添删改查,查询条件采用多条件组合模糊查询,查询结果都采用分页显示,其中字符串分为单 ...
- bootstrap后台模板_免费bootstrap后台管理系统模板源码 网站后台模板_后台管理界面...
Frogetor-响应式管理仪表板模板 Frogetor是一个Bootstrap 4管理仪表板,它具有充分的响应能力,并包括一些很棒的功能,可帮助您快速,轻松地构建Web应用程序.经过精心设计和开发的 ...
- 响应式Bootstrap后台管理系统模板UI框架
介绍: Ubold是一个功能齐全的优质管理模板基于Bootstrap框架之上,现代网络技术HTML5,CSS3和jQuery. 它有许多可以使用的组件. 主题是充分响应.易于定制,代码超级容易理解并将 ...
- 纯前端bootstrap后台管理系统
基于bootstrap+chart.js 5个页面 git地址:https://github.com/Simple3762/fist.git 觉得不错可以给个start
最新文章
- javascript 之反射
- 微信小程序button授权页面,用户拒绝后仍可再次授权
- java.io.EOFException: Chunk stream does not exist at page: 0
- (十三)真题模拟【告诉你答案是什么】
- Android SDK tools,platform-tools,build-tools 区别
- ios中strong和weak的解释理解
- Java程序设计实验2
- python图片压缩算法_Optipng,jpegoptim应用,用python实现图片压缩,让你的网站变得更快...
- 更新maven卡在18不动_Android Studio maven-metadata.xml 卡着不动原因和解决方法
- python实现七种方法去除列表中的重复元素
- 【预测模型】基于matlab GUI AR模型线性预测【含Matlab源码 942期】
- C 语言中 bzero()函数的使用
- 电脑博主fps测试软件,APP性能测试—帧率
- 免费下载百度文库需下载券文件
- 【附源码】计算机毕业设计JAVA大学生旅游拼团网站
- Android应用权限申请
- maven报错:Failure to transfer xxx.jar from xxx was cached in the local repository.
- 人在囧途之火车调研篇
- iOS应用的内测签名、分发托管平台:蒲公英内测分发平台简介
- [MSDN版本][32bit/64bit]Windows 2003 R2 With Sp2[中/英][标准/企业/数据中心]