235 lines
7.9 KiB
Vue
235 lines
7.9 KiB
Vue
<template>
|
|
<div style="height: 100%;">
|
|
<div class="tree-search-bar">
|
|
<Input v-model="keyword" placeholder="输入学校,回车查找" suffix="ios-search" clearable @on-enter="onSearch"
|
|
@on-clear="onSearch" style="width:100%;margin-bottom: 10px;" />
|
|
</div>
|
|
<div :id="domId" :ref="domId" class="ztree"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
export default {
|
|
props: {
|
|
treeData: {
|
|
type: Object,
|
|
},
|
|
setting: {
|
|
type: Object,
|
|
default: {
|
|
view: {
|
|
dblClickExpand: false,
|
|
showIcon: false,
|
|
},
|
|
edit: {
|
|
enable: true,
|
|
showRemoveBtn: false,
|
|
showRenameBtn: false,
|
|
drag: false,
|
|
},
|
|
check: {
|
|
enable: false,
|
|
},
|
|
callback: {},
|
|
},
|
|
},
|
|
autoClick: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
isCheck: {
|
|
typeof: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
domId: "",
|
|
treeSetting: _.cloneDeep(this.setting),
|
|
treeObj: null,
|
|
keyword: '',
|
|
highlightNodes: []
|
|
};
|
|
},
|
|
created() {
|
|
this.$watch("treeData", val => {
|
|
console.log(val);
|
|
if (val) {
|
|
console.log(val);
|
|
this.$nextTick(() => {
|
|
this.initTree(this.treeData, this.domId);
|
|
});
|
|
}
|
|
});
|
|
},
|
|
mounted() {
|
|
this.domId = this.uuid();
|
|
},
|
|
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() {
|
|
this.treeData.open = true;
|
|
this.initTree(this.treeData, this.domId);
|
|
},
|
|
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") {
|
|
if (!targetNode.isParent) return false;
|
|
} else {
|
|
if (targetNode.pid === 0) return 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;
|
|
},
|
|
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) {
|
|
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 };
|
|
treeObj.addNodes(pnode, -1, newNode);
|
|
},
|
|
onSearch() {
|
|
this.clearHighlight();
|
|
if (!this.keyword) return;
|
|
this.doSearch(this.keyword);
|
|
},
|
|
doSearch(key) {
|
|
const treeObj = this.treeObj;
|
|
// 1. 模糊匹配
|
|
const matchNodes = treeObj.getNodesByFilter(node =>
|
|
node.type == 2 &&
|
|
node.name && node.name.toLowerCase().includes(key.toLowerCase())
|
|
);
|
|
if (!matchNodes.length) {
|
|
this.$Message.info('未搜索到匹配学校')
|
|
return;
|
|
}
|
|
// 2. 展开所有命中节点的父节点
|
|
matchNodes.forEach(n => {
|
|
let p = n.getParentNode();
|
|
while (p) {
|
|
treeObj.expandNode(p, true, false, false);
|
|
p = p.getParentNode();
|
|
}
|
|
});
|
|
// 3. 高亮
|
|
this.highlightNodes = matchNodes;
|
|
matchNodes.forEach(n => this.setHighlight(n, true));
|
|
|
|
// const box = document.getElementById('treeBox');
|
|
// const nodeEl = document.getElementById(matchNodes[0].tId);
|
|
// box.scrollTop = nodeEl.offsetTop - box.clientHeight / 2; // 居中
|
|
|
|
if (matchNodes.length) {
|
|
const treeObj = this.treeObj;
|
|
console.log(matchNodes[0]);
|
|
this.selectNode(matchNodes[0].id);
|
|
|
|
// treeObj.selectNode(matchNodes[0]); // 先选中,会自动滚入可视区
|
|
//this.$nextTick(() => treeObj.cancelSelectedNode()); // 取消选中,保持纯高亮
|
|
}
|
|
|
|
},
|
|
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 = [];
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.ztree {
|
|
height: calc(100% - 60px);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.ztree-search-highlight {
|
|
background-color: #ff6600 !important;
|
|
}
|
|
|
|
.ztree li a.curSelectedNode {
|
|
background-color: #ffe4bb !important;
|
|
}
|
|
</style>
|