UnisKB/ui/src/workflow/nodes/loop-node/index.vue

147 lines
4.8 KiB
Vue
Raw Normal View History

2025-09-16 07:49:49 +00:00
<template>
<NodeContainer :nodeModel="nodeModel">
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
<el-form
@submit.prevent
:model="form_data"
label-position="top"
require-asterisk-position="right"
label-width="auto"
ref="replyNodeFormRef"
>
<el-form-item
2025-09-17 10:22:08 +00:00
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.label')"
2025-09-16 07:49:49 +00:00
@click.prevent
2025-09-17 10:22:08 +00:00
prop="loop_type"
:rules="{
message: $t('views.applicationWorkflow.nodes.loopNode.loopType.requiredMessage'),
trigger: 'change',
required: true,
}"
2025-09-16 07:49:49 +00:00
>
<el-select v-model="form_data.loop_type" type="small">
<el-option
2025-09-17 10:22:08 +00:00
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.arrayLoop')"
2025-09-16 07:49:49 +00:00
value="ARRAY"
/>
<el-option
2025-09-17 10:22:08 +00:00
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.numberLoop')"
2025-09-16 07:49:49 +00:00
value="NUMBER"
/>
<el-option
2025-09-17 10:22:08 +00:00
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.infiniteLoop')"
2025-09-16 07:49:49 +00:00
value="LOOP"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="form_data.loop_type == 'ARRAY'"
2025-09-17 10:22:08 +00:00
:label="$t('views.applicationWorkflow.nodes.loopNode.loopArray.label')"
2025-09-16 07:49:49 +00:00
@click.prevent
prop="array"
:rules="{
2025-09-17 10:22:08 +00:00
message: $t('views.applicationWorkflow.nodes.loopNode.loopArray.requiredMessage'),
2025-09-16 07:49:49 +00:00
trigger: 'blur',
required: true,
}"
>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
class="w-full"
2025-09-17 10:22:08 +00:00
:placeholder="$t('views.applicationWorkflow.nodes.loopNode.loopArray.placeholder')"
2025-09-16 07:49:49 +00:00
v-model="form_data.array"
/>
</el-form-item>
<el-form-item
v-else-if="form_data.loop_type == 'NUMBER'"
2025-09-17 10:22:08 +00:00
:label="$t('views.applicationWorkflow.nodes.loopNode.loopArray.label')"
2025-09-16 07:49:49 +00:00
@click.prevent
prop="number"
:rules="{
2025-09-17 10:22:08 +00:00
message: $t('views.applicationWorkflow.nodes.loopNode.loopArray.requiredMessage'),
2025-09-16 07:49:49 +00:00
trigger: 'blur',
required: true,
}"
>
<el-input-number v-model="form_data.number" :min="1" />
</el-form-item>
</el-form>
</el-card>
</NodeContainer>
</template>
<script setup lang="ts">
import { set } from 'lodash'
import NodeContainer from '@/workflow/common/NodeContainer.vue'
import { ref, computed, onMounted } from 'vue'
import { isLastNode } from '@/workflow/common/data'
import { loopBodyNode, loopStartNode } from '@/workflow/common/data'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
const props = defineProps<{ nodeModel: any }>()
const form = {
loop_type: 'ARRAY',
array: [],
number: 1,
}
const form_data = computed({
get: () => {
if (props.nodeModel.properties.node_data) {
return props.nodeModel.properties.node_data
} else {
set(props.nodeModel.properties, 'node_data', form)
}
return props.nodeModel.properties.node_data
},
set: (value) => {
set(props.nodeModel.properties, 'node_data', value)
},
})
const replyNodeFormRef = ref()
const nodeCascaderRef = ref()
const validate = () => {
return Promise.all([
nodeCascaderRef.value ? nodeCascaderRef.value.validate() : Promise.resolve(''),
replyNodeFormRef.value?.validate(),
]).catch((err: any) => {
return Promise.reject({ node: props.nodeModel, errMessage: err })
})
}
onMounted(() => {
if (typeof props.nodeModel.properties.node_data?.is_result === 'undefined') {
if (isLastNode(props.nodeModel)) {
set(props.nodeModel.properties.node_data, 'is_result', true)
}
}
set(props.nodeModel, 'validate', validate)
const nodeOutgoingNode = props.nodeModel.graphModel.getNodeOutgoingNode(props.nodeModel.id)
if (!nodeOutgoingNode.some((item: any) => item.type == loopBodyNode.type)) {
let workflow = { nodes: [loopStartNode], edges: [] }
if (props.nodeModel.properties.node_data.loop_body) {
workflow = props.nodeModel.properties.node_data.loop_body
}
const nodeModel = props.nodeModel.graphModel.addNode({
type: loopBodyNode.type,
properties: {
...loopBodyNode.properties,
workflow: workflow,
loop_node_id: props.nodeModel.id,
},
x: props.nodeModel.x,
y: props.nodeModel.y + loopBodyNode.height,
})
props.nodeModel.graphModel.addEdge({
type: 'loop-edge',
sourceNodeId: props.nodeModel.id,
sourceAnchorId: props.nodeModel.id + '_children',
targetNodeId: nodeModel.id,
virtual: true,
})
}
})
</script>
<style lang="scss" scoped></style>