Skip to content

Commit 67bb0a0

Browse files
authored
feat: Support single line multi select cards (#3976)
1 parent b1dcdcb commit 67bb0a0

File tree

6 files changed

+371
-3
lines changed

6 files changed

+371
-3
lines changed

apps/application/flow/step_node/form_node/impl/base_form_node.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,22 @@
1616
from application.flow.i_step_node import NodeResult
1717
from application.flow.step_node.form_node.i_form_node import IFormNode
1818

19+
multi_select_list = [
20+
'MultiSelect',
21+
'MultiRow'
22+
]
23+
1924

2025
def get_default_option(option_list, _type, value_field):
2126
try:
2227
if option_list is not None and isinstance(option_list, list) and len(option_list) > 0:
2328
default_value_list = [o.get(value_field) for o in option_list if o.get('default')]
2429
if len(default_value_list) == 0:
2530
return [option_list[0].get(
26-
value_field)] if _type == 'MultiSelect' else option_list[0].get(
31+
value_field)] if multi_select_list.__contains__(_type) else option_list[0].get(
2732
value_field)
2833
else:
29-
if _type == 'MultiSelect':
34+
if multi_select_list.__contains__(_type):
3035
return default_value_list
3136
else:
3237
return default_value_list[0]
@@ -84,7 +89,7 @@ def reset_field(self, field):
8489
if tooltip is not None:
8590
_value.get('attrs')['tooltip'] = generate_prompt(self.workflow_manage, tooltip)
8691

87-
if ['SingleSelect', 'MultiSelect', 'RadioCard', 'RadioRow'].__contains__(field.get('input_type')):
92+
if ['SingleSelect', 'MultiSelect', 'RadioCard', 'RadioRow', 'MultiRow'].__contains__(field.get('input_type')):
8893
if field.get('assignment_method') == 'ref_variables':
8994
option_list = self.workflow_manage.get_reference_field(field.get('option_list')[0],
9095
field.get('option_list')[1:])

ui/src/components/dynamics-form/constructor/data.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const input_type_list = [
3232
label: t('dynamicsForm.input_type_list.RadioRow'),
3333
value: 'RadioRow',
3434
},
35+
{
36+
label: t('dynamicsForm.input_type_list.MultiRow'),
37+
value: 'MultiRow',
38+
},
3539
{
3640
label: t('dynamicsForm.input_type_list.Slider'),
3741
value: 'Slider',
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
<template>
2+
<el-form-item v-if="getModel">
3+
<template #label>
4+
<div class="flex-between">
5+
{{ $t('dynamicsForm.AssignmentMethod.label', '赋值方式') }}
6+
</div>
7+
</template>
8+
9+
<el-row style="width: 100%" :gutter="10">
10+
<el-radio-group @change="formValue.option_list = []" v-model="formValue.assignment_method">
11+
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list"
12+
>{{ item.label }}
13+
<el-popover
14+
width="300px"
15+
v-if="item.value == 'ref_variables'"
16+
class="box-item"
17+
placement="top-start"
18+
>
19+
{{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover') }}:<br />
20+
[<br />
21+
{<br />
22+
"label": "xx",<br />
23+
"value": "xx",<br />
24+
"default": false<br />
25+
}<br />
26+
]<br />
27+
label: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_label') }}
28+
{{ $t('common.required') }}<br />
29+
value: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_value') }}
30+
{{ $t('common.required') }}<br />
31+
default:{{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_default') }}
32+
<template #reference>
33+
<el-icon><InfoFilled /></el-icon>
34+
</template>
35+
</el-popover>
36+
</el-radio>
37+
</el-radio-group>
38+
</el-row>
39+
</el-form-item>
40+
<el-form-item
41+
v-if="formValue.assignment_method == 'ref_variables'"
42+
:required="true"
43+
prop="option_list"
44+
:rules="[default_ref_variables_value_rule]"
45+
>
46+
<NodeCascader
47+
ref="nodeCascaderRef"
48+
:nodeModel="model"
49+
class="w-full"
50+
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
51+
v-model="formValue.option_list"
52+
/>
53+
</el-form-item>
54+
<el-form-item v-if="formValue.assignment_method == 'custom'">
55+
<template #label>
56+
<div class="flex-between">
57+
{{ $t('dynamicsForm.Select.label') }}
58+
<el-button link type="primary" @click.stop="addOption()">
59+
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
60+
{{ $t('common.add') }}
61+
</el-button>
62+
</div>
63+
</template>
64+
65+
<el-row style="width: 100%" :gutter="10">
66+
<el-col :span="10">
67+
<div class="grid-content ep-bg-purple" />
68+
{{ $t('dynamicsForm.tag.label') }}
69+
</el-col>
70+
<el-col :span="12">
71+
<div class="grid-content ep-bg-purple" />
72+
{{ $t('dynamicsForm.Select.label') }}
73+
</el-col>
74+
</el-row>
75+
<el-row
76+
style="width: 100%"
77+
v-for="(option, $index) in formValue.option_list"
78+
:key="$index"
79+
:gutter="10"
80+
class="mb-8"
81+
>
82+
<el-col :span="10">
83+
<div class="grid-content ep-bg-purple" />
84+
<el-input
85+
v-model="formValue.option_list[$index].label"
86+
:placeholder="$t('dynamicsForm.tag.placeholder')"
87+
/>
88+
</el-col>
89+
<el-col :span="12">
90+
<div class="grid-content ep-bg-purple" />
91+
<el-input
92+
v-model="formValue.option_list[$index].value"
93+
:placeholder="$t('dynamicsForm.Select.label')"
94+
/>
95+
</el-col>
96+
<el-col :span="1">
97+
<div class="grid-content ep-bg-purple" />
98+
<el-button link class="ml-8" @click.stop="delOption($index)">
99+
<AppIcon iconName="app-delete"></AppIcon>
100+
</el-button>
101+
</el-col>
102+
</el-row>
103+
</el-form-item>
104+
<el-form-item
105+
v-if="formValue.assignment_method == 'custom'"
106+
class="defaultValueItem"
107+
:label="$t('dynamicsForm.default.label')"
108+
:required="formValue.required"
109+
prop="default_value"
110+
:rules="
111+
formValue.required
112+
? [
113+
{
114+
required: true,
115+
message: `${$t('dynamicsForm.default.label')}${$t('dynamicsForm.default.requiredMessage')}`,
116+
},
117+
]
118+
: []
119+
"
120+
>
121+
<div class="defaultValueCheckbox">
122+
<el-checkbox
123+
v-model="formValue.show_default_value"
124+
:label="$t('dynamicsForm.default.show')"
125+
/>
126+
</div>
127+
<MultiRow
128+
:form-field="formField"
129+
v-model="formValue.default_value"
130+
:other-params="{}"
131+
field="default_value"
132+
>
133+
</MultiRow>
134+
</el-form-item>
135+
</template>
136+
<script setup lang="ts">
137+
import { computed, onMounted, inject } from 'vue'
138+
import MultiRow from '@/components/dynamics-form/items/MultiRow.vue'
139+
import NodeCascader from '@/workflow/common/NodeCascader.vue'
140+
import type { FormField } from '@/components/dynamics-form/type'
141+
import { t } from '@/locales'
142+
const getModel = inject('getModel') as any
143+
144+
const assignment_method_option_list = computed(() => {
145+
const option_list = [
146+
{
147+
label: t('dynamicsForm.AssignmentMethod.custom.label', '自定义'),
148+
value: 'custom',
149+
},
150+
]
151+
if (getModel) {
152+
option_list.push({
153+
label: t('dynamicsForm.AssignmentMethod.ref_variables.label', '引用变量'),
154+
value: 'ref_variables',
155+
})
156+
}
157+
return option_list
158+
})
159+
160+
const model = computed(() => {
161+
if (getModel) {
162+
return getModel()
163+
} else {
164+
return null
165+
}
166+
})
167+
const props = defineProps<{
168+
modelValue: any
169+
}>()
170+
const emit = defineEmits(['update:modelValue'])
171+
const formValue = computed({
172+
set: (item) => {
173+
emit('update:modelValue', item)
174+
},
175+
get: () => {
176+
return props.modelValue
177+
},
178+
})
179+
180+
const default_ref_variables_value_rule = {
181+
required: true,
182+
validator: (rule: any, value: any, callback: any) => {
183+
console.log(value.length)
184+
if (!(Array.isArray(value) && value.length > 1)) {
185+
callback(
186+
t('dynamicsForm.AssignmentMethod.ref_variables.label', '引用变量') + t('common.required'),
187+
)
188+
}
189+
190+
return true
191+
},
192+
trigger: 'blur',
193+
}
194+
const addOption = () => {
195+
formValue.value.option_list.push({ value: '', label: '' })
196+
}
197+
198+
const delOption = (index: number) => {
199+
const option = formValue.value.option_list[index]
200+
if (option.value && formValue.value.default_value == option.value) {
201+
formValue.value.default_value = ''
202+
}
203+
formValue.value.option_list.splice(index, 1)
204+
}
205+
const formField = computed<FormField>(() => {
206+
return { field: '', ...getData() }
207+
})
208+
const getData = () => {
209+
return {
210+
input_type: 'MultiRow',
211+
attrs: {},
212+
default_value: formValue.value.default_value,
213+
text_field: 'label',
214+
value_field: 'value',
215+
option_list: formValue.value.option_list,
216+
assignment_method: formValue.value.assignment_method || 'custom',
217+
}
218+
}
219+
const rander = (form_data: any) => {
220+
formValue.value.option_list = form_data.option_list || []
221+
formValue.value.default_value = form_data.default_value
222+
formValue.value.assignment_method = form_data.assignment_method || 'custom'
223+
}
224+
225+
defineExpose({ getData, rander })
226+
onMounted(() => {
227+
formValue.value.option_list = []
228+
formValue.value.default_value = ''
229+
formValue.value.assignment_method = 'custom'
230+
if (formValue.value.show_default_value === undefined) {
231+
formValue.value.show_default_value = true
232+
}
233+
addOption()
234+
})
235+
</script>
236+
<style lang="scss" scoped>
237+
.defaultValueItem {
238+
position: relative;
239+
.defaultValueCheckbox {
240+
position: absolute;
241+
right: 0;
242+
top: -35px;
243+
}
244+
}
245+
:deep(.el-form-item__label) {
246+
display: block;
247+
}
248+
249+
:deep(.el-select-dropdown) {
250+
max-width: 400px;
251+
}
252+
</style>

0 commit comments

Comments
 (0)