1. 程式人生 > 實用技巧 >尚籌網04選單維護

尚籌網04選單維護

樹形結構基礎知識介紹

參考知識

選單維護:頁面顯示樹形結構

目標

將資料庫中查詢得到的資料到頁面上顯示出來.

思路

資料庫查詢全部-java物件組裝-》頁面上使用zTree顯示

程式碼:將資料在java程式碼中組裝成樹形結構

MenuExample

// 主鍵
private Integer id;
// 父節點
private Integer pid;
private String name;
private String url;
// 圖示樣式
private String icon;
// 儲存子節點的集合,初始化避免空指標異常
private List<Menu> children=new
ArrayList<>(); //控制節點預設狀態,true開啟 private Boolean open=true;

service方法

@Override
public List<Menu> getAll() {
    return menuMapper.selectByExample(new MenuExample());
}

Controller方法(構建二叉樹)

思路

  • 整體的思路是組裝二叉樹
  • 找到根節點
  • 為父節點新增子節點
@RequestMapping("/menu/get/whole/tree.json")
public ResultEntity<Menu> getWholeTreeNew(){
    
//1、查詢全部的Menu物件 List<Menu> menus = menuService.getAll(); //2、宣告一個變數用來儲存找到根節點 Menu root = null; //3、建立Map物件用來儲存id和Menu物件的對應關係便於查詢父節點 Map<Integer,Menu> menuMap = new HashMap<>(); //4、遍歷menuList填充menuMap for (Menu menu : menus) { Integer id = menu.getId(); menuMap.put(id,menu); }
//5、再次遍歷menuList查詢根節點、組裝父子節點 for (Menu menu : menus) { //6、獲取當前menu物件的pid屬性值 Integer pid = menu.getPid(); //7、如果pid為null,判定為根節點 if (pid == null){ root = menu; //8、如果當前節點是根節點,那麼繼續執行 continue; } //9、如果pid不為null,說明當前節點有父節點,那麼可以根據 //pid到menuMap中查詢對應的Menu物件 Menu father = menuMap.get(pid); //10、將當前節點存入父節點的children集合 father.getChildren().add(menu); } //11、經過上面的運算,根節點包含了整個樹形結構,返回根節點 return ResultEntity.sucessWithData(root); }

程式碼:跳轉頁面

<mvc:view-controller path="/menu/to/page.html" view-name="menu-page"/>

<%--//zTree引入--%>
<link rel="stylesheet" href="static/ztree/zTreeStyle.css"/>
<script type="text/javascript" src="static/ztree/jquery.ztree.all-3.5.min.js"></script>
<script src="static/commonjs/my-menu.js"></script>

程式碼:在頁面上使用真實資料

$.ajax({
    "url":"menu/get/whole/tree.json",
    "type":"post",
    "dataType":"json",
    "success":function (response) {
        var result = response.result;
        if (result == "SUCCESS"){
            // 建立json物件儲存zTree所做的設定
            var setting = {
                "view":{
                    //加圖示
                    "addDiyDom":myAddDiyDom,
                    "addHoverDom":myAddHoverDom,
                    "removeHoverDom":myRemoveHoverDom
                },
                "data":{
                    "key":{
                        "url":"maomi"
                    }
                }
            };
            var zNodes=response.data;
            // 初始化樹結構
            // ,不要寫成.
            $.fn.zTree.init($("#treeDemo"),setting,zNodes);
        }
        if (result == "FAILD"){
            layer.msg(response.message)
        }
    }
});

程式碼:修改預設圖示為真實圖示

//修改預設圖示
function myAddDiyDom(treeId,treeNode){
    //控制span標籤
        var spanId=treeNode.tId+"_ico";
    //刪除舊class
    //新增新的class
    $("#"+spanId)
        .removeClass()
        .addClass(treeNode.icon);
}

程式碼實現點了不跑

當點選時,zTree沒有找到maomi這個key就不會發送資料

程式碼:顯示按鈕組

思路步驟

  • 控制<span>A</span>是否顯示
  • 明確具體按鈕的新增規則
  • 準備好按鈕的html標籤
  • 根據按鈕規則把按鈕填充到span

myremoveHoverDom(treeId,treeNode)函式

//滑鼠移入範圍是刪除按鈕組
function myRemoveHoverDom(treeId,treeNode) {
    var btnGroupId=treeNode.tId+"_btnGrp";
    $("#"+btnGroupId).remove()
}

myAddHoverDom(treeId,treeNode)函式

//滑鼠移入範圍是新增按鈕組
function myAddHoverDom(treeId,treeNode) {
    //定id刪除的時候定位
    var btnGroupId=treeNode.tId+"_btnGrp";
    if ($("#"+btnGroupId).length>0){
        return;}
    //準備各個按鈕的HTML標籤onclick='showAddModal(this)'
    var addBtn="<a id='"+treeNode.id+"' class='addBtn btn btn-info dropdown-toggle btn-xs '  style='margin-left:10px;padding-top:0px;' href='#' title='新增許可權資訊'>&nbsp;&nbsp;<i class='fa fa-fw fa-plus rbg '></i></a>";
    var editBtn="<a id='"+treeNode.id+"' class='editBtn btn btn-info dropdown-toggle btn-xs ' style='margin-left:10px;padding-top:0px;' href='#' title='修改許可權資訊'>&nbsp;&nbsp;<i class='fa fa-fw fa-edit rbg '></i></a>"
    var removeBtn="<a id='"+treeNode.id+"' class='removeBtn btn btn-info dropdown-toggle btn-xs ' style='margin-left:10px;padding-top:0px;' href='#' title='刪除許可權資訊'>&nbsp;&nbsp;<i class='fa fa-fw fa-times rbg '></i></a>";
    // 獲取當前節點的級別資料
    var level=treeNode.level;
    var btnHTML="";
    //各級別不同操作,按鈕的不同
    if (level ==0){
        btnHTML=addBtn;}
    if (level ==1){
        btnHTML=addBtn+" "+editBtn+" "+removeBtn;
        var length=treeNode.children.length;
        if (length == 0){
            btnHTML =addBtn+" "+removeBtn;
        }
    }
    if (level ==2){
        btnHTML=editBtn+" "+removeBtn+" ";
    }
    var anchorId=treeNode.tId+"_a";
    $("#"+anchorId).after("<span id='"+btnGroupId+"'>"+btnHTML+"</span>")
}

程式碼:把生成樹形結構的程式碼封裝到函式

menu-page.jsp渲染時呼叫即可

$(function () {
    //呼叫專門封裝好的函式初始化樹形結構
    generateTree();
});

選單維護:新增子節點

目標

給當前節點新增子節點,儲存到資料庫並重新整理樹形結構的顯示

前端程式碼

//準備各個按鈕的HTML標籤onclick='showAddModal(this)'
var addBtn = "<a id='" + treeNode.id + "' class='addBtn btn btn-info dropdown-toggle btn-xs '  style='margin-left:10px;padding-top:0px;' href='#' title='新增許可權資訊'>&nbsp;&nbsp;<i class='fa fa-fw fa-plus rbg '></i></a>";
var editBtn = "<a id='" + treeNode.id + "' class='editBtn btn btn-info dropdown-toggle btn-xs ' style='margin-left:10px;padding-top:0px;' href='#' title='修改許可權資訊'>&nbsp;&nbsp;<i class='fa fa-fw fa-edit rbg '></i></a>"
var removeBtn = "<a id='" + treeNode.id + "' class='removeBtn btn btn-info dropdown-toggle btn-xs ' style='margin-left:10px;padding-top:0px;' href='#' title='刪除許可權資訊'>&nbsp;&nbsp;<i class='fa fa-fw fa-times rbg '></i></a>";

“+”按鈕繫結單機響應函式

//給新增子節點按鈕繫結單擊響應函式
$("#treeDemo").on("click", ".addBtn", function () {
    //將當前節點的id,作為新節點的pid儲存到全域性變數
    window.pid = this.id;
    //開啟模態框
    $("#menuAddModal").modal("show");
    return false;
});

給新增子節點的模態框中的儲存按鈕繫結單擊響應函式

$("#menuSaveBtn").click(function () {
    //收集表單項中使用者輸入的資料
    var name = $.trim($("#menuAddModal [name=name]").val());
    var url = $.trim($("#menuAddModal [name=url]").val());
    //單選按鈕要定位到"被選中"的那一個
    var icon = $("#menuAddModal [name = icon]:checked").val;

    //傳送ajax請求
    $.ajax({
        "url": "menu/save.json",
        "type": "post",
        "data": {
            "pid": window.pid,
            "name": name,
            "url": url,
            "icon": icon
        },
        "datatype": "json",
        "success": function (response) {
            alert(response);
            var result = response.result;
            if (response === "SUCCESS") {
                layer.msg("操作成功");
                // 重新載入樹形結構,
                // 注意:要在確認伺服器端完成儲存操作後再重新整理
                // 否則有可能重新整理不到最新的資料,因為這裡是非同步的
                generateTree();
            }
            if (result === "FAILED") {
                layer.msg("操作失敗" + response.message);
            }
        },
        "error": function (response) {
            layer.msg(response.status + " " + response.statusText)
        }
    });
    //關閉模態框
    $("#menuAddModal").modal("hide");
    //清空表單
    //JQuery物件呼叫click()函式,裡面不傳任何引數,相當於使用者點選一了下1
    $("#menuResetBtn").click();
});

後端程式碼

Controller

@RequestMapping("/menu/save.json")
public ResultEntity<String> saveMenu(Menu menu){
    menuService.saveMenu(menu);
    return ResultEntity.successWithoutData();
}

service程式碼

@Override
public void saveMenu(Menu menu) {
    menuMapper.insert(menu);
}

選單維護:更新節點

目標

修改當前節點的基本屬性.不更換父節點.

思路

前端程式碼

給編輯按鈕繫結單擊響應函式

//給編輯按鈕繫結單擊響應函式
$("#treeDemo").on("click", ".editBtn", function () {
    //將當前節點的id儲存到全域性變數
    window.id = this.id;

    //開啟模態框
    $("#menuEditModal").modal("show");

    //獲取zTreeObj物件
    var zTreeObj = $.fn.zTree.getZTreeObj("treeDemo");

    //根據id屬性查詢節點物件
    //用來搜尋節點的屬性名
    var key = "id";

    //用來搜尋節點的屬性值
    var value = window.id;

    var currentNode = zTreeObj.getNodeByParam(key, value);

    //回顯表單資料
    $("#menuEditModal [name=name]").val(currentNode.name);
    $("#menuEditModal [name=url]").val(currentNode.url);

    //回顯radio可以這樣理解:被選中的radio的value屬性可以組成一個數組
    //然後再用這個陣列設定回radio,就能夠把對應的值選中
    $("#menuEditModal [name=icon]").val([currentNode.icon]);
    return false;
});

//給更新模態框中的更新按鈕繫結單擊響應函式
$("#menuEditBtn").click(function () {
    //收集表單資料
    var name = $("#menuEditModal [name = name]").val();
    var url = $("#menuEditModal [name=url]").val();
    var icon = $("#menuEditModal [name=icon]:checked").val();

    //傳送ajax請求
    $.ajax({
        "url": "menu/update.json",
        "type": "post",
        "data": {
            "id": window.id,
            "name": name,
            "icon": url,
            "url": url,
            "icon": icon
        },
        "datatype": "json",
        "success": function (response) {
            var result = response.result;
            if (result === "SUCCESS") {
                layer.msg("操作成功");
                // 重新載入樹形結構,注意:要在確認伺服器端完成儲存操作後再重新整理
                // 否則有可能重新整理不到最新的資料,因為這裡是非同步的
                generateTree();
            }
            if (result === "FAILED") {
                layer.msg("操作失敗" + response.message);
            }
        },
        "error": function (response) {
            layer.msg(response.status + " " + response.statusText);
        }
    });
    //關閉模態框
    $("#menuEditModal").modal("hide");
});

後端程式碼

controller程式碼

@RequestMapping("/menu/update.json")
public ResultEntity<String> updateMenu(Menu menu){
    menuService.updateMenu(menu);
    return ResultEntity.successWithoutData();
}

service程式碼

@Override
public void updateMenu(Menu menu) {
    // 由於 pid 沒有傳入,一定要使用有選擇的更新,保證“pid”欄位不會被置空
    menuMapper.updateByPrimaryKeySelective(menu);
}

選單維護:刪除節點

目標

刪除當前節點

思路

前端程式碼

按鈕繫結單擊響應函式

//給叉按鈕繫結單擊響應函式
$("#treeDemo").on("click", ".removeBtn", function () {
    //將當前節點的id儲存到全域性變數
    window.id = this.id;

    //開啟模態框
    $("#menuConfirmModal").modal("show");

    //獲取zTreeObj物件
    var zTreeObj = $.fn.zTree.getZTreeObj("treeDemo");

    //根據id屬性查詢節點物件
    //用來搜尋節點的屬性名
    var key = "id";

    //用來搜尋節點的屬性值
    var value = window.id;

    var currentNode = zTreeObj.getNodeByParam(key, value);

    $("#removeNodeSpan").html("【" + "<i class = '" + currentNode.icon + "' > </i>" + currentNode.name + "】");
    return false;
});

//給更新模態框中的更新按鈕繫結單擊響應函式
$("#confirmBtn").click(function () {
    //傳送ajax請求
    $.ajax({
        "url": "menu/remove.json",
        "type": "post",
        "data": {
            "id": window.id
        },
        "datatype": "json",
        "success": function (response) {
            var result = response.result;
            if (result === "SUCCESS") {
                layer.msg("操作成功");
                // 重新載入樹形結構,注意:要在確認伺服器端完成儲存操作後再重新整理
                // 否則有可能重新整理不到最新的資料,因為這裡是非同步的
                generateTree();
            }
            if (result === "FAILED") {
                layer.msg("操作失敗" + response.message);
            }
        },
        "error": function (response) {
            layer.msg(response.status + " " + response.statusText);
        }
    });
    //關閉模態框
    $("#menuConfirmModal").modal("hide");
});

後端程式碼

@RequestMapping("/menu/remove.json")
public ResultEntity<String> deleteMenu(Integer id){
    menuService.deleteByPrimaryKey(id);

    return ResultEntity.successWithoutData();
}

service程式碼

@Override
public void deleteByPrimaryKey(Integer id) {
    menuMapper.deleteByPrimaryKey(id);
}