CMVR-IOT-UI/src/views/flow/components/NodeTitle.vue
2026-04-14 16:17:52 +08:00

249 lines
6.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="title__container">
<div class="title">
<div class="left">
<img :src="imageUrl()" alt="" />
<div class="text__container">
<div class="text__title" v-if="showTextTitle">
<span class="text">{{ nodeName }}</span>
<el-icon class="editIcon" @click="showTextTitle = false"><EditPen/></el-icon>
</div>
<div class="input_name_container" v-else>
<el-input v-model="nodeName" @keydown="handleInputKeydown" />
<el-button
class="input_name_select"
circle
size="small"
@click="confirmNodeName"
>
<el-icon><Select /></el-icon>
</el-button>
<el-button
class="input_name_closeBold"
circle
size="small"
@click="cancelNodeName"
>
<el-icon><CloseBold /></el-icon>
</el-button>
</div>
</div>
</div>
<div class="right">
<el-tooltip
class="box-item"
effect="dark"
content="执行"
placement="top"
>
<el-button v-if="nodeType && nodeType !=='NONE'" circle @click="execute">
<el-icon>
<VideoPlay />
</el-icon>
</el-button>
</el-tooltip>
<!-- <el-tooltip
class="box-item"
effect="dark"
:content="zoomState ? '缩小' : '放大'"
placement="top"
>
<el-button v-if="showZoom" circle @click="zoom">
<el-icon>
<ZoomOut v-if="zoomState" />
<ZoomIn v-else />
</el-icon>
</el-button>
</el-tooltip> -->
<el-tooltip
class="box-item"
effect="dark"
content="删除"
placement="top"
>
<el-button circle @click="deleteNode">
<el-icon><Delete /></el-icon>
</el-button>
</el-tooltip>
</div>
</div>
<div class="subTitle">{{ props.nodeDesc }}</div>
</div>
</template>
<script setup lang="js">
import { ref } from 'vue'
import { EditPen, Select, CloseBold, Delete, ZoomOut, ZoomIn, VideoPlay } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import { computed } from 'vue'
const props = defineProps({
icon: {
type: String,
default: ''
},
nodeId: {
type: String,
default: ''
},
nodeProperties: {
type: Object,
default: () => {}
},
nodeDesc: {
type: String,
default: ''
},
nodeName: {
type: String,
default: ''
},
nodeType: {
type: String,
default: ''
},
showZoom: {
type: Boolean,
default: true
},
zoomState: {
type: Boolean,
default: false
}
})
const emits = defineEmits(['zoom', 'setNodeName'])
const showTextTitle = ref(true)
const nodeName = ref(props.nodeProperties.name || props.nodeName)
const confirmNodeName = () => {
emits('setNodeName', nodeName.value)
showTextTitle.value = true
}
const cancelNodeName = () => {
nodeName.value = props.nodeProperties?.name || props.nodeName
showTextTitle.value = true
}
const deleteNode = () => {
ElMessageBox.confirm(
'是否删除该节点?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
if (props.nodeType === 'selectArea') {
const children = lf.getNodeModelById(props.nodeId).children
lf.getNodeModelById(props.nodeId).children = []
children.forEach(item => {
lf.getNodeModelById(item).draggable = true
})
}
lf.deleteNode(props.nodeId);
})
}
const zoom = () => {
emits('zoom', !props.zoomState)
}
const execute = () => {
const myEvent = new CustomEvent('singleNodeExecution', {
bubbles: false, // 是否冒泡(默认 false
cancelable: false, // 是否可被 preventDefault() 取消(默认 false
detail: { ...props.nodeProperties } // 自定义数据(任意类型,通过 event.detail 读取)
});
document.dispatchEvent(myEvent);
}
const handleInputKeydown = (e) => {
// 阻止事件冒泡到 Logic Flow 节点,避免被其事件拦截
e.stopPropagation();
// 可选:明确放行 Ctrl+V增强兼容性
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
e.returnValue = true; // 允许默认粘贴行为
}
}
const imageUrl = () => {
return new URL(props.icon, import.meta.url).href;
}
</script>
<style lang="scss" scoped>
.title__container {
.title {
display: flex;
align-items: center;
justify-content: space-between;
.left {
display: flex;
img {
width: 24px;
height: 24px;
}
.text__container {
.text__title {
display: flex;
align-items: center;
.text {
font-size: 16px;
font-weight: bold;
margin: 0 12px;
}
.editIcon {
cursor: pointer;
}
}
.input_name_container {
display: flex;
align-items: center;
.el-input {
margin-left: 12px;
width: 120px;
}
.input_name_select {
color: #00b42a;
margin-left: 4px;
border: none;
}
.input_name_closeBold {
color: #f53f3f;
margin-left: 4px;
border: none;
}
}
}
}
.right {
cursor: pointer;
.el-button {
border: none;
font-size: 24px;
}
}
}
.subTitle {
color: #737a87;
font-size: 12px;
margin: 8px 0;
}
}
</style>