AIoT前端公共UI

Tree.vue 4.4KB

    <!-- 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>