215 lines
7.4 KiB
Vue
215 lines
7.4 KiB
Vue
<template>
|
|
<div>
|
|
<div :id="domId" :ref="domId" class="ztree"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
export default {
|
|
props: {
|
|
treeData: {
|
|
type: Object,
|
|
},
|
|
setting: {
|
|
type: Object,
|
|
default: {},
|
|
},
|
|
autoClick: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
isCheck: {
|
|
typeof: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
domId: "",
|
|
treeSetting: _.cloneDeep(this.setting),
|
|
treeObj: null,
|
|
highlightNodes: [],
|
|
};
|
|
},
|
|
created() {
|
|
this.$watch("treeData", val => {
|
|
if (val) {
|
|
this.$nextTick(() => {
|
|
this.initTree(this.treeData, this.domId);
|
|
});
|
|
}
|
|
});
|
|
},
|
|
mounted() {
|
|
this.domId = this.uuid();
|
|
if (this.treeData) {
|
|
this.$nextTick(() => {
|
|
this.initTree(this.treeData, this.domId);
|
|
});
|
|
}
|
|
},
|
|
methods: {
|
|
uuid() {
|
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
var r = (Math.random() * 16) | 0,
|
|
v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
return v.toString(16);
|
|
});
|
|
},
|
|
reloadTree(nodeId) {
|
|
this.initTree(this.treeData, this.domId);
|
|
if (nodeId != null) {
|
|
this.$nextTick(() => {
|
|
this.selectNode(nodeId, true); // 第二个参数 true 会 emit on-tree-click
|
|
});
|
|
}
|
|
},
|
|
initTree(_data, _domId) {
|
|
const _this = this;
|
|
_this.treeSetting.callback.onClick = (event, treeId, treeNode, clickFlag) => {
|
|
// console.log(event, treeId, treeNode, clickFlag);
|
|
if (_this.isCheck) {
|
|
var treeObj = $.fn.zTree.getZTreeObj(treeId);
|
|
treeObj.checkNode(treeNode, !treeNode.checked, true);
|
|
}
|
|
_this.$emit("on-tree-click", treeNode);
|
|
};
|
|
|
|
_this.treeSetting.callback.beforeDrop = (treeId, treeNodes, targetNode, moveType) => {
|
|
if (moveType == "inner") {
|
|
// 移除限制,允许叶子节点接受子节点
|
|
} else {
|
|
if (targetNode.pid === 0) return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
_this.treeSetting.callback.beforeDrag = (treeId, treeNodes) => {
|
|
return treeNodes[0].drag !== false;
|
|
};
|
|
|
|
_this.treeSetting.callback.beforeClick = (treeId, treeNode, clickFlag) => {
|
|
return !(treeNode.click === false);
|
|
};
|
|
|
|
_this.treeSetting.callback.onDrop = (event, treeId, treeNodes, targetNode, moveType) => {
|
|
_this.$emit("on-tree-drag", { treeNodes, targetNode, moveType });
|
|
};
|
|
|
|
_this.treeSetting.callback.onCheck = (event, treeId, treeNode) => {
|
|
_this.$emit("on-tree-check", treeNode);
|
|
};
|
|
|
|
_this.treeObj = $.fn.zTree.init($("#" + _domId), _this.treeSetting, _data);
|
|
if (_this.autoClick) {
|
|
if (Array.isArray(this.treeData)) {
|
|
let id = this.treeData[0].id;
|
|
_this.selectNode(id);
|
|
} else {
|
|
let id = this.treeData.id;
|
|
_this.selectNode(id);
|
|
}
|
|
}
|
|
},
|
|
selectNode(id, isClick = true) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
var node = treeObj.getNodesByFilter(node => node.id == id, true);
|
|
if (node == null) return false;
|
|
treeObj.selectNode(node);
|
|
treeObj.expandNode(node, true, false, false);
|
|
treeObj.selectNode(node);
|
|
if (isClick) this.$emit("on-tree-click", node);
|
|
},
|
|
openTree(open) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
treeObj.expandAll(open);
|
|
},
|
|
removeNode(id) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
var node = treeObj.getNodesByFilter(node => node.id == id, true);
|
|
var pnode = node.getParentNode();
|
|
treeObj.removeNode(node);
|
|
pnode.isParent = true;
|
|
treeObj.updateNode(pnode);
|
|
this.selectNode(pnode.id);
|
|
},
|
|
getNodeById(id) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
var node = treeObj.getNodesByFilter(node => node.id == id, true);
|
|
return node;
|
|
},
|
|
// 仅更新节点勾选状态,不级联、不触发 onCheck 回调
|
|
checkNodeById(id, checked) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
if (!treeObj) return;
|
|
var node = treeObj.getNodesByFilter(node => node.id == id, true);
|
|
if (node) treeObj.checkNode(node, !!checked, false);
|
|
},
|
|
renameNode(id, name) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
var node = treeObj.getNodesByFilter(node => node.id == id, true);
|
|
node.name = name;
|
|
treeObj.updateNode(node);
|
|
},
|
|
addNote(pid, id, name, isParent, children) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
var pnode = treeObj.getNodesByFilter(node => node.id == pid, true);
|
|
var newNode = { pid, id, name, isParent };
|
|
if (children && children.length) newNode.children = children;
|
|
treeObj.addNodes(pnode, -1, newNode);
|
|
},
|
|
setHighlight(node, on = true) {
|
|
const a = $('#' + node.tId + '_a');
|
|
if (on) a.addClass('ztree-search-highlight');
|
|
else a.removeClass('ztree-search-highlight');
|
|
},
|
|
clearHighlight() {
|
|
(this.highlightNodes || []).forEach(n => this.setHighlight(n, false));
|
|
this.highlightNodes = [];
|
|
},
|
|
search(keyword) {
|
|
const _domId = this.domId;
|
|
var treeObj = $.fn.zTree.getZTreeObj(_domId);
|
|
if (!treeObj) return;
|
|
this.clearHighlight();
|
|
const kw = (keyword || '').trim().toLowerCase();
|
|
if (!kw) return;
|
|
const matchNodes = treeObj.getNodesByFilter(
|
|
(node) => node.name && node.name.toLowerCase().includes(kw),
|
|
false
|
|
) || [];
|
|
if (!matchNodes.length) {
|
|
if (this.$Message && this.$Message.info) this.$Message.info('未搜索到匹配组');
|
|
return;
|
|
}
|
|
matchNodes.forEach(n => {
|
|
let p = n;
|
|
while (p) {
|
|
treeObj.expandNode(p, true, false, false);
|
|
p = p.getParentNode();
|
|
}
|
|
});
|
|
this.highlightNodes = matchNodes;
|
|
matchNodes.forEach(n => this.setHighlight(n, true));
|
|
this.selectNode(matchNodes[0].id, true);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.ztree-search-highlight {
|
|
background-color: #ff6600 !important;
|
|
}
|
|
|
|
.ztree li a.curSelectedNode {
|
|
background-color: #ffe4bb !important;
|
|
}
|
|
</style>
|