CMVR-IOT-UI/src/views/flow/nodes/function/loop.vue

200 lines
5.9 KiB
Vue
Raw Normal View History

2025-09-04 16:41:54 +08:00
<template>
<div class="group__container" @mouseleave="setNodeProperties">
<NodeTitle :icon="loop" :nodeId="props.model.id" :nodeProperties="props.properties" :nodeName="props.properties?.name || '循环'" nodeDesc="循环执行一系列任务,直至输出所有结果" />
<div class="loop__container">
<div>
<el-form :inline="true" :model="formData" :rules="rules" ref="dynamicForm" label-position="top" label-width="auto" :disabled="flowStore.disableForm">
<div v-for="(property, index) in formData.nodeParams" :key="index">
<el-row>
<el-form-item :label="index === 0 ? '参数名' : ''" :prop="`nodeParams.${index}.name`" :rules="[{ required: true, message: '请输入参数名', trigger: 'blur' }]">
<el-input :disabled="index === 0" v-model="property.name" placeholder="请输入" clearable />
</el-form-item>
<el-form-item :label="index === 0 ? '参数值' : ''" :prop="`nodeParams.${index}.type`" >
<el-select v-model="property.type" @change="handleTypeChange(index)">
<el-option label="引用" value="quote" />
<el-option label="输入" value="input" />
</el-select>
<el-form-item v-if="property.type === 'input'" :rules="[{ required: true, message: '请输入参数值', trigger: 'blur' }]" :prop="`nodeParams.${index}.input`">
<el-input-number v-model="property.input" :min="0" :controls="false" :step-strictly="true" placeholder="请输入" clearable />
</el-form-item>
<el-form-item v-if="property.type === 'quote'" :rules="[{ required: true, message: '请选择参数值', trigger: 'blur' }]" :prop="`nodeParams.${index}.quote`">
<el-cascader v-model="property.quote" :options="quoteOptions" placeholder="请选择" @visible-change="visibleChange"/>
</el-form-item>
</el-form-item>
</el-row>
</div>
</el-form>
</div>
</div>
<div>循环体</div>
<div class="child__container" @drop="handleDrop" @dragover="handleDragover">
<slot></slot>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import NodeTitle from '../../components/NodeTitle.vue'
import loop from '../../icon/loop.svg'
import { useFlowStore } from '@/store/modules/flow'
import { addNewEdge, getInput } from '@/utils/flow'
const props = defineProps({
model: Object,
graphModel: Object,
properties: Object,
nowTime: Number,
});
const flowStore = useFlowStore()
const formData = reactive({
nodeParams: [
{ name: "loopNum", type: "input", input: null, quote: "" }
]
})
const quoteOptions = ref([])
const handleTypeChange = (index) => {
if (formData.nodeParams[index].type === 'input') {
formData.nodeParams[index].quote = ""
} else {
formData.nodeParams[index].input = null
const option = getInput(props.model.id)
if (option) {
quoteOptions.value = option
}
}
}
const rules = reactive({})
const emits = defineEmits(['bindRef', 'addToGroup', 'contentChange'])
const handleDragover = (e) => {
e.preventDefault()
}
const handleDrop = (e) => {
e.preventDefault()
e.stopPropagation();
let flowNode = e.dataTransfer.getData('flowNode');
flowNode = JSON.parse(flowNode)
const point = lf.getPointByClient(e.clientX, e.clientY)
const { type, ...other } = flowNode
const node = lf.addNode({
type,
x: point.canvasOverlayPosition.x,
y: point.canvasOverlayPosition.y,
properties: {
parentId: props.model.id,
...other
}
})
emits('addToGroup', node.id)
setTimeout(() => {
addNewEdge(props.model.id)
}, 50)
}
const dynamicForm = ref()
const setNodeProperties = async () => {
try {
const valid = await dynamicForm.value.validate()
if (valid) {
const data = toRaw(formData)
setTimeout(() => {
const properties = lf.getProperties(props.model.id)
window.lf.setProperties(props.model.id, {
...properties,
...data
})
}, 50)
}
} catch (error) {
dynamicForm.value.clearValidate()
}
}
const visibleChange = (value) => {
if (value) {
const option = getInput(props.model.id)
if (option) {
quoteOptions.value = option
}
}
}
watch(
() => props.properties,
() => {
if (props.properties.nodeParams && props.properties.nodeParams.length > 0) {
formData.nodeParams = props.properties.nodeParams
2025-09-09 16:37:38 +08:00
const option = getInput(props.model.id)
2025-09-04 16:41:54 +08:00
if (option) {
quoteOptions.value = option
}
}
}, {
immediate: true,
deep: true
}
)
onMounted(() => {
emits('bindRef', dynamicForm.value)
})
</script>
<style lang="scss" scoped>
.group__container {
width: 100%;
height: 100%;
background: #fff;
padding: 12px;
cursor: default;
border-radius: 12px;
border: 2px solid white;
box-shadow: 0 5px 15px 0#00000008;
display: flex;
flex-direction: column;
position: relative;
.title {
height: 40px;
}
:deep(.loop__container) {
height: 80px;
.el-input {
width: 92px;
}
.el-input-number {
width: 92px;
}
.el-select {
width: 92px;
}
.el-cascader {
width: 92px;
}
}
.child__container {
min-height: 80px;
flex: 1;
background-color: #f6f8fa;
border-radius: 8px;
}
.el-row {
align-items: end;
}
}
2025-08-21 14:11:58 +08:00
</style>