MaxKB/ui/src/workflow/nodes/variable-aggregation-node/index.vue
2025-12-05 18:10:54 +08:00

284 lines
9.3 KiB
Vue

<template>
<NodeContainer :nodeModel="nodeModel">
<h5 class="title-decoration-1 mb-8">{{ $t('workflow.nodeSetting') }}</h5>
<el-form
@submit.prevent
:model="form_data"
label-position="top"
require-asterisk-position="right"
label-width="auto"
ref="VariableAggregationRef"
hide-required-asterisk
>
<el-form-item
:label="$t('workflow.nodes.variableAggregationNode.Strategy')"
:rules="{
required: true,
trigger: 'change',
}"
>
<template #label>
<div class="flex-between">
<div>
<span
>{{ $t('workflow.nodes.variableAggregationNode.Strategy') }}
<span class="color-danger">*</span>
</span>
</div>
</div>
</template>
<el-select v-model="form_data.strategy" :teleported="false">
<el-option
:label="t('workflow.nodes.variableAggregationNode.placeholder')"
value="first_non_null"
/>
<el-option
:label="t('workflow.nodes.variableAggregationNode.placeholder1')"
value="variable_to_json"
/>
</el-select>
</el-form-item>
<div v-for="(group, gIndex) in form_data.group_list" :key="group.id" class="mb-8">
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
<div class="flex-between mb-12">
<span class="ellipsis" :title="group.label">{{ group.label }}</span>
<div class="flex align-center" style="margin-right: -3px">
<el-button @click="openAddOrEditDialog(group, gIndex)" link>
<el-icon><EditPen /></el-icon>
</el-button>
<el-button
@click="deleteGroup(gIndex)"
link
:disabled="form_data.group_list.length <= 1"
>
<AppIcon iconName="app-delete"></AppIcon>
</el-button>
</div>
</div>
<VueDraggable
ref="el"
v-bind:modelValue="group.variable_list"
:disabled="group.variable_list.length === 1"
handle=".handle"
:animation="150"
ghostClass="ghost"
@end="onEnd($event, gIndex)"
>
<div v-for="(item, vIndex) in group.variable_list" :key="item.v_id" class="drag-card">
<el-row class="handle">
<el-col :span="22" class="flex">
<img src="@/assets/sort.svg" alt="" height="15" class="mr-4 mt-8" />
<el-form-item
:prop="`group_list.${gIndex}.variable_list.${vIndex}.variable`"
:rules="{
type: 'array',
required: true,
message: $t('workflow.variable.placeholder'),
trigger: 'change',
}"
>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
style="width: 200px"
:placeholder="$t('workflow.variable.placeholder')"
v-model="item.variable"
/>
</el-form-item>
</el-col>
<el-col :span="2">
<el-button
link
class="mt-4 ml-4"
:disabled="group.variable_list.length <= 1"
@click="deleteVariable(gIndex, vIndex)"
>
<AppIcon iconName="app-delete"></AppIcon>
</el-button>
</el-col>
</el-row>
</div>
</VueDraggable>
<el-button @click="addVariable(gIndex)" type="primary" size="large" link>
<AppIcon iconName="app-add-outlined" class="mr-4" />
{{ $t('common.add') }}
</el-button>
</el-card>
</div>
<el-button @click="openAddOrEditDialog()" type="primary" size="large" link>
<AppIcon iconName="app-add-outlined" class="mr-4" />
{{ $t('workflow.nodes.variableAggregationNode.addGroup') }}
</el-button>
</el-form>
<GroupFieldDialog ref="GroupFieldDialogRef" @refresh="refreshFieldList"></GroupFieldDialog>
</NodeContainer>
</template>
<script setup lang="ts">
import { set, cloneDeep } from 'lodash'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import NodeContainer from '@/workflow/common/NodeContainer.vue'
import GroupFieldDialog from './component/GroupFieldDialog.vue'
import { ref, computed, onMounted } from 'vue'
import { isLastNode } from '@/workflow/common/data'
import { t } from '@/locales'
import { randomId } from '@/utils/common'
import { MsgError } from '@/utils/message'
import { VueDraggable } from 'vue-draggable-plus'
const props = defineProps<{ nodeModel: any }>()
const VariableAggregationRef = ref()
const nodeCascaderRef = ref()
const GroupFieldDialogRef = ref()
const form = {
strategy: 'first_non_null',
group_list: [
{
id: randomId(),
label: 'Group1',
field: 'Group1',
variable_list: [
{
v_id: randomId(),
variable: [],
},
],
},
],
}
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 inputFieldList = ref<any[]>([])
function openAddOrEditDialog(group?: any, index?: any) {
let data = null
if (group && index !== undefined) {
data = {
field: group.field,
label: group.label,
}
}
GroupFieldDialogRef.value.open(data, index)
}
function refreshFieldList(data: any, index: any) {
for (let i = 0; i < inputFieldList.value.length; i++) {
if (inputFieldList.value[i].field === data.field && index !== i) {
MsgError(t('workflow.tip.paramErrorMessage') + data.field)
return
}
}
if ([undefined, null].includes(index)) {
inputFieldList.value.push(data)
addGroup(data)
} else {
inputFieldList.value.splice(index, 1, data)
editGroupDesc(data, index)
}
GroupFieldDialogRef.value.close()
const fields = [...inputFieldList.value.map((item) => ({ label: item.label, value: item.field }))]
set(props.nodeModel.properties.config, 'fields', fields)
}
const editGroupDesc = (data: any, gIndex: any) => {
const c_group_list = cloneDeep(form_data.value.group_list)
c_group_list[gIndex].field = data.field
c_group_list[gIndex].label = data.label
form_data.value.group_list = c_group_list
}
const deleteGroup = (gIndex: number) => {
const c_group_list = cloneDeep(form_data.value.group_list)
c_group_list.splice(gIndex, 1)
form_data.value.group_list = c_group_list
inputFieldList.value.splice(gIndex, 1)
const fields = c_group_list.map((item: any) => ({ label: item.label, value: item.field }))
set(props.nodeModel.properties.config, 'fields', fields)
}
const addVariable = (gIndex: number) => {
const c_group_list = cloneDeep(form_data.value.group_list)
c_group_list[gIndex].variable_list.push({
v_id: randomId(),
variable: [],
})
form_data.value.group_list = c_group_list
}
const deleteVariable = (gIndex: number, vIndex: number) => {
const c_group_list = cloneDeep(form_data.value.group_list)
c_group_list[gIndex].variable_list.splice(vIndex, 1)
form_data.value.group_list = c_group_list
}
const addGroup = (data: any) => {
const c_group_list = cloneDeep(form_data.value.group_list)
c_group_list.push({
id: randomId(),
field: data.field,
label: data.label,
variable_list: [
{
v_id: randomId(),
variable: [],
},
],
})
form_data.value.group_list = c_group_list
}
const validate = async () => {
const validate_list = [
...nodeCascaderRef.value.map((item: any) => item.validate()),
VariableAggregationRef.value?.validate(),
]
return Promise.all(validate_list).catch((err) => {
return Promise.reject({ node: props.nodeModel, errMessage: err })
})
}
function onEnd(event: any, gIndex: number) {
const { oldIndex, newIndex } = event
if (oldIndex === undefined || newIndex === undefined) return
const list = cloneDeep(props.nodeModel.properties.node_data.group_list[gIndex].variable_list)
const newInstance = { ...list[oldIndex] }
const oldInstance = { ...list[newIndex] }
list[newIndex] = newInstance
list[oldIndex] = oldInstance
set(props.nodeModel.properties.node_data.group_list[gIndex], 'variable_list', list)
}
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)
if (props.nodeModel.properties.node_data.group_list) {
inputFieldList.value = form_data.value.group_list.map((item: any) => ({
label: item.label,
field: item.field,
}))
}
const fields = form_data.value.group_list.map((item: any) => ({
label: item.label,
value: item.field,
}))
set(props.nodeModel.properties.config, 'fields', fields)
})
</script>
<style lang="scss" scoped></style>