mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-27 20:42:52 +00:00
feat: Group field dialog
This commit is contained in:
parent
42d7aeb5bf
commit
2fc4a393ad
|
|
@ -17,7 +17,8 @@ class VariableListSerializer(serializers.Serializer):
|
|||
|
||||
class VariableGroupSerializer(serializers.Serializer):
|
||||
id = serializers.CharField(required=True, label=_("Group id"))
|
||||
group_name = serializers.CharField(required=True, label=_("group_name"))
|
||||
field = serializers.CharField(required=True, label=_("group_name"))
|
||||
label = serializers.CharField(required=True)
|
||||
variable_list = VariableListSerializer(many=True)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class BaseVariableAggregationNode(IVariableAggregation):
|
|||
'variable_to_json': self.set_variable_to_json,
|
||||
}
|
||||
|
||||
result = { item.get('group_name'):strategy_map[strategy](item.get('variable_list')) for item in group_list}
|
||||
result = { item.get('field'):strategy_map[strategy](item.get('variable_list')) for item in group_list}
|
||||
|
||||
return NodeResult({'result': result,**result},{})
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:title="isEdit ? $t('common.param.editParam') : $t('common.param.addParam')"
|
||||
v-model="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:destroy-on-close="true"
|
||||
:before-close="close"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
label-position="top"
|
||||
ref="fieldFormRef"
|
||||
:rules="rules"
|
||||
:model="form"
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('dynamicsForm.paramForm.field.label')"
|
||||
:required="true"
|
||||
prop="field"
|
||||
:rules="rules.field"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.field"
|
||||
:maxlength="64"
|
||||
:placeholder="$t('dynamicsForm.paramForm.field.placeholder')"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('dynamicsForm.paramForm.name.label')"
|
||||
:required="true"
|
||||
prop="label"
|
||||
:rules="rules.label"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.label"
|
||||
:maxlength="64"
|
||||
show-word-limit
|
||||
:placeholder="$t('dynamicsForm.paramForm.name.placeholder')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="close"> {{ $t('common.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
|
||||
{{ isEdit ? $t('common.save') : $t('common.add') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { t } from '@/locales'
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
||||
const fieldFormRef = ref()
|
||||
const loading = ref<boolean>(false)
|
||||
const isEdit = ref(false)
|
||||
const currentIndex = ref(null)
|
||||
const form = ref<any>({
|
||||
field: '',
|
||||
label: '',
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
label: [
|
||||
{ required: true, message: t('dynamicsForm.paramForm.name.requiredMessage'), trigger: 'blur' },
|
||||
],
|
||||
field: [
|
||||
{ required: true, message: t('dynamicsForm.paramForm.field.requiredMessage'), trigger: 'blur' },
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9_]+$/,
|
||||
message: t('dynamicsForm.paramForm.field.requiredMessage2'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
|
||||
const open = (data: any, index?: any) => {
|
||||
if (data) {
|
||||
form.value = cloneDeep(data)
|
||||
isEdit.value = true
|
||||
currentIndex.value = index
|
||||
}
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
dialogVisible.value = false
|
||||
isEdit.value = false
|
||||
currentIndex.value = null
|
||||
form.value = {
|
||||
field: '',
|
||||
label: '',
|
||||
}
|
||||
}
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
emit('refresh', form.value, currentIndex.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open, close })
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -39,11 +39,11 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div v-for="(group_list, gIndex) in form_data.group_list" :key="group_list.id" class="mb-8">
|
||||
<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">
|
||||
<el-form-item
|
||||
<!-- <el-form-item
|
||||
v-if="editingGroupIndex === gIndex"
|
||||
:prop="`group_list.${gIndex}.group_name`"
|
||||
:rules="groupNameRules(gIndex)"
|
||||
|
|
@ -58,10 +58,10 @@
|
|||
style="width: 200px; font-weight: bold;"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<span v-else class="font-bold">{{ group_list.group_name }}</span>
|
||||
</el-form-item> -->
|
||||
<span class="font-bold">{{ group.field }}</span>
|
||||
<div class="flex align-center">
|
||||
<el-button @click="editGroupName(gIndex)" size="large" link>
|
||||
<el-button @click="openAddOrEditDialog(group,gIndex)" size="large" link>
|
||||
<el-icon><EditPen /></el-icon>
|
||||
</el-button>
|
||||
<el-button @click="deleteGroup(gIndex)" size="large" link :disabled="form_data.group_list.length <= 1">
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="(item, vIndex) in group_list.variable_list" :key="item.v_id" class="mb-4">
|
||||
<div v-for="(item, vIndex) in group.variable_list" :key="item.v_id" class="mb-4">
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="21">
|
||||
<el-form-item
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
link
|
||||
size="large"
|
||||
class="mt-4"
|
||||
:disabled="group_list.variable_list.length <= 1"
|
||||
:disabled="group.variable_list.length <= 1"
|
||||
@click="deleteVariable(gIndex, vIndex)"
|
||||
>
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
|
|
@ -112,36 +112,37 @@
|
|||
|
||||
</el-card>
|
||||
</div>
|
||||
<el-button @click="addGroup" type="primary" size="large" link>
|
||||
<el-button @click="openAddOrEditDialog()" type="primary" size="large" link>
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"/>
|
||||
{{ $t('views.applicationWorkflow.nodes.variableAggregationNode.add') }}
|
||||
</el-button>
|
||||
</el-form>
|
||||
<GroupFieldDialog ref="GroupFieldDialogRef" @refresh="refreshFieldList"></GroupFieldDialog>
|
||||
</NodeContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { set, cloneDeep, debounce } from 'lodash'
|
||||
import { set, cloneDeep } from 'lodash'
|
||||
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
||||
import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
||||
|
||||
import { ref, computed, onMounted, nextTick } from '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'
|
||||
|
||||
const props = defineProps<{ nodeModel: any }>()
|
||||
const VariableAggregationRef = ref()
|
||||
const nodeCascaderRef = ref()
|
||||
const editingGroupIndex = ref<number | null>(null)
|
||||
const groupNameInputRef = ref()
|
||||
|
||||
const GroupFieldDialogRef = ref()
|
||||
|
||||
const form = {
|
||||
strategy: 'first_non_null',
|
||||
group_list: [
|
||||
{
|
||||
id: randomId(),
|
||||
group_name: 'Group1',
|
||||
label: 'Group1',
|
||||
field: 'Group1',
|
||||
variable_list: [
|
||||
{
|
||||
v_id: randomId(),
|
||||
|
|
@ -165,68 +166,53 @@ const form_data = computed({
|
|||
}
|
||||
})
|
||||
|
||||
const isGroupNameValid = ref<boolean>(true)
|
||||
const groupNameErrMsg = ref('')
|
||||
const tempGroupName = ref('')
|
||||
const inputFieldList = ref<any[]>([])
|
||||
|
||||
const editGroupName = async (gIndex: number) => {
|
||||
editingGroupIndex.value = gIndex
|
||||
tempGroupName.value = form_data.value.group_list[gIndex].group_name
|
||||
isGroupNameValid.value = true
|
||||
groupNameErrMsg.value = ''
|
||||
await nextTick()
|
||||
if (groupNameInputRef.value) {
|
||||
groupNameInputRef.value.focus()
|
||||
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)
|
||||
}
|
||||
|
||||
const groupNameRules = (gIndex: number) => [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.applicationWorkflow.nodes.variableAggregationNode.group.noneError'),
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
const trimmedValue = value?.trim() || ''
|
||||
|
||||
const hasDuplicate = form_data.value.group_list.some((item: any, index: number) =>
|
||||
index !== gIndex && item.group_name.trim() === trimmedValue
|
||||
)
|
||||
|
||||
if (hasDuplicate) {
|
||||
callback(new Error(t('views.applicationWorkflow.nodes.variableAggregationNode.group.dupError')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'change' // 实时触发
|
||||
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('views.applicationWorkflow.tip.paramErrorMessage') + data.field)
|
||||
return
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const validateGroupNameField = debounce((gIndex: number) => {
|
||||
VariableAggregationRef.value?.validateField(`group_list.${gIndex}.group_name`)
|
||||
}, 500)
|
||||
|
||||
const finishEditGroupName = async (gIndex: number) => {
|
||||
try {
|
||||
await VariableAggregationRef.value?.validateField(`group_list.${gIndex}.group_name`)
|
||||
const c_group_list = cloneDeep(form_data.value.group_list)
|
||||
const fields = c_group_list.map((item:any) => ({ label: item.group_name, value: item.group_name}))
|
||||
set(props.nodeModel.properties.config, 'fields', fields)
|
||||
editingGroupIndex.value = null
|
||||
} catch (error) {
|
||||
form_data.value.group_list[gIndex].group_name = tempGroupName.value
|
||||
editingGroupIndex.value = null
|
||||
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
|
||||
const fields = c_group_list.map((item:any) => ({ label: item.group_name, value: item.group_name}))
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -245,32 +231,22 @@ const deleteVariable = (gIndex: number,vIndex: number) => {
|
|||
form_data.value.group_list = c_group_list
|
||||
}
|
||||
|
||||
const addGroup = () => {
|
||||
let group_number = form_data.value.group_list.length + 1
|
||||
let group_name = `Group${group_number}`
|
||||
|
||||
while (form_data.value.group_list.some((item: any) => item.group_name === group_name)) {
|
||||
group_number++
|
||||
group_name = `Group${group_number}`
|
||||
}
|
||||
|
||||
const addGroup = (data: any) => {
|
||||
const c_group_list = cloneDeep(form_data.value.group_list)
|
||||
c_group_list.push({
|
||||
id: randomId(),
|
||||
group_name: group_name,
|
||||
field: data.field,
|
||||
label: data.label,
|
||||
variable_list: [{
|
||||
v_id: randomId(),
|
||||
variable: []
|
||||
}]
|
||||
})
|
||||
form_data.value.group_list = c_group_list
|
||||
const fields = c_group_list.map((item:any) => ({ label: item.group_name, value: item.group_name}))
|
||||
set(props.nodeModel.properties.config, 'fields', fields)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const validate = async () => {
|
||||
const validate_list = [
|
||||
...nodeCascaderRef.value.map((item:any)=>item.validate()),
|
||||
|
|
@ -288,7 +264,10 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
set(props.nodeModel, 'validate', validate)
|
||||
const fields = form_data.value.group_list.map((item:any) => ({ label: item.group_name, value: item.group_name}))
|
||||
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)
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue