feat: Workflow form nodes support reference assignment (#3866) #2439

This commit is contained in:
shaohuzhang1 2025-08-15 18:08:18 +08:00 committed by GitHub
parent f78027818d
commit a85c36f289
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 301 additions and 75 deletions

View File

@ -17,6 +17,19 @@ from application.flow.i_step_node import NodeResult
from application.flow.step_node.form_node.i_form_node import IFormNode from application.flow.step_node.form_node.i_form_node import IFormNode
def get_default_option(option_list, _type, value_field):
if option_list is not None and len(option_list) > 0:
default_value_list = [o.get(value_field) for o in option_list if o.get('default')]
if len(default_value_list) == 0:
return option_list[0].get(value_field)
else:
if _type == 'MultiSelect':
return default_value_list
else:
return default_value_list[0]
return []
def write_context(step_variable: Dict, global_variable: Dict, node, workflow): def write_context(step_variable: Dict, global_variable: Dict, node, workflow):
if step_variable is not None: if step_variable is not None:
for key in step_variable: for key in step_variable:
@ -44,6 +57,28 @@ class BaseFormNode(IFormNode):
for key in form_data: for key in form_data:
self.context[key] = form_data[key] self.context[key] = form_data[key]
def reset_field(self, field):
if ['SingleSelect', 'MultiSelect', 'RadioCard'].__contains__(field.get('input_type')):
if field.get('assignment_method') == 'ref_variables':
option_list = self.workflow_manage.get_reference_field(field.get('option_list')[0],
field.get('option_list')[1:])
field['option_list'] = option_list
field['default_value'] = get_default_option(option_list, field.get('input_type'),
field.get('value_field'))
reset_field = ['field', 'label', 'default_value']
for f in reset_field:
_value = field[f]
if isinstance(_value, str):
field[f] = self.workflow_manage.generate_prompt(_value)
else:
_label_value = _value.get('label')
_value['label'] = self.workflow_manage.generate_prompt(_label_value)
tooltip = _value.get('attrs').get('tooltip')
if tooltip is not None:
_value.get('attrs')['tooltip'] = self.workflow_manage.generate_prompt(tooltip)
return field
def execute(self, form_field_list, form_content_format, form_data, **kwargs) -> NodeResult: def execute(self, form_field_list, form_content_format, form_data, **kwargs) -> NodeResult:
if form_data is not None: if form_data is not None:
self.context['is_submit'] = True self.context['is_submit'] = True
@ -52,6 +87,7 @@ class BaseFormNode(IFormNode):
self.context[key] = form_data.get(key) self.context[key] = form_data.get(key)
else: else:
self.context['is_submit'] = False self.context['is_submit'] = False
form_field_list = [self.reset_field(field) for field in form_field_list]
form_setting = {"form_field_list": form_field_list, "runtime_node_id": self.runtime_node_id, form_setting = {"form_field_list": form_field_list, "runtime_node_id": self.runtime_node_id,
"chat_record_id": self.flow_params_serializer.data.get("chat_record_id"), "chat_record_id": self.flow_params_serializer.data.get("chat_record_id"),
"is_submit": self.context.get("is_submit", False)} "is_submit": self.context.get("is_submit", False)}
@ -60,6 +96,7 @@ class BaseFormNode(IFormNode):
form_content_format = self.workflow_manage.reset_prompt(form_content_format) form_content_format = self.workflow_manage.reset_prompt(form_content_format)
prompt_template = PromptTemplate.from_template(form_content_format, template_format='jinja2') prompt_template = PromptTemplate.from_template(form_content_format, template_format='jinja2')
value = prompt_template.format(form=form, context=context) value = prompt_template.format(form=form, context=context)
return NodeResult( return NodeResult(
{'result': value, 'form_field_list': form_field_list, 'form_content_format': form_content_format}, {}, {'result': value, 'form_field_list': form_field_list, 'form_content_format': form_content_format}, {},
_write_context=write_context) _write_context=write_context)

View File

@ -1,5 +1,28 @@
<template> <template>
<el-form-item> <el-form-item v-if="getModel">
<template #label>
<div class="flex-between">
{{ $t('dynamicsForm.AssignmentMethod.label', '赋值方式') }}
</div>
</template>
<el-row style="width: 100%" :gutter="10">
<el-radio-group v-model="formValue.assignment_method">
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list">{{
item.label
}}</el-radio>
</el-radio-group>
</el-row>
</el-form-item>
<NodeCascader
v-if="formValue.assignment_method == 'ref_variables'"
ref="nodeCascaderRef"
:nodeModel="model"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="formValue.option_list"
/>
<el-form-item v-if="formValue.assignment_method == 'custom'">
<template #label> <template #label>
<div class="flex-between"> <div class="flex-between">
{{ $t('dynamicsForm.Select.label') }} {{ $t('dynamicsForm.Select.label') }}
@ -51,6 +74,7 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="formValue.assignment_method == 'custom'"
class="defaultValueItem" class="defaultValueItem"
:label="$t('dynamicsForm.default.label')" :label="$t('dynamicsForm.default.label')"
:required="formValue.required" :required="formValue.required"
@ -92,8 +116,34 @@
</el-form-item> </el-form-item>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted } from 'vue' import { computed, onMounted, inject } from 'vue'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import { t } from '@/locales'
const getModel = inject('getModel') as any
const assignment_method_option_list = computed(() => {
const option_list = [
{
label: t('dynamicsForm.AssignmentMethod.custom.label', '自定义'),
value: 'custom',
},
]
if (getModel) {
option_list.push({
label: t('dynamicsForm.AssignmentMethod.ref_variables.label', '引用变量'),
value: 'ref_variables',
})
}
return option_list
})
const model = computed(() => {
if (getModel) {
return getModel()
} else {
return null
}
})
const props = defineProps<{ const props = defineProps<{
modelValue: any modelValue: any
}>() }>()
@ -128,17 +178,20 @@ const getData = () => {
text_field: 'label', text_field: 'label',
value_field: 'value', value_field: 'value',
option_list: formValue.value.option_list, option_list: formValue.value.option_list,
assignment_method: formValue.value.assignment_method || 'custom',
} }
} }
const rander = (form_data: any) => { const rander = (form_data: any) => {
formValue.value.option_list = form_data.option_list || [] formValue.value.option_list = form_data.option_list || []
formValue.value.default_value = form_data.default_value formValue.value.default_value = form_data.default_value
formValue.value.assignment_method = form_data.assignment_method || 'custom'
} }
defineExpose({ getData, rander }) defineExpose({ getData, rander })
onMounted(() => { onMounted(() => {
formValue.value.option_list = [] formValue.value.option_list = []
formValue.value.default_value = '' formValue.value.default_value = ''
formValue.value.assignment_method = 'custom'
if (formValue.value.show_default_value === undefined) { if (formValue.value.show_default_value === undefined) {
formValue.value.show_default_value = true formValue.value.show_default_value = true
} }

View File

@ -1,5 +1,28 @@
<template> <template>
<el-form-item> <el-form-item v-if="getModel">
<template #label>
<div class="flex-between">
{{ $t('dynamicsForm.AssignmentMethod.label', '赋值方式') }}
</div>
</template>
<el-row style="width: 100%" :gutter="10">
<el-radio-group v-model="formValue.assignment_method">
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list">{{
item.label
}}</el-radio>
</el-radio-group>
</el-row>
</el-form-item>
<NodeCascader
v-if="formValue.assignment_method == 'ref_variables'"
ref="nodeCascaderRef"
:nodeModel="model"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="formValue.option_list"
/>
<el-form-item v-if="formValue.assignment_method === 'custom'">
<template #label> <template #label>
<div class="flex-between"> <div class="flex-between">
{{ $t('dynamicsForm.Select.label') }} {{ $t('dynamicsForm.Select.label') }}
@ -51,7 +74,9 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="formValue.assignment_method === 'custom'"
class="defaultValueItem" class="defaultValueItem"
:label="$t('dynamicsForm.default.label')" :label="$t('dynamicsForm.default.label')"
:required="formValue.required" :required="formValue.required"
@ -83,8 +108,35 @@
</el-form-item> </el-form-item>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted } from 'vue' import { computed, onMounted, inject, ref } from 'vue'
import RadioCard from '@/components/dynamics-form/items/radio/RadioCard.vue' import RadioCard from '@/components/dynamics-form/items/radio/RadioCard.vue'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import { t } from '@/locales'
const getModel = inject('getModel') as any
const assignment_method_option_list = computed(() => {
const option_list = [
{
label: t('dynamicsForm.AssignmentMethod.custom.label', '自定义'),
value: 'custom',
},
]
if (getModel) {
option_list.push({
label: t('dynamicsForm.AssignmentMethod.ref_variables.label', '引用变量'),
value: 'ref_variables',
})
}
return option_list
})
const model = computed(() => {
if (getModel) {
return getModel()
} else {
return null
}
})
const props = defineProps<{ const props = defineProps<{
modelValue: any modelValue: any
}>() }>()
@ -121,17 +173,20 @@ const getData = () => {
text_field: 'label', text_field: 'label',
value_field: 'value', value_field: 'value',
option_list: formValue.value.option_list, option_list: formValue.value.option_list,
assignment_method: formValue.value.assignment_method || 'custom',
} }
} }
const rander = (form_data: any) => { const rander = (form_data: any) => {
formValue.value.option_list = form_data.option_list || [] formValue.value.option_list = form_data.option_list || []
formValue.value.default_value = form_data.default_value formValue.value.default_value = form_data.default_value
formValue.value.assignment_method = form_data.assignment_method || 'custom'
} }
defineExpose({ getData, rander }) defineExpose({ getData, rander })
onMounted(() => { onMounted(() => {
formValue.value.option_list = [] formValue.value.option_list = []
formValue.value.default_value = '' formValue.value.default_value = ''
formValue.value.assignment_method = 'custom'
if (formValue.value.show_default_value === undefined) { if (formValue.value.show_default_value === undefined) {
formValue.value.show_default_value = true formValue.value.show_default_value = true
} }

View File

@ -1,5 +1,28 @@
<template> <template>
<el-form-item> <el-form-item v-if="getModel">
<template #label>
<div class="flex-between">
{{ $t('dynamicsForm.AssignmentMethod.label', '赋值方式') }}
</div>
</template>
<el-row style="width: 100%" :gutter="10">
<el-radio-group v-model="formValue.assignment_method">
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list">{{
item.label
}}</el-radio>
</el-radio-group>
</el-row>
</el-form-item>
<NodeCascader
v-if="formValue.assignment_method == 'ref_variables'"
ref="nodeCascaderRef"
:nodeModel="model"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="formValue.option_list"
/>
<el-form-item v-if="formValue.assignment_method == 'custom'">
<template #label> <template #label>
<div class="flex-between"> <div class="flex-between">
{{ $t('dynamicsForm.Select.label') }} {{ $t('dynamicsForm.Select.label') }}
@ -52,6 +75,7 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="formValue.assignment_method == 'custom'"
class="defaultValueItem" class="defaultValueItem"
:required="formValue.required" :required="formValue.required"
prop="default_value" prop="default_value"
@ -85,8 +109,34 @@
</el-form-item> </el-form-item>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted } from 'vue' import { computed, onMounted, inject } from 'vue'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import { t } from '@/locales'
const getModel = inject('getModel') as any
const assignment_method_option_list = computed(() => {
const option_list = [
{
label: t('dynamicsForm.AssignmentMethod.custom.label', '自定义'),
value: 'custom',
},
]
if (getModel) {
option_list.push({
label: t('dynamicsForm.AssignmentMethod.ref_variables.label', '引用变量'),
value: 'ref_variables',
})
}
return option_list
})
const model = computed(() => {
if (getModel) {
return getModel()
} else {
return null
}
})
const props = defineProps<{ const props = defineProps<{
modelValue: any modelValue: any
}>() }>()
@ -121,18 +171,21 @@ const getData = () => {
text_field: 'label', text_field: 'label',
value_field: 'value', value_field: 'value',
option_list: formValue.value.option_list, option_list: formValue.value.option_list,
assignment_method: formValue.value.assignment_method || 'custom',
} }
} }
const rander = (form_data: any) => { const rander = (form_data: any) => {
formValue.value.option_list = form_data.option_list || [] formValue.value.option_list = form_data.option_list || []
formValue.value.default_value = form_data.default_value formValue.value.default_value = form_data.default_value
formValue.value.show_default_value = form_data.show_default_value formValue.value.show_default_value = form_data.show_default_value
formValue.value.assignment_method = form_data.assignment_method || 'custom'
} }
defineExpose({ getData, rander }) defineExpose({ getData, rander })
onMounted(() => { onMounted(() => {
formValue.value.option_list = [] formValue.value.option_list = []
formValue.value.default_value = '' formValue.value.default_value = ''
formValue.value.assignment_method = 'custom'
if (formValue.value.show_default_value === undefined) { if (formValue.value.show_default_value === undefined) {
formValue.value.show_default_value = true formValue.value.show_default_value = true
} }

View File

@ -10,11 +10,11 @@
style="--el-card-padding: 12px 16px" style="--el-card-padding: 12px 16px"
:class="[ :class="[
inputDisabled ? 'is-disabled' : '', inputDisabled ? 'is-disabled' : '',
modelValue == item[valueField] ? 'active' : '' modelValue == item[valueField] ? 'active' : '',
]" ]"
@click="inputDisabled ? () => {} : selected(item[valueField])" @click="inputDisabled ? () => {} : selected(item[valueField])"
:innerHTML="item[textField]"
> >
{{ item[textField] }}
</el-card> </el-card>
</el-col> </el-col>
</template> </template>

View File

@ -9,46 +9,46 @@ export default {
DatePicker: 'Date Picker', DatePicker: 'Date Picker',
JsonInput: 'JSON', JsonInput: 'JSON',
RadioCard: 'Radio Card', RadioCard: 'Radio Card',
RadioRow: 'Radio Row' RadioRow: 'Radio Row',
}, },
default: { default: {
label: 'Default', label: 'Default',
placeholder: 'Please enter a default', placeholder: 'Please enter a default',
requiredMessage: ' is a required property', requiredMessage: ' is a required property',
show: 'Show Default' show: 'Show Default',
}, },
tip: { tip: {
requiredMessage: 'cannot be empty', requiredMessage: 'cannot be empty',
jsonMessage: 'Incorrect JSON format' jsonMessage: 'Incorrect JSON format',
}, },
searchBar: { searchBar: {
placeholder: 'Please enter keywords to search' placeholder: 'Please enter keywords to search',
}, },
paramForm: { paramForm: {
field: { field: {
label: 'Parameter', label: 'Parameter',
placeholder: 'Please enter a parameter', placeholder: 'Please enter a parameter',
requiredMessage: 'Parameter is a required property', requiredMessage: 'Parameter is a required property',
requiredMessage2: 'Only letters, numbers, and underscores are allowed' requiredMessage2: 'Only letters, numbers, and underscores are allowed',
}, },
name: { name: {
label: 'Name', label: 'Name',
placeholder: 'Please enter a name', placeholder: 'Please enter a name',
requiredMessage: 'Name is a required property' requiredMessage: 'Name is a required property',
}, },
tooltip: { tooltip: {
label: 'Tooltip', label: 'Tooltip',
placeholder: 'Please enter a tooltip' placeholder: 'Please enter a tooltip',
}, },
required: { required: {
label: 'Required', label: 'Required',
requiredMessage: 'Required is a required property' requiredMessage: 'Required is a required property',
}, },
input_type: { input_type: {
label: 'Type', label: 'Type',
placeholder: 'Please select a type', placeholder: 'Please select a type',
requiredMessage: 'Type is a required property' requiredMessage: 'Type is a required property',
} },
}, },
DatePicker: { DatePicker: {
placeholder: 'Select Date', placeholder: 'Select Date',
@ -58,35 +58,35 @@ export default {
datetime: 'Date Time', datetime: 'Date Time',
dataType: { dataType: {
label: 'Date Type', label: 'Date Type',
placeholder: 'Please select a date type' placeholder: 'Please select a date type',
}, },
format: { format: {
label: 'Format', label: 'Format',
placeholder: 'Please select a format' placeholder: 'Please select a format',
} },
}, },
Select: { Select: {
label: 'Option Value', label: 'Option Value',
placeholder: 'Please enter an option value' placeholder: 'Please enter an option value',
}, },
tag: { tag: {
label: 'Tag', label: 'Tag',
placeholder: 'Please enter an option label' placeholder: 'Please enter an option label',
}, },
Slider: { Slider: {
showInput: { showInput: {
label: 'Show Input Box' label: 'Show Input Box',
}, },
valueRange: { valueRange: {
label: 'Value Range', label: 'Value Range',
minRequired: 'Minimum value is required', minRequired: 'Minimum value is required',
maxRequired: 'Maximum value is required' maxRequired: 'Maximum value is required',
}, },
step: { step: {
label: 'Step Value', label: 'Step Value',
requiredMessage1: 'Step value is required', requiredMessage1: 'Step value is required',
requiredMessage2: 'Step value cannot be 0' requiredMessage2: 'Step value cannot be 0',
} },
}, },
TextInput: { TextInput: {
length: { length: {
@ -96,7 +96,16 @@ export default {
requiredMessage1: 'Length must be between', requiredMessage1: 'Length must be between',
requiredMessage2: 'and', requiredMessage2: 'and',
requiredMessage3: 'characters', requiredMessage3: 'characters',
requiredMessage4: 'Text length is a required parameter' requiredMessage4: 'Text length is a required parameter',
} },
} },
AssignmentMethod: {
label: 'Assignment Method',
custom: {
label: 'Custom',
},
ref_variables: {
label: 'Reference Variables',
},
},
} }

View File

@ -9,46 +9,46 @@ export default {
DatePicker: '日期', DatePicker: '日期',
JsonInput: 'JSON文本框', JsonInput: 'JSON文本框',
RadioCard: '选项卡', RadioCard: '选项卡',
RadioRow: '单行选项卡' RadioRow: '单行选项卡',
}, },
default: { default: {
label: '默认值', label: '默认值',
placeholder: '请输入默认值', placeholder: '请输入默认值',
requiredMessage: '为必填属性', requiredMessage: '为必填属性',
show: '显示默认值' show: '显示默认值',
}, },
tip: { tip: {
requiredMessage: '不能为空', requiredMessage: '不能为空',
jsonMessage: 'JSON格式不正确' jsonMessage: 'JSON格式不正确',
}, },
searchBar: { searchBar: {
placeholder: '请输入关键字搜索' placeholder: '请输入关键字搜索',
}, },
paramForm: { paramForm: {
field: { field: {
label: '参数', label: '参数',
placeholder: '请输入参数', placeholder: '请输入参数',
requiredMessage: '参数 为必填属性', requiredMessage: '参数 为必填属性',
requiredMessage2: '只能输入字母数字和下划线' requiredMessage2: '只能输入字母数字和下划线',
}, },
name: { name: {
label: '显示名称', label: '显示名称',
placeholder: '请输入显示名称', placeholder: '请输入显示名称',
requiredMessage: '显示名称 为必填属性' requiredMessage: '显示名称 为必填属性',
}, },
tooltip: { tooltip: {
label: '参数提示说明', label: '参数提示说明',
placeholder: '请输入参数提示说明' placeholder: '请输入参数提示说明',
}, },
required: { required: {
label: '是否必填', label: '是否必填',
requiredMessage: '是否必填 为必填属性' requiredMessage: '是否必填 为必填属性',
}, },
input_type: { input_type: {
label: '组件类型', label: '组件类型',
placeholder: '请选择组件类型', placeholder: '请选择组件类型',
requiredMessage: '组建类型 为必填属性' requiredMessage: '组建类型 为必填属性',
} },
}, },
DatePicker: { DatePicker: {
placeholder: '选择日期', placeholder: '选择日期',
@ -58,35 +58,35 @@ export default {
datetime: '日期时间', datetime: '日期时间',
dataType: { dataType: {
label: '时间类型', label: '时间类型',
placeholder: '请选择时间类型' placeholder: '请选择时间类型',
}, },
format: { format: {
label: '格式', label: '格式',
placeholder: '请选择格式' placeholder: '请选择格式',
} },
}, },
Select: { Select: {
label: '选项值', label: '选项值',
placeholder: '请输入选项值' placeholder: '请输入选项值',
}, },
tag: { tag: {
label: '标签', label: '标签',
placeholder: '请输入选项标签' placeholder: '请输入选项标签',
}, },
Slider: { Slider: {
showInput: { showInput: {
label: '是否带输入框' label: '是否带输入框',
}, },
valueRange: { valueRange: {
label: '取值范围', label: '取值范围',
minRequired: '最小值必填', minRequired: '最小值必填',
maxRequired: '最大值必填' maxRequired: '最大值必填',
}, },
step: { step: {
label: '步长值', label: '步长值',
requiredMessage1: '步长值必填', requiredMessage1: '步长值必填',
requiredMessage2: '步长不能为0' requiredMessage2: '步长不能为0',
} },
}, },
TextInput: { TextInput: {
length: { length: {
@ -96,7 +96,16 @@ export default {
requiredMessage1: '长度在', requiredMessage1: '长度在',
requiredMessage2: '到', requiredMessage2: '到',
requiredMessage3: '个字符', requiredMessage3: '个字符',
requiredMessage4: '文本长度为必填参数' requiredMessage4: '文本长度为必填参数',
} },
} },
AssignmentMethod: {
label: '赋值方式',
custom: {
label: '自定义',
},
ref_variables: {
label: '引用变量 ',
},
},
} }

View File

@ -9,46 +9,46 @@ export default {
DatePicker: '日期選擇器', DatePicker: '日期選擇器',
JsonInput: 'JSON文字框', JsonInput: 'JSON文字框',
RadioCard: '選項卡', RadioCard: '選項卡',
RadioRow: '單行選項卡' RadioRow: '單行選項卡',
}, },
default: { default: {
label: '預設值', label: '預設值',
placeholder: '請輸入預設值', placeholder: '請輸入預設值',
requiredMessage: '為必填屬性', requiredMessage: '為必填屬性',
show: '顯示預設值' show: '顯示預設值',
}, },
tip: { tip: {
requiredMessage: '不能為空', requiredMessage: '不能為空',
jsonMessage: 'JSON格式不正確' jsonMessage: 'JSON格式不正確',
}, },
searchBar: { searchBar: {
placeholder: '請輸入關鍵字搜索' placeholder: '請輸入關鍵字搜索',
}, },
paramForm: { paramForm: {
field: { field: {
label: '參數', label: '參數',
placeholder: '請輸入參數', placeholder: '請輸入參數',
requiredMessage: '參數 為必填屬性', requiredMessage: '參數 為必填屬性',
requiredMessage2: '只能輸入字母、數字和底線' requiredMessage2: '只能輸入字母、數字和底線',
}, },
name: { name: {
label: '顯示名稱', label: '顯示名稱',
placeholder: '請輸入顯示名稱', placeholder: '請輸入顯示名稱',
requiredMessage: '顯示名稱 為必填屬性' requiredMessage: '顯示名稱 為必填屬性',
}, },
tooltip: { tooltip: {
label: '參數提示說明', label: '參數提示說明',
placeholder: '請輸入參數提示說明' placeholder: '請輸入參數提示說明',
}, },
required: { required: {
label: '是否必填', label: '是否必填',
requiredMessage: '是否必填 為必填屬性' requiredMessage: '是否必填 為必填屬性',
}, },
input_type: { input_type: {
label: '組件類型', label: '組件類型',
placeholder: '請選擇組件類型', placeholder: '請選擇組件類型',
requiredMessage: '組件類型 為必填屬性' requiredMessage: '組件類型 為必填屬性',
} },
}, },
DatePicker: { DatePicker: {
placeholder: '選擇日期', placeholder: '選擇日期',
@ -58,35 +58,35 @@ export default {
datetime: '日期時間', datetime: '日期時間',
dataType: { dataType: {
label: '時間類型', label: '時間類型',
placeholder: '請選擇時間類型' placeholder: '請選擇時間類型',
}, },
format: { format: {
label: '格式', label: '格式',
placeholder: '請選擇格式' placeholder: '請選擇格式',
} },
}, },
Select: { Select: {
label: '選項值', label: '選項值',
placeholder: '請輸入選項值' placeholder: '請輸入選項值',
}, },
tag: { tag: {
label: '標籤', label: '標籤',
placeholder: '請輸入選項標籤' placeholder: '請輸入選項標籤',
}, },
Slider: { Slider: {
showInput: { showInput: {
label: '是否帶輸入框' label: '是否帶輸入框',
}, },
valueRange: { valueRange: {
label: '取值範圍', label: '取值範圍',
minRequired: '最小值必填', minRequired: '最小值必填',
maxRequired: '最大值必填' maxRequired: '最大值必填',
}, },
step: { step: {
label: '步長值', label: '步長值',
requiredMessage1: '步長值必填', requiredMessage1: '步長值必填',
requiredMessage2: '步長不能為0' requiredMessage2: '步長不能為0',
} },
}, },
TextInput: { TextInput: {
length: { length: {
@ -96,7 +96,16 @@ export default {
requiredMessage1: '長度在', requiredMessage1: '長度在',
requiredMessage2: '到', requiredMessage2: '到',
requiredMessage3: '個字元', requiredMessage3: '個字元',
requiredMessage4: '文字長度為必填參數' requiredMessage4: '文字長度為必填參數',
} },
} },
AssignmentMethod: {
label: '賦值方式',
custom: {
label: '自定義',
},
ref_variables: {
label: '引用變量',
},
},
} }

View File

@ -147,13 +147,14 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
import AddFormCollect from '@/workflow/common/AddFormCollect.vue' import AddFormCollect from '@/workflow/common/AddFormCollect.vue'
import EditFormCollect from '@/workflow/common/EditFormCollect.vue' import EditFormCollect from '@/workflow/common/EditFormCollect.vue'
import { type FormInstance } from 'element-plus' import { type FormInstance } from 'element-plus'
import { ref, onMounted, computed } from 'vue' import { ref, onMounted, computed, provide } from 'vue'
import { input_type_list } from '@/components/dynamics-form/constructor/data' import { input_type_list } from '@/components/dynamics-form/constructor/data'
import { MsgError } from '@/utils/message' import { MsgError } from '@/utils/message'
import { set, cloneDeep } from 'lodash' import { set, cloneDeep } from 'lodash'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { t } from '@/locales' import { t } from '@/locales'
const props = defineProps<{ nodeModel: any }>() const props = defineProps<{ nodeModel: any }>()
provide('getModel', () => props.nodeModel)
const formNodeFormRef = ref<FormInstance>() const formNodeFormRef = ref<FormInstance>()
const tableRef = ref() const tableRef = ref()
const editFormField = (form_field_data: any, field_index: number) => { const editFormField = (form_field_data: any, field_index: number) => {