|
<!-- eslint-disable vue/no-mutating-props -->
<!-- eslint-disable vue/no-template-shadow -->
<!--
* @Author: Devin
* @Date: 2022-12-12 16:52:01
* @LastEditors: Devin
* @LastEditTime: 2023-02-22 14:50:08
* @Description: 公共树组件
-->
<template>
<div class="aiot-common-tree">
<div class="common-btn">
<el-button link @click.stop="addRootLevel">
<span class="btn-icon">
<!-- <common-icon name="common-plus" :size="12"></common-icon> -->
+
</span>
{{ btnText }}
</el-button>
</div>
<!-- filter -->
<el-input
v-if="hasFilter"
v-model="filterText"
size="small"
:suffix-icon="Search"
:placeholder="searchText || '请输入'"
class="int"
@keydown="filterTree"
></el-input>
<!-- tree module -->
<el-tree
ref="treeRef"
:data="treeData"
v-bind="attrs"
empty-text="暂无数据"
:highlight-current="true"
:filter-node-method="filterNode"
@node-click="nodeClick"
>
<template #default="{ node, data }">
<span
class="custom-tree-node"
@mouseenter="() => (hIndex = node.label)"
@mouseleave="() => (hIndex = '')"
>
<span>{{ node.label }}</span>
{{ node.$index }}
<template v-if="hIndex === node.label">
<span v-if="actions">
<span
v-for="action in actions"
:key="action?.['name']"
:class="action?.['type'] || 'primary'"
class="m-l-4 text-btn"
@click.stop="action.onClick(node, data)"
>
<common-icon
v-if="isIcon"
:name="action?.['name']"
:size="action?.['size'] || 18"
:content="action?.['label']"
></common-icon>
<span v-else>
{{ action?.['label'] }}
</span>
</span>
</span>
</template>
</span>
</template>
</el-tree>
</div>
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue';
import { watch, ref } from 'vue';
const emits = defineEmits(['nodeClick', 'addRootLevel']);
const hIndex = ref<any>('');
const props = defineProps({
attrs: {
type: Object,
default: () => {}
},
hasFilter: {
type: Boolean,
default: () => true
},
searchText: {
type: String,
default: () => ''
},
treeData: {
type: Array,
default: () => []
},
searchWord: {
type: String,
default: () => ''
},
actions: {
type: Array<any>,
default: () => []
},
isIcon: {
type: Boolean,
default: () => true
},
btnText: {
type: String,
default: () => '新增根目录'
}
});
// 树过滤
function filterTree(val: any) {
console.log(val);
}
function filterNode(value: string, data: any) {
if (!value) return true;
return data?.[props?.attrs?.props?.label || 'label'].includes(value);
}
const filterText = ref('');
const treeRef = ref<any>(null);
watch(filterText, (val) => {
treeRef.value!.filter(val);
});
defineExpose({
treeRef
});
// 节点被点击时
function nodeClick(data: any) {
emits('nodeClick', data);
}
// 添加一级目录
function addRootLevel() {
emits('addRootLevel');
}
</script>
<script lang="ts">
export default {
name: 'CommonTree'
};
</script>
<style lang="scss">
.aiot-common-tree {
.icon {
margin-left: 5px;
}
.custom-tree-node {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
line-height: 32px;
}
.int {
margin-bottom: 10px;
}
.common-btn {
width: 100%;
// text-align: center;
border-bottom: 1px solid #ebebeb;
margin-bottom: 10px;
padding-bottom: 10px;
font-size: 14px;
color: #455a74;
.btn-icon {
background-color: #2d98ff;
color: #fff;
padding: 2px;
margin-right: 10px;
border-radius: 2px;
}
}
}
:deep(.el-tree-node) {
line-height: 32px;
}
:deep(.el-tree-node__label) {
width: 100%;
}
:deep(.el-tree-node__content) {
height: 32px;
}
.text-btn {
cursor: pointer;
min-width: 12px;
}
// type color
.primary {
color: #169bfa;
}
.warning {
color: #ffb95b;
}
.error {
color: #ff5f5f;
}
.danger {
color: #ff5f5f;
}
.info {
color: #2d3e53;
}
</style>
|