• 通用后台管理系统UI模板-AdminLTE简介及构造动态菜单栏


    AdminLTE是一款基于bootstrap的后台管理系统的通用模板UI,它的样式美观且较为符合大多数后台管理系统的需求,典型的上|左右|下的布局形式。并且提供了一整套我们开发的时候可能用到的UI样式,比如表格,表单,图表,日历等。非常适合像我这样对样式编排不太擅长的后端开发者。有了它,我们可以不用自己去写很多复杂的html,css。而把更多时间和精力留在后台的开发上。

    话不多说,接下来我简要的介绍一下这款模板UI框架的用法。

    官网:https://adminlte.io/

    该款框架是免费的,可以直接在官网下载,下载下来的文件大概有50多兆,包含了所有的html,css,js,还有很多的demo。可供我们随时查阅学习。

    先来看看整体的UI的风格吧,是不是挺炫酷的。

    可以说几乎所有的后台需要用到的样式都可以从中寻找得到。

    由于全套的UI都是静态数据,所以本篇文章着重介绍一下如何动态构造左侧的菜单栏。这应该也是大家比较关心的问题。

    所谓的动态就是指的是从数据库或者文件,或者内存中取到的数据。

    本人习惯将菜单的数据写成一个静态的js文件,放在项目的js目录中,这样做的好处是不必每次都去从数据库请求,减少IO操作造成的性能和时间损失,当然你也可以从数据库去请求,甚至把菜单数据放入到redis等内存数据库。各类方法都不影响我们前端代码的编写,因为传递的数据格式都是json.

    1.将菜单数据写入一个json文件,代码如下。该文件的路径为webapp/static/json/menu.json。

    [{
    "menuId":"1",
    "name": "基本信息",
    "controller":"#",
    "child": []
    },{
    "menuId":"2",
    "name": "会员管理",
    "controller":"#",
    "child": [{
    "menuId":"3",
    "pMenuId":"2",
    "name": "会员概览",
    "controller":"user/home"
    },{
    "menuId":"4",
    "pMenuId":"2",
    "name": "添加会员",
    "controller":"user/add"
    }]
    },{
    "menuId":"5",
    "name": "销售管理",
    "controller":"#",
    "child": [{
    "menuId":"5",
    "pMenuId":"6",
    "name": "销售返佣",
    "controller":"post/home"
    },{
    "menuId":"5",
    "pMenuId":"7",
    "name": "销售报表",
    "controller":"post/add"
    }]
    }]

    至于如何写入到文件,我们可以在每次修改菜单以后,先获取菜单的json数据,然后调用如下代码来将菜单的json数据写入文件。

        public void generateMenuJson(String jsonStr) {
            try {
                File f = new File(ServletActionContext.getServletContext()
                        .getRealPath("/static/json") + "/menu.json");
                if (!f.exists()) {
                    f.createNewFile();
                }
                // 定义编码
                OutputStreamWriter write = new OutputStreamWriter(
                        new FileOutputStream(f), "UTF-8");
                BufferedWriter writer = new BufferedWriter(write);
                writer.write(jsonStr);
                writer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    2.前台ajax获取json数据,并且动态构造出html元素及样式。

    主要是用了jQuery ajax异步获取数据,还有就是jquery的append()方法,代码没有什么高深的,只是拼接的时候要很认真。一个取巧的方法是去下载下来的html源码中复制一些关键的代码,避免写错。

     1 $(function () {
     2     $.ajax({
     3         type: 'get',
     4         url:'static/json/menu.json',
     5         dataType:'json',
     6         success:function(data){
     7             var menu=null;
     8             var html=null;
     9             var childLen=null;
    10             var child=null;
    11             var json=data;
    12             console.log(json);
    13             for(var i in json){
    14                 menu=json[i];
    15                 //这里默认展开第一个主菜单
    16                 if(i==0){
    17                     html=$('<li menu-id="'+i+'" class="active treeview "><li>');
    18                 }else{
    19                     html=$('<li menu-id="'+i+'" class="treeview "><li>');
    20                 }
    21                 $(".sidebar .sidebar-menu").append(html);
    22                 html=$('<a href="'+menu.controller+'"><i class="fa fa-dashboard"></i> <span>'+menu.name+'</span><span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a><ul menuUL-id="'+i+'" class="treeview-menu"></ul>');
    23                 $('[menu-id="'+i+'"]').append(html);
    24                 //继续遍历二级菜单
    25                 childLen=menu.child.length;
    26                 for(var j in menu.child){
    27                     child=menu.child[j];
    28                     //这里默认设置第一个子菜单为选中状态
    29                     if(j==0){
    30                             html=$('<li class="active"><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>');
    31                     }else{
    32                             html=$('<li><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>');
    33                     }            
    34                     $('[menuUL-id="'+i+'"]').append(html);
    35                 }
    36             }
    37         }
    38     
    39 });
    40 });

    相信大家对照demo中的html源码,可以很容易的理解上述代码。我们把原来的左侧菜单的静态html注释掉,引入上述的js文件。看看效果。

    这样基本实现了菜单显示的效果。但是还有一个缺点,就是菜单不能根据页面动态变换样式,比如我们在会员概览页面,此时展开的是会员管理,选中的是会员概览。而当我们到了销售管理的时候,我们又希望此时菜单能展开销售管理主菜单并选中相应的子菜单。

    要实现这个功能,我们需要在上述的js代码中传入当前访问的链接的菜单id,以及其父级菜单id(如果是最上层的菜单,则其父菜单为自己)。然后根据这两个参数来进行菜单是否展开即是否选中的判断。具体步骤如下。

    1.菜单实体如下

    package com.wonyen.entity;
    
    public class TMenu {
        private int menuId;//菜单编号
        private int pMenuId;//父菜单编号
        private String name;//菜单名称
        private String controller;//菜单对应的controller
        public int getMenuId() {
            return menuId;
        }
        public void setMenuId(int menuId) {
            this.menuId = menuId;
        }
    public int getpMenuId() { return pMenuId; } public void setpMenuId(int pMenuId) { this.pMenuId = pMenuId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getController() { return controller; } public void setController(String controller) { this.controller = controller; } }

    2.获取当前菜单对象,并传入到前台。以会员概览页面为例,代码如下。第8行获取了当前的菜单对象,第9行将其传入到ModelAndView对象中,我们就可以在转发的jsp页面中拿到这个menu对象了。

     1     @RequestMapping("partnerHome")
     2     public ModelAndView partnerHome(ParamModel pm) {
     3         ModelAndView mv = new ModelAndView("back/partner/PartnerList");
     4         mv.addObject("pm", pm);
     5         List<TPartnerLevel> partnerLevelList = partnerLevelService
     6                 .getPartnerLevelList();
     7         mv.addObject("partnerLevelList", partnerLevelList);
     8         TMenu menu=menuService.getMenuByController("partnerHome");//获取当前的菜单信息
     9         mv.addObject("menu", menu);
    10         return mv;
    11     }

    3.在每个页面body加入两个属性,menu_id和p_menu_id.如下所示。

    <body class="hold-transition skin-red sidebar-mini" menu_id="${menu.menuId}" p_menu_id="${menu.pMenuId}">

    4.重新改写原来js代码,让其支持根据当前页面来变换选中的菜单。

    $(function () {
        var menu_id=$('body').attr('menu_id');//菜单id
        var p_menu_id=$('body').attr('p_menu_id');//父级菜单id
        $.ajax({
            type: 'get',
            url:'static/json/menu.json',
            dataType:'json',
            success:function(data){
                var menu=null;
                var html=null;
                var childLen=null;
                var child=null;
                var json=data;
                console.log(json);
                for(var i in json){
                    menu=json[i];
                    //如果父菜单是该菜单,就展开
                    if(menu.menuId==p_menu_id){
                        html=$('<li menu-id="'+i+'" class="active treeview "><li>');
                    }else{
                        html=$('<li menu-id="'+i+'" class="treeview "><li>');
                    }
                    $(".sidebar .sidebar-menu").append(html);
                    html=$('<a href="'+menu.controller+'"><i class="fa fa-dashboard"></i> <span>'+menu.name+'</span><span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a><ul menuUL-id="'+i+'" class="treeview-menu"></ul>');
                    $('[menu-id="'+i+'"]').append(html);
                    //继续遍历二级菜单
                    childLen=menu.child.length;
                    for(var j in menu.child){
                        child=menu.child[j];
                        //如果子菜单是该菜单,则设为active选中
                        if(child.menuId==menu_id){
                                html=$('<li class="active"><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>');
                        }else{
                                html=$('<li><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>');
                        }            
                        $('[menuUL-id="'+i+'"]').append(html);
                    }
                }
            }
        
    });
    });

    经过上述步骤以后,我们就可以得到更为合理的左侧菜单了。来看看效果吧。

    --会员概览页

    ---会员添加页

    看,已经实现了我们想要的效果。如果你也正在寻找一个后台的UI,赶紧试试吧。

    -----------------------------------------------------------------------------------------------2018年4月2日更新-------------------------------------------------------------------------------------------------------------------------------------------------------------------

    最近发现一种新的记录菜单选中情况的方法,就是利用浏览器的缓存,每次点击菜单的时候,将点击的菜单Id记录到浏览器缓存中,然后加载菜单的时候通过缓存中的菜单来比对,匹配成功就将其展开并且设为active.这种方法就不需要在服务端传入当前的菜单了,简单了很多。

     1 $(function () {
     2     var firstLvId=getFirstLvMenu();//一级菜单
     3     var secondLvId=getSecondLvMenu();//二级菜单
     4     var thirdLvId=getThirdLvMenu();//三级菜单
     5     $.ajax({
     6         type: 'get',
     7         url:'/menu/tree',
     8         dataType:'json',
     9         success:function(data){
    10             var menu=null;
    11             var html=null;
    12             var childLen=null;
    13             var child=null;
    14             var json=data;
    15             console.log(json);
    16             for(var i in json){
    17                 menu=json[i];
    18                 //如果父菜单是该菜单,就展开
    19                 if(menu.menuId==firstLvId){
    20                     html=$('<li menu-id="'+i+'" class="active treeview "><li>');
    21                 }else{
    22                     html=$('<li menu-id="'+i+'" class="treeview "><li>');
    23                 }
    24                 $(".sidebar .sidebar-menu").append(html);
    25                 html=$('<a class="first-menu" href="../'+menu.menuSrc+'" onclick="saveFirstLvMenu('+menu.menuId+')"><i class="fa fa-dashboard"></i> <span>'+menu.menuName+'</span><span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a><ul menuUL-id="'+i+'" class="treeview-menu"></ul>');
    26                 $('[menu-id="'+i+'"]').append(html);
    27                 //继续遍历二级菜单
    28                 childLen=menu.child.length;
    29                 for(var j in menu.child){
    30                     child=menu.child[j];
    31                     //如果子菜单是该菜单,则设为active选中
    32                     if(child.menuId==secondLvId){
    33                             html=$('<li class="active"><a class="second-menu" href="../'+child.menuSrc+'" onclick="saveSecondLvMenu('+child.menuId+')"><i class="fa fa-circle-o"></i>'+child.menuName+'</a></li>');
    34                     }else{
    35                             html=$('<li><a class="second-menu" href="../'+child.menuSrc+'" onclick="saveSecondLvMenu('+child.menuId+')"><i class="fa fa-circle-o"></i>'+child.menuName+'</a></li>');
    36                     }            
    37                     $('[menuUL-id="'+i+'"]').append(html);
    38                 }
    39             }
    40         }
    41     
    42 });
    43 });
    44 function saveFirstLvMenu(menuId) {
    45     var id = JSON.stringify(menuId);
    46      window.sessionStorage.setItem("firstMenuId", id);
    47 }
    48 
    49 function saveSecondLvMenu(menuId) {
    50     var id = JSON.stringify(menuId);
    51      window.sessionStorage.setItem("secondMenuId", id);
    52 }
    53 
    54 function saveThirdLvMenu(menuId) {
    55     var id = JSON.stringify(menuId);
    56      window.sessionStorage.setItem("thirdMenuId", id);
    57 }
    58 
    59 function getFirstLvMenu() {
    60     return JSON.parse(window.sessionStorage.getItem("firstMenuId"));
    61 }
    62 function getSecondLvMenu() {
    63     return JSON.parse(window.sessionStorage.getItem("secondMenuId"));
    64 }
    65 function getThirdLvMenu() {
    66     return JSON.parse(window.sessionStorage.getItem("thirdMenuId"));
    67 }
  • 相关阅读:
    Ceph相关
    Redis学习
    docker mysql
    WebSocket学习与使用
    nginx学习与使用
    python学习小记
    基数计数——HyperLogLog
    Swagger使用小记
    理解Java枚举类型
    Jenkins使用
  • 原文地址:https://www.cnblogs.com/roy-blog/p/8280933.html
Copyright © 2020-2023  润新知