AIoT前端公共UI

DndNodes.vue 5.0KB

    <template> <div class="dnd-nodes"> <div class="int-box"> <el-input v-model="filterValue" class="int" placeholder="根据节点名称搜索" @input="searchFilter" > <template #suffix> <el-icon><Search @click.stop="searchFilter"></Search></el-icon> </template> </el-input> </div> <div class="node-container"> <el-collapse v-model="activeNames"> <template v-for="item in nodeList" :key="item?.name"> <el-collapse-item :name="item.name"> <template #title> <div class="c-title">{{ item.label }}</div> </template> <el-row> <template v-for="node in item.nodes" :key="node.id"> <el-col :span="8"> <div :data-id="node.id" :data-type="node.type" :data-name="node.name" :data-label="node.label" :data-icon="node.icon" class="ability-item" @mousedown="startDrag" > <common-icon v-if="item.name !== 'process'" :name="node.icon" :size="36" ></common-icon> <img v-else class="img" :src="node.icon || icon" alt="" /> <span class="title">{{ node.label }}</span> </div> </el-col> </template> </el-row> </el-collapse-item> </template> </el-collapse> </div> </div> </template> <script setup> import { defineProps, ref, computed, watchEffect } from 'vue'; const props = defineProps({ nodes: { type: Array, default: () => [] }, dnd: { type: Array, default: () => [] }, processDefItemList: { type: Array, default: () => [] }, onDragStart: { type: Function, default: () => null } }); const filterValue = ref(''); const basicNodes = ref([]); const nodeLists = ref([]); const nodeList = computed(() => { const nodes = JSON.parse(JSON.stringify(nodeLists.value)); const val = filterValue.value; return nodes.reduce((acc, item) => { if (item.nodes.some((node) => node.label.indexOf(val) > -1)) { const nodes = item.nodes.filter((node) => node.label.indexOf(val) > -1); acc.push({ ...item, nodes }); } else if (item.label.indexOf(val) > -1) { acc.push({ ...item, nodes: [] }); } return acc; }, []); }); const activeNames = computed(() => nodeLists.value.map((item) => item.name)); const formatDnd = (processDefItemList) => { const nodes = processDefItemList.map((item) => ({ name: 'process', id: item.assetSpecId, label: item.assetSpecName, type: 'process', icon: item.iconUrl })); if (nodes.length) { nodeLists.value = [ { label: '资产模型节点', name: 'process', nodes }, ...basicNodes.value ]; } else { nodeLists.value = [...basicNodes.value]; } }; watchEffect(() => { basicNodes.value = props.nodes; formatDnd(props.processDefItemList); }); const startDrag = (event) => { const { currentTarget } = event; // const node = getShapeAttr(event.currentTarget); const { id, type, name, label, icon } = currentTarget.dataset; const offsetX = event.clientX - currentTarget.getBoundingClientRect().left; const offsetY = event.clientY - currentTarget.getBoundingClientRect().top; props.onDragStart({ id, type, name, label, icon, offsetX, offsetY }, event); }; </script> <style lang="scss" scoped> .dnd-nodes { width: 260px; height: calc(100vh - 70px); overflow: auto; } .int-box { padding: 15px; } .c-title { padding-left: 10px; color: rgba(0, 0, 0, 0.65); font-size: 14px; } :deep(.el-collapse-item__header) { background: rgba(0, 0, 0, 0.02); height: 40px; line-height: 40px; .el-collapse-item__arrow { font-size: 18px; color: #040000; } } .ability-item { display: flex; justify-content: center; align-items: center; flex-direction: column; margin-top: 30px; cursor: move; .title { margin-top: 6px; color: rgba(0, 0, 0, 0.65); font-size: 14px; width: 90px; word-wrap: break-word; word-break: break-all; text-align: center; } .img { width: 32px; height: 32px; } } .node-container { height: calc(100vh - 134px); overflow: auto; } /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/ ::-webkit-scrollbar { width: 5px; height: 10px; background-color: #f5f5f5; } /*定义滚动条轨道 内阴影+圆角*/ ::-webkit-scrollbar-track { box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); border-radius: 10px; background-color: #f5f5f5; } /*定义滑块 内阴影+圆角*/ ::-webkit-scrollbar-thumb { border-radius: 10px; box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); background-color: #c8c8c8; } </style>