原先使用的是Ztree,后来因为更多的定制化要求,还是手写一个算了
<template>
<div>
<menu-tree :nodes="nodes" :selected="currentCameraId"></menu-tree>
</div>
</template>
<script>
import EventBus from "@/utils/EventBus";
import MenuTree from "@/views/HomePage2D/components/MenuTree";
import dh_config from "static/config/dh-camera";
export default {
name: "zoneDeviceDir",
components: {MenuTree},
data() {
return {
nodes: [],
allNodes: [],
currentCameraId: ''
}
},
watch: {},
computed: {},
methods: {
//选中
cameraClick(item) {
this.currentCameraId = this.currentCameraId === item.id ? '' : item.id;
if (this.currentCameraId !== '') {
EventBus.$emit('showThisVideo',item)
}
},
//全部展开或折叠
allNoExpand(flag) {
this.nodes.forEach(node => {
this.noExpand(node, flag)
})
},
noExpand(node, flag) {
node.expand = flag;
if (node.children && node.children.length > 0) {
node.children.forEach(childNode => {
this.noExpand(childNode, flag)
})
}
},
//反向定位
reverseCamera(id) {
this.currentCameraId = id;
this.allNoExpand(false);
this.nodes = this.allNodes;
this.cameraSelect(this.nodes, id);
},
cameraSelect(nodes, queryData) {
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (node.children === null && this.corCamera(node, queryData)) {
node.expand = true;
} else {
let deepQuery = this.corCamera(node, queryData);
if (deepQuery) {
node.expand = true;
if (node.children) {
this.cameraSelect(node.children, queryData);
}
}
}
}
},
corCamera(node, queryData) {
if (node.children === null) {
if (node.id === queryData) {
return true;
} else {
return false;
}
}
for (let i = 0; i < node.children.length; i++) {
if (this.corCamera(node.children[i], queryData)) {
return true;
}
}
return false;
},
//查找
search(queryData) {
let array = this.treeSelect(this.allNodes, queryData);
this.nodes = array;
this.allNoExpand(true);
},
treeSelect(nodes, queryData) {
let newArray = [];
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (node.children === null && this.treeDeepQuery(node, queryData)) {
newArray.push(node);
} else {
let deepQuery = this.treeDeepQuery(node, queryData);
if (deepQuery) {
let newNode = JSON.parse(JSON.stringify(node));
if (node.children) {
newNode.children = this.treeSelect(node.children, queryData);
}
newArray.push(newNode)
}
}
}
return newArray;
},
treeDeepQuery(node, queryData) {
if (node.children === null) {
if (node.name.indexOf(queryData) !== -1) {
return true;
} else {
return false;
}
}
for (let i = 0; i < node.children.length; i++) {
if (this.treeDeepQuery(node.children[i], queryData)) {
return true;
}
}
return false;
}
},
mounted() {
EventBus.$on("item-click", this.cameraClick)
EventBus.$on('ReversePositioning',this.reverseCamera)
let T = this
this.$axios.get(`/camera/menu/list?&time=${new Date().getTime()}`).then(res => {
if (res.data.code !== 200) {
this.$Message.error(res.data.msg)
} else {
T.nodes = res.data.data
T.allNodes = res.data.data
}
})
},
beforeDestroy() {
}
}
</script>
<style lang="scss" scoped>
</style>
树组件
<template>
<div class="menu-tree" :class="{'menu-tree-top' : top}">
<div v-for="item in nodes" :key="item.id">
<!--菜单-->
<div class="menu-item" @click="folderClick(item)" v-show="item.children !== null && item.num > 0">
<div style="position: absolute;top: 0;left: 20px;width: calc(100% - 20px);height: 100%"></div>
<i class="iconfont iconjia" v-show="!item.expand" style="color: #0ABBE5"></i>
<i class="iconfont iconjian" v-show="item.expand"></i>
{{item.name}}<span v-show="item.num > 0">({{item.num}})</span>
</div>
<!--摄像头-->
<div class="menu-item" @click="itemClick(item)" v-show="item.children === null" :class="{'menu-item-selected-parent':item.id === selected}">
<div style="position: absolute;top: 0;left: 20px;width: calc(100% - 20px);height: 100%" :class="{'menu-item-selected':item.id === selected}"></div>
<i class="iconfont iconshexiangtou" :class="[{'online': item.statusName === '在线'},{'offline': item.statusName !== '在线'}]"></i>
<span>({{item.resource}}) </span>{{item.name}}
</div>
<!--子菜单递归-->
<div v-show="item.children && item.children.length > 0 && item.expand" class="child-menu">
<menu-tree :nodes="item.children" :selected="selected" :top="false"></menu-tree>
</div>
</div>
</div>
</template>
<script>
import EventBus from "@/utils/EventBus";
export default {
props: {
nodes: Array,
selected: String,
top: {
required: false,
default: true
}
},
name: "MenuTree",
data() {
return {}
},
mounted() {
},
methods: {
itemClick(item) {
EventBus.$emit('item-click', item);
},
folderClick(item) {
this.nodes.forEach(node => {
if (node.id === item.id) {
node.expand = !node.expand;
}
})
}
}
}
</script>
<style lang="scss">
.menu-tree {
color: #333;
font-size: 17px;
position: relative;
.menu-item {
position: relative;
padding-left: 25px;
height: 40px;
line-height: 40px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.online {
color: #1686D8;
}
.offline {
color: #B7C3CE;
}
.menu-item-selected {
border: 1px solid #1686D8;
background: rgba(22, 134, 216, 0.1);
}
&:hover {
cursor: pointer;
> div {
&:first-child {
border: 1px solid #1686D8;
background: rgba(22, 134, 216, 0.1);
}
}
}
&:after {
content: "";
width: 11px;
height: 20px;
position: absolute;
left: 12px;
top: 19px;
border-width: 1px;
border-top: 1px dashed #52627C;
}
}
.menu-item-selected-parent {
font-weight: bold;
}
.menu-item-camera {
width: 100%;
}
.child-menu {
margin-left: 20px;
position: relative;
&:before {
content: "";
height: calc(100% - 11px);
width: 1px;
position: absolute;
left: 12px;
top: -11px;
border-width: 1px;
border-left: 1px dashed #52627C;
}
}
}
.menu-tree-top > div > .menu-item {
/*padding-left: 0;*/
&:before {
border-left: none;
}
&:after {
border-top: none;
}
}
</style>