其中后端代码不包含权限控制,同时支持二级(无子菜单) 和 三级菜单(无子菜单)。
1、layui前端代码:(其他前端框架实现方法通用,不过需要修改js中append对应标签元素即可)
1 <div class="layui-side layui-bg-black"> 2 <div class="layui-side-scroll"> 3 <!-- 左侧导航区域(可配合layui已有的垂直导航) --> 4 <ul class="layui-nav layui-nav-tree" id="chuizhi" lay-filter="test"></ul> 5 </div> 6 </div> 7 8 <div class="layui-body"> 9 <!-- 内容主体区域 --> 10 <iframe name="iframe" src="/test/welcome" width="100%" height="100%" 11 frameborder="no" border="0" scrolling="auto"></iframe> 12 </div> 13 14 <div class="layui-footer"> 15 <!-- 底部固定区域 --> 16 © myzy.cn - 17 </div> 18 19 <script> 20 21 function isArrayFn(value){//用于判断对象是否为数组. 22 if (typeof Array.isArray === "function") { 23 return Array.isArray(value); 24 }else{ 25 return Object.prototype.toString.call(value) === "[object Array]"; 26 } 27 } 28 //JavaScript代码区域 29 layui.use(['form', 'layedit','element', 'layer','laydate','table'], function(){ 30 var table = layui.table 31 ,element = layui.element 32 ,form = layui.form 33 ,layer = layui.layer 34 ,layedit = layui.layedit 35 ,laydate = layui.laydate 36 ,$ = layui.jquery; 37
38 39 //动态渲染树形菜单 40 $.post("/todo/treeData", function (data){//请求后端返回对应json 41 var menu1 = [];//所有一级菜单名称数组 42 for (var key in data) { 43 menu1.push(key); 44 } 45 var len = menu1.length; 46 for(var i=0;i<len;i++){ 47 $("#chuizhi").append(`<li class="layui-nav-item"><a href="javascript:;">${menu1[i]}</a> 48 <dl class="layui-nav-child ${menu1[i]}"> 49 </dl></li>`);//一级菜单(有子菜单) 50 let ss = data[menu1[i]]; 51 if(isArrayFn(ss)){ 52 for(let j=0;j<ss.length;j++){ 53 $("."+menu1[i]).append(`<dd class="twoMenu"><a href="${ss[j].url}" target="iframe"> ${ss[j].name}</a></dd>`);//只到(没有子菜单)二级菜单 54 } 55 }else{ 56 let arr = []; 57 for(var key in ss){ 58 arr = ss[key]; 59 $("."+menu1[i]).append(`<li class="layui-nav-item twoMenu"><a href="javascript:;"> ${key}</a> 60 <dl class="layui-nav-child ${key}"> 61 </dl></li>`);//二级菜单(有子菜单) 62 for(let j=0;j<arr.length;j++){ 63 $("."+key).append(`<dd><a href="${arr[j].url}" target="iframe"> ${arr[j].name}</a></dd>`);//只到(没有子菜单)三级菜单 64 } 65 } 66 } 67 } 68 element.render();//element.init();//全部更新,用于动态渲染之后的挂载 (2) 69 /**用于菜单显示效果:点击其他菜单,原来打开的菜单自动关闭*/ 70 $(".twoMenu,#chuizhi>li").on("click",function () { 71 if(!$(this).hasClass("layui-nav-itemed")){ 72 $(this).removeClass("layui-nav-itemed"); 73 if($(this).children().children().hasClass("layui-nav-itemed")){ 74 $(this).children().children().removeClass("layui-nav-itemed"); 75 } 76 }else if($(this).hasClass("layui-nav-itemed")){ 77 $(this).addClass("layui-nav-itemed"); 78 $(this).siblings().removeClass("layui-nav-itemed"); 79 if(!$(this).children().children().hasClass("layui-nav-itemed")){ 80 $(this).children().children().removeClass("layui-nav-itemed"); 81 } 82 } 83 }) 84 85 }) 86 }); 87 </script>
2.java后端代码:用于返回给前端 菜单(json) 数据
1 @Override//其中menu_duidMapper为装载的dao层接口 2 public Map<String, Object> queryJsonMenus() { 3 Map<String, Object> mapR = new LinkedHashMap<String, Object>(); 4 //Map<String,Map<String,List<Map<String,String>>>> mapSan = new LinkedHashMap<>();//前端三级菜单json在后端表现形式 5 //Map<String,List<Map<String,String>>> mapTwo = new LinkedHashMap<>();//前端二级菜单json在后端表现形式 6 List<String> oneLevelMenuId = menu_duidMapper.selectGoodsMenuIdOneJ();//一级菜单id 7 List<String> TwoLevelPId = menu_duidMapper.selectGoodsParentIdTwoJ(); //二级菜单fuid 8 List<String> grandIdThreeJ = menu_duidMapper.selectGoodsGrandIdThreeJ();//三级菜单祖父id 9 String oneName = null; 10 String twoName = null; 11 List<Map<String,String>> msp = null; 12 List<String> threePid = null; 13 for(String oneMid : oneLevelMenuId){ 14 Map<String,List<Map<String,String>>> mapTwo = new LinkedHashMap<>();//这里不可以使用单例,所以只能生命在for循环内部 15 for(String erPid : TwoLevelPId){ 16 if(oneMid.equals(erPid)){ 17 oneName = menu_duidMapper.selectGoodsTypeByMenuId(oneMid);//根据一级菜单menuid查询对应名称 18 msp = menu_duidMapper.selectGoodsMapByPid(erPid);//根据二级菜单父id查找对应二级map 19 mapR.put(oneName,msp);//填充一级菜单对应的二级菜单(无子菜单) 20 }else{ 21 continue; 22 } 23 } 24 for(String sanGpid : grandIdThreeJ){ 25 if(oneMid.equals(sanGpid)){ 26 oneName = menu_duidMapper.selectGoodsTypeByMenuId(oneMid);// 27 threePid = menu_duidMapper.selectGoodsParentIdThreeJByGrandId(sanGpid);//根据祖父id查询父id并去重 28 for(String tpid : threePid){ 29 msp = menu_duidMapper.selectGoodsMapByPidAndGpid(tpid,sanGpid);//根据祖父id和父id查询对应map 30 twoName = menu_duidMapper.selectGoodsTypeByMenuId(tpid);//根据三级菜单父id查询对应二级菜单 31 //System.out.println(twoName); 32 mapTwo.put(twoName,msp);//填充二级菜单(有子菜单)和对应三级菜单(物资菜单) 33 } 34 mapR.put(oneName,mapTwo);//填充一级菜单所对应的二(有子菜单)三(无子菜单)级菜单 35 }else{ 36 continue; 37 } 38 } 39 } 40 return mapR; 41 }
3.数据库表结构
1 DROP TABLE IF EXISTS `menu_duid`; 2 CREATE TABLE `menu_duid` ( 3 `id` int(11) NOT NULL AUTO_INCREMENT, 4 `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, 5 `menu_id` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单id', 6 `parent_id` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '菜单父id', 7 `grand_pid` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '菜单爷爷id', 8 `url` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单路径', 9 `romaker` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', 10 PRIMARY KEY (`id`) USING BTREE 11 ) ENGINE = InnoDB AUTO_INCREMENT = 96 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
4.ajax返回的json数据格式为
1 { 2 "新闻资讯":{ 3 "企业新闻":[ 4 { 5 "menuID":"010101", 6 "name":"xxx", 7 "url":"/test/petroleum010101" 8 }, 9 { 10 "menuID":"010102", 11 "name":"xxx", 12 "url":"/test/mAsphalt010102" 13 } 14 ], 15 "行业新闻":[ 16 { 17 "menuID":"010201", 18 "name":"xxx", 19 "url":"/test/petroleum010201" 20 }, 21 { 22 "menuID":"010202", 23 "name":"xxx", 24 "url":"/test/mAsphalt010202" 25 } 26 ] 27 }, 28 "行业报告":{ 29 "日报":[ 30 { 31 "menuID":"020101", 32 "name":"xxx", 33 "url":"/test/petroleum020101" 34 }, 35 { 36 "menuID":"020102", 37 "name":"xxx", 38 "url":"/test/mAsphalt020102" 39 } 40 ], 41 "周报":[ 42 { 43 "menuID":"020201", 44 "name":"xxx", 45 "url":"/test/petroleum020201" 46 }, 47 { 48 "menuID":"020202", 49 "name":"xxxx", 50 "url":"/test/mAsphalt020202" 51 } 52 ], 53 "月报":[ 54 { 55 "menuID":"", 56 "name":"xxx", 57 "url":"/test/petroleum020301" 58 }, 59 { 60 "menuID":"", 61 "name":"xxx", 62 "url":"/test/mAsphalt020302" 63 } 64 ], 65 "年报":[ 66 { 67 "menuID":"", 68 "name":"xxx", 69 "url":"/test/petroleum020401" 70 }, 71 { 72 "menuID":"", 73 "name":"xxx", 74 "url":"/test/mAsphalt020402" 75 } 76 ] 77 }, 78 "政策法规":[ 79 { 80 "menuID":"", 81 "name":"xxx", 82 "url":"/test/petroleum0301" 83 }, 84 { 85 "menuID":"", 86 "name":"xxx", 87 "url":"/test/mAsphalt0302" 88 } 89 ] 90 }
5.对应查询的sql语句省略,这个比较简单,只用到了普通查询和几个子查询。。。。