zTree的用法,以及父子節點(關係節點)轉化爲tree結構

var setting = {
    edit: {
        enable: true,
        showRemoveBtn: false,//顯示後,節點可刪除
        showRenameBtn: false,//顯示後,節點可重命名
        drag:{
            isCopy:true,  //允許複製
            isMove:false, //允許移動
            prev:false,   //允許插在前面
            inner:false,  //允許插在裏面
            next:false     //允許插在後面
        }
    },
    data: {
        simpleData: {
            enable: true
        }
    },
    callback: {
        beforeDrag: beforeDrag,
        beforeDrop: beforeDrop
    }
};

var setting2 = {
    edit: {
        enable: true,
        showRemoveBtn: true,
        showRenameBtn: true,
        drag:{
            isCopy:false,
            isMove:true,
            prev:false,
            inner:true,
            next:false
        }
    },
    data: {
        simpleData: {
            enable: true,
            idKey: "id",
            pIdKey: "pId",
            rootPId: 0
        }
    },
    callback: {
        beforeDrag: beforeDrag,
        beforeDrop: beforeDrop
    }
};

var zNodes2 =[
    { id:1, pId:0, name:"fast", open:true, myAttr:"root"},//額外的屬性幫助顯示不同的圖標
                              //如果用自帶level,拖動之後圖標會亂,項目特性需要綁定到節點上
    { id:2, pId:1, name:"ceph10", open:true, myAttr:"host"},
        { id:5, pId:2, name:"osd.0"},
        { id:6, pId:2, name:"osd.1"},
        { id:7, pId:2, name:"osd.2"},
        { id:8, pId:2, name:"osd.3"},
    { id:3, pId:1, name:"ceph20", open:true, myAttr:"host"},
        { id:9, pId:3, name:"osd.4"},
        { id:10, pId:3, name:"osd.5"},
        { id:11, pId:3, name:"osd.6"},
        { id:12, pId:3, name:"osd.7"},
    { id:4, pId:1, name:"ceph30", open:true, myAttr:"host"},
        { id:13, pId:4, name:"osd.8"},
        { id:14, pId:4, name:"osd.9"},
        { id:15, pId:4, name:"osd.10"},
        { id:16, pId:4, name:"osd.11"},

    { id:21, pId:0, name:"default", open:true, myAttr:"root"},
    { id:22, pId:21, name:"ceph10", open:true,  myAttr:"host"},
        { id:25, pId:22, name:"osd.0"},
        { id:26, pId:22, name:"osd.1"},
        { id:27, pId:22, name:"osd.2"},
        { id:28, pId:22, name:"osd.3"},
    { id:23, pId:21, name:"ceph20", open:true, myAttr:"host"},
        { id:29, pId:23, name:"osd.4"},
        { id:30, pId:23, name:"osd.5"},
        { id:31, pId:23, name:"osd.6"},
        { id:32, pId:23, name:"osd.7"},
    { id:24, pId:21, name:"ceph30", open:true, myAttr:"host"},
        { id:33, pId:24, name:"osd.8"},
        { id:34, pId:24, name:"osd.9"},
        { id:35, pId:24, name:"osd.10"},
        { id:36, pId:24, name:"osd.11"}
];

function beforeDrag(treeId, treeNodes) {
    //更加深入的定製啓動點的條件
    for (var i=0,l=treeNodes.length; i<l; i++) {
        if (treeNodes[i].drag === false) {
            return false;
        }
    }
    return true;
}
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
    //更加深入的定製落點的條件
    if (targetNode && targetNode.myAttr==undefined){
        return false
    }

    return targetNode ? targetNode.drop !== false : true;
}

function fixIcon(demotree){
    var treeObj = $.fn.zTree.getZTreeObj(demotree);
    //過濾出某一類的節點,選出myAttr=='host'的節點
    var folderNode = treeObj.getNodesByFilter(function (node) { return node.myAttr=="host"});
    for(j=0 ; j<folderNode.length; j++){//遍歷目錄節點,設置isParent屬性爲true;
        folderNode[j].isParent = true;
        folderNode[j].icon="/static/images/8.png";
    }

    var folderNode = treeObj.getNodesByFilter(function (node) { return node.myAttr=="root"});
    for(j=0 ; j<folderNode.length; j++){//遍歷目錄節點,設置isParent屬性爲true;
        folderNode[j].isParent = true;
        folderNode[j].iconOpen="/static/images/1_open.png";
        folderNode[j].iconClose="/static/images/1_close.png"
    }
    treeObj.refresh();//調用api自帶的refresh函數。
}
function fixopen(demotree) {
    var treeObj = $.fn.zTree.getZTreeObj(demotree);
    var folderNode = treeObj.getNodesByFilter(function (node) { return node.myAttr=="host" || node.myAttr=="root"});
    for(j=0 ; j<folderNode.length; j++){//遍歷目錄節點,設置isParent屬性爲true;
        folderNode[j].open = true;
    }
    treeObj.refresh();//調用api自帶的refresh函數。

}
//異步加載數據,數據格式如zNodes2定義的地方
zNodes2 = JSON.parse(arg.topo);
$.fn.zTree.init($("#treeDemo2"), setting2, zNodes2);
fixIcon("treeDemo2");
fixopen("treeDemo2");

父子節點(關係節點)的列表,轉化成tree的算法:、

from collections import namedtuple
 #原始機構 
Relation = namedtuple("RELATION",["name","id","pId","myAttr"])
#舒型結構,多一個children,其他語言可以用類或者結構體實現也一樣
Tree = namedtuple("TREE",["name","id","pId","myAttr","children"]) 

    
#需要保證關係列表是有序的,否則父節點沒有插入就插入字節點會失敗
#如果實在不保序, 解決辦法建立一個節點添加標誌的字典,失敗的重複添加
def make_tree(nodes):
    res = Tree("super", 0, 0, "super", []) #根節點,不同語言根節點生成不一樣
    for node in nodes:
        add_tree(res, node)
    return res

def add_tree(root, node):
    data = Tree(node["name"], node["id"], node["pId"], node["myAttr"], [])
    if node["pId"]== root.id: #只有符合條件的才真正添加
        root.children.append(data)
        return
    for child in root.children: #可迭代對象自動判空
        add_tree(child,node) #所有節點都嘗試添加

def traverse_tree(res, root):
    if root:
        res.append(Relation(root.name, root.id, root.pId, root.myAttr)._asdict())
        for child in root.children:
            traverse_tree(res, child)
#逆向操作,樹生成關係節點
def tree_to_relation(root):
    res =[]
    traverse_tree(res, root)
    return res

項目中還遇到js的問題,後臺傳的數據給前臺下拉列表;下拉列表(本身也是異步數據,生成的時候會清空再存入選項)會觸發監聽,相互覆蓋的下拉選項;目前解決是後臺數據傳給下拉框的時候,不調用trigger,並且也傳入完整的下拉列表和選中情況;

也許有辦法直接根據後臺數據,直接修改下拉列表的選中選中情況;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章