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,并且也传入完整的下拉列表和选中情况;
也许有办法直接根据后台数据,直接修改下拉列表的选中选中情况;