feat: Enhance dynamic form rendering (#4223)
parent
da7f0edecd
commit
727c8bfa98
|
|
@ -5,6 +5,7 @@
|
||||||
:model="form_data"
|
:model="form_data"
|
||||||
:render_data="damo_data"
|
:render_data="damo_data"
|
||||||
ref="dynamicsFormRef"
|
ref="dynamicsFormRef"
|
||||||
|
:other-params="{ current_workspace_id: 'default' }"
|
||||||
>
|
>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-form-item label="其他字段">
|
<el-form-item label="其他字段">
|
||||||
|
|
@ -21,7 +22,30 @@ import { ref } from 'vue'
|
||||||
import type { Dict } from '@/api/type/common'
|
import type { Dict } from '@/api/type/common'
|
||||||
|
|
||||||
const damo_data: Array<FormField> = [
|
const damo_data: Array<FormField> = [
|
||||||
{ field: 'name', input_type: 'PasswordInput', label: '用戶名', required: false },
|
{
|
||||||
|
field: 'name',
|
||||||
|
input_type: 'PasswordInput',
|
||||||
|
label: {
|
||||||
|
label: '用戶名',
|
||||||
|
input_type: 'SettingLabel',
|
||||||
|
field: 'name_setting',
|
||||||
|
relation_show_field_dict: {
|
||||||
|
name: {
|
||||||
|
values: ['01993837-5b09-7f20-9360-801d11d43d28'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relation_trigger_field_dict: {
|
||||||
|
name: {
|
||||||
|
values: ['01993837-5b09-7f20-9360-801d11d43d28'],
|
||||||
|
request:
|
||||||
|
'self.children=()=>request.get(extra.renderTemplate(trigger_setting.url)).then(ok=>{return ok})',
|
||||||
|
url: '/workspace/${current_workspace_id}/model/${trigger_value}/model_params_form',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
{ field: 'json_text', input_type: 'JsonInput', label: 'aa', required: false },
|
{ field: 'json_text', input_type: 'JsonInput', label: 'aa', required: false },
|
||||||
{
|
{
|
||||||
field: 'array_object_card_field',
|
field: 'array_object_card_field',
|
||||||
|
|
@ -33,8 +57,8 @@ const damo_data: Array<FormField> = [
|
||||||
children: [
|
children: [
|
||||||
{ field: 'name1', input_type: 'TextInput', label: '用戶名1' },
|
{ field: 'name1', input_type: 'TextInput', label: '用戶名1' },
|
||||||
{ field: 'name2', input_type: 'TextInput', label: '用戶名2' },
|
{ field: 'name2', input_type: 'TextInput', label: '用戶名2' },
|
||||||
{ field: 'name3', input_type: 'TextInput', label: '用戶名3' }
|
{ field: 'name3', input_type: 'TextInput', label: '用戶名3' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'maxkb_tokens',
|
field: 'maxkb_tokens',
|
||||||
|
|
@ -46,9 +70,9 @@ const damo_data: Array<FormField> = [
|
||||||
step: 1,
|
step: 1,
|
||||||
precision: 1,
|
precision: 1,
|
||||||
'show-input-controls': false,
|
'show-input-controls': false,
|
||||||
'show-input': true
|
'show-input': true,
|
||||||
},
|
},
|
||||||
label: { label: '温度', attrs: { tooltip: 'sss' }, input_type: 'TooltipLabel' }
|
label: { label: '温度', attrs: { tooltip: 'sss' }, input_type: 'TooltipLabel' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'object_card_field',
|
field: 'object_card_field',
|
||||||
|
|
@ -60,8 +84,8 @@ const damo_data: Array<FormField> = [
|
||||||
children: [
|
children: [
|
||||||
{ field: 'name1', input_type: 'TextInput', label: '用戶名1' },
|
{ field: 'name1', input_type: 'TextInput', label: '用戶名1' },
|
||||||
{ field: 'name2', input_type: 'TextInput', label: '用戶名2' },
|
{ field: 'name2', input_type: 'TextInput', label: '用戶名2' },
|
||||||
{ field: 'name3', input_type: 'TextInput', label: '用戶名3' }
|
{ field: 'name3', input_type: 'TextInput', label: '用戶名3' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'tab_card_field',
|
field: 'tab_card_field',
|
||||||
|
|
@ -70,39 +94,54 @@ const damo_data: Array<FormField> = [
|
||||||
trigger_type: 'CHILD_FORMS',
|
trigger_type: 'CHILD_FORMS',
|
||||||
attrs: { 'label-width': '120px', 'label-suffix': ':ssss', 'label-position': 'left' },
|
attrs: { 'label-width': '120px', 'label-suffix': ':ssss', 'label-position': 'left' },
|
||||||
required: false,
|
required: false,
|
||||||
relation_trigger_field_dict: {
|
|
||||||
'array_object_card_field.0.name1': ['111']
|
|
||||||
},
|
|
||||||
props_info: { tabs_label: '用户' },
|
props_info: { tabs_label: '用户' },
|
||||||
children: [
|
children: [
|
||||||
{ field: 'name1', input_type: 'TextInput', label: '用戶名1' },
|
{ field: 'name1', input_type: 'TextInput', label: '用戶名1' },
|
||||||
{ field: 'name2', input_type: 'TextInput', label: '用戶名2' },
|
{ field: 'name2', input_type: 'TextInput', label: '用戶名2' },
|
||||||
{ field: 'name3', input_type: 'TextInput', label: '用戶名3' }
|
{ field: 'name3', input_type: 'TextInput', label: '用戶名3' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'single_select_field',
|
field: 'single_select_field',
|
||||||
input_type: 'SingleSelect',
|
input_type: 'SingleSelect',
|
||||||
label: '测试单选',
|
text_field: 'name',
|
||||||
|
value_field: 'id',
|
||||||
required: true,
|
required: true,
|
||||||
attrs: { placeholder: '请选择' },
|
attrs: { placeholder: '请选择' },
|
||||||
option_list: [
|
required_asterisk: true,
|
||||||
{
|
label: {
|
||||||
key: '测试',
|
label: '测试单选',
|
||||||
value: 'test'
|
input_type: 'SettingLabel',
|
||||||
|
field: 'name_setting',
|
||||||
|
relation_show_field_dict: {
|
||||||
|
single_select_field: {
|
||||||
|
values: [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
relation_trigger_field_dict: {
|
||||||
key: '测试1',
|
single_select_field: {
|
||||||
value: 'test1'
|
values: [],
|
||||||
}
|
request:
|
||||||
]
|
'self.children=()=>request.get(extra.renderTemplate(trigger_setting.url)).then(ok=>{return ok})',
|
||||||
|
url: '/workspace/${current_workspace_id}/model/${trigger_value}/model_params_form',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
relation_trigger_field_dict: {
|
||||||
|
name: {
|
||||||
|
values: [],
|
||||||
|
url: '/workspace/${current_workspace_id}/model_list?model_type=LLM',
|
||||||
|
change_field: 'option_list',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'multi_select_field',
|
field: 'multi_select_field',
|
||||||
input_type: 'MultiSelect',
|
input_type: 'MultiSelect',
|
||||||
default_value: ['test1'],
|
default_value: ['test1'],
|
||||||
relation_show_field_dict: {
|
relation_show_field_dict: {
|
||||||
'object_card_field.name1': []
|
'object_card_field.name1': [],
|
||||||
},
|
},
|
||||||
label: '测试多选下拉',
|
label: '测试多选下拉',
|
||||||
required: true,
|
required: true,
|
||||||
|
|
@ -110,13 +149,13 @@ const damo_data: Array<FormField> = [
|
||||||
option_list: [
|
option_list: [
|
||||||
{
|
{
|
||||||
key: '测试',
|
key: '测试',
|
||||||
value: 'test'
|
value: 'test',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '测试1',
|
key: '测试1',
|
||||||
value: 'test1'
|
value: 'test1',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'radio_field',
|
field: 'radio_field',
|
||||||
|
|
@ -127,13 +166,13 @@ const damo_data: Array<FormField> = [
|
||||||
option_list: [
|
option_list: [
|
||||||
{
|
{
|
||||||
key: '测试',
|
key: '测试',
|
||||||
value: 'test'
|
value: 'test',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '测试1',
|
key: '测试1',
|
||||||
value: 'test1'
|
value: 'test1',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'radio_button_field',
|
field: 'radio_button_field',
|
||||||
|
|
@ -144,13 +183,13 @@ const damo_data: Array<FormField> = [
|
||||||
option_list: [
|
option_list: [
|
||||||
{
|
{
|
||||||
key: '测试',
|
key: '测试',
|
||||||
value: 'test'
|
value: 'test',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '测试1',
|
key: '测试1',
|
||||||
value: 'test1'
|
value: 'test1',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'radio_card_field',
|
field: 'radio_card_field',
|
||||||
|
|
@ -161,13 +200,13 @@ const damo_data: Array<FormField> = [
|
||||||
option_list: [
|
option_list: [
|
||||||
{
|
{
|
||||||
key: '测试',
|
key: '测试',
|
||||||
value: 'test'
|
value: 'test',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '测试111111',
|
key: '测试111111',
|
||||||
value: 'test1'
|
value: 'test1',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'table_radio_field',
|
field: 'table_radio_field',
|
||||||
|
|
@ -181,7 +220,7 @@ const damo_data: Array<FormField> = [
|
||||||
{
|
{
|
||||||
property: '`${row.key}${row.number}`',
|
property: '`${row.key}${row.number}`',
|
||||||
label: '名称',
|
label: '名称',
|
||||||
type: 'eval'
|
type: 'eval',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
property: 'ProgressTableItem',
|
property: 'ProgressTableItem',
|
||||||
|
|
@ -194,8 +233,8 @@ const damo_data: Array<FormField> = [
|
||||||
{ color: '#e6a23c', percentage: 40 },
|
{ color: '#e6a23c', percentage: 40 },
|
||||||
{ color: '#5cb87a', percentage: 60 },
|
{ color: '#5cb87a', percentage: 60 },
|
||||||
{ color: '#1989fa', percentage: 80 },
|
{ color: '#1989fa', percentage: 80 },
|
||||||
{ color: '#6f7ad3', percentage: 100 }
|
{ color: '#6f7ad3', percentage: 100 },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
props_info: {
|
props_info: {
|
||||||
view_card: [
|
view_card: [
|
||||||
|
|
@ -203,31 +242,31 @@ const damo_data: Array<FormField> = [
|
||||||
type: 'eval',
|
type: 'eval',
|
||||||
title: '测试',
|
title: '测试',
|
||||||
value_field:
|
value_field:
|
||||||
'`${parseFloat(row.number).toLocaleString("zh-CN",{style: "decimal",maximumFractionDigits:1})}% `'
|
'`${parseFloat(row.number).toLocaleString("zh-CN",{style: "decimal",maximumFractionDigits:1})}% `',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'eval',
|
type: 'eval',
|
||||||
title: '名称',
|
title: '名称',
|
||||||
value_field: '`${row.key} `'
|
value_field: '`${row.key} `',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
style: { width: '500px' }
|
style: { width: '500px' },
|
||||||
},
|
},
|
||||||
option_list: [
|
option_list: [
|
||||||
{
|
{
|
||||||
key: '测试',
|
key: '测试',
|
||||||
value: 'test',
|
value: 'test',
|
||||||
number: 10
|
number: 10,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '测试111111',
|
key: '测试111111',
|
||||||
value: 'test1',
|
value: 'test1',
|
||||||
number: 100
|
number: 100,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'table_checkbox_field',
|
field: 'table_checkbox_field',
|
||||||
|
|
@ -241,7 +280,7 @@ const damo_data: Array<FormField> = [
|
||||||
{
|
{
|
||||||
property: '`${row.key}${row.number}`',
|
property: '`${row.key}${row.number}`',
|
||||||
label: '名称',
|
label: '名称',
|
||||||
type: 'eval'
|
type: 'eval',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
property: 'ProgressTableItem',
|
property: 'ProgressTableItem',
|
||||||
|
|
@ -254,8 +293,8 @@ const damo_data: Array<FormField> = [
|
||||||
{ color: '#e6a23c', percentage: 40 },
|
{ color: '#e6a23c', percentage: 40 },
|
||||||
{ color: '#5cb87a', percentage: 60 },
|
{ color: '#5cb87a', percentage: 60 },
|
||||||
{ color: '#1989fa', percentage: 80 },
|
{ color: '#1989fa', percentage: 80 },
|
||||||
{ color: '#6f7ad3', percentage: 100 }
|
{ color: '#6f7ad3', percentage: 100 },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
props_info: {
|
props_info: {
|
||||||
view_card: [
|
view_card: [
|
||||||
|
|
@ -263,32 +302,32 @@ const damo_data: Array<FormField> = [
|
||||||
type: 'eval',
|
type: 'eval',
|
||||||
title: '测试',
|
title: '测试',
|
||||||
value_field:
|
value_field:
|
||||||
'`${parseFloat(row.number).toLocaleString("zh-CN",{style: "decimal",maximumFractionDigits:1})}% `'
|
'`${parseFloat(row.number).toLocaleString("zh-CN",{style: "decimal",maximumFractionDigits:1})}% `',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'eval',
|
type: 'eval',
|
||||||
title: '名称',
|
title: '名称',
|
||||||
value_field: '`${row.key} `'
|
value_field: '`${row.key} `',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
style: { width: '500px' }
|
style: { width: '500px' },
|
||||||
},
|
},
|
||||||
option_list: [
|
option_list: [
|
||||||
{
|
{
|
||||||
key: '测试',
|
key: '测试',
|
||||||
value: 'test',
|
value: 'test',
|
||||||
number: 10
|
number: 10,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '测试111111',
|
key: '测试111111',
|
||||||
value: 'test1',
|
value: 'test1',
|
||||||
number: 100
|
number: 100,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
const form_data = ref<Dict<any>>({})
|
const form_data = ref<Dict<any>>({})
|
||||||
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
|
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,16 @@
|
||||||
:prop="formfield.field"
|
:prop="formfield.field"
|
||||||
:key="formfield.field"
|
:key="formfield.field"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
|
:class="formfield.required_asterisk ? 'hide-asterisk' : ''"
|
||||||
>
|
>
|
||||||
<template #label v-if="formfield.label">
|
<template #label v-if="formfield.label">
|
||||||
<FormItemLabel v-if="isString(formfield.label)" :form-field="formfield"></FormItemLabel>
|
<FormItemLabel v-if="isString(formfield.label)" :form-field="formfield"></FormItemLabel>
|
||||||
<component
|
<component
|
||||||
v-else
|
v-else
|
||||||
:is="formfield.label.input_type"
|
:is="formfield.label.input_type"
|
||||||
:label="formfield.label.label"
|
:label="formfield.label"
|
||||||
|
v-model="labelValue"
|
||||||
|
:form-value="formValue"
|
||||||
v-bind="label_attrs"
|
v-bind="label_attrs"
|
||||||
></component>
|
></component>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -36,6 +39,7 @@ import FormItemLabel from './FormItemLabel.vue'
|
||||||
import type { Dict } from '@/api/type/common'
|
import type { Dict } from '@/api/type/common'
|
||||||
import bus from '@/utils/bus'
|
import bus from '@/utils/bus'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
import { get } from 'lodash'
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
// 双向绑定的值
|
// 双向绑定的值
|
||||||
modelValue: any
|
modelValue: any
|
||||||
|
|
@ -47,7 +51,13 @@ const props = defineProps<{
|
||||||
// 调用接口所需要的其他参数
|
// 调用接口所需要的其他参数
|
||||||
otherParams: any
|
otherParams: any
|
||||||
// 获取Options
|
// 获取Options
|
||||||
trigger: (formItem: FormField, loading: Ref<boolean>) => Promise<any>
|
trigger: (
|
||||||
|
trigger_field: string,
|
||||||
|
trigger_value: any,
|
||||||
|
trigger_setting: any,
|
||||||
|
self: any,
|
||||||
|
loading: Ref<boolean>,
|
||||||
|
) => void
|
||||||
// 初始化默认数据
|
// 初始化默认数据
|
||||||
initDefaultData: (formItem: FormField) => void
|
initDefaultData: (formItem: FormField) => void
|
||||||
// 默认每个宽度
|
// 默认每个宽度
|
||||||
|
|
@ -60,13 +70,22 @@ const props = defineProps<{
|
||||||
parent_field?: string
|
parent_field?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['change'])
|
const emit = defineEmits(['change', 'changeLabel'])
|
||||||
|
|
||||||
const loading = ref<boolean>(false)
|
const loading = ref<boolean>(false)
|
||||||
|
|
||||||
const isString = (value: any) => {
|
const isString = (value: any) => {
|
||||||
return typeof value === 'string'
|
return typeof value === 'string'
|
||||||
}
|
}
|
||||||
|
const labelValue = computed({
|
||||||
|
get: () => {
|
||||||
|
return props.formValue[props.formfield.label.field]
|
||||||
|
},
|
||||||
|
set: (value: any) => {
|
||||||
|
emit('changeLabel', value)
|
||||||
|
bus.emit(props.formfield.label.field, value)
|
||||||
|
},
|
||||||
|
})
|
||||||
const itemValue = computed({
|
const itemValue = computed({
|
||||||
get: () => {
|
get: () => {
|
||||||
return props.modelValue
|
return props.modelValue
|
||||||
|
|
@ -147,32 +166,50 @@ const componentStyle = computed(() => {
|
||||||
const attrs = computed(() => {
|
const attrs = computed(() => {
|
||||||
return props.formfield.attrs ? props.formfield.attrs : {}
|
return props.formfield.attrs ? props.formfield.attrs : {}
|
||||||
})
|
})
|
||||||
|
const initTrigger = (self: any, trigger_field_dict?: Dict<any>) => {
|
||||||
|
if (trigger_field_dict) {
|
||||||
|
Object.keys(trigger_field_dict).forEach((key) => {
|
||||||
|
const setting = trigger_field_dict[key]
|
||||||
|
const triggerValues = setting['values']
|
||||||
|
const value = get(props.formValue, key)
|
||||||
|
if (triggerValues && triggerValues.length > 0) {
|
||||||
|
if (triggerValues.includes(value)) {
|
||||||
|
props.trigger(key, value, setting, self, loading)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
props.trigger(key, value, setting, self, loading)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
props.initDefaultData(props.formfield)
|
props.initDefaultData(props.formfield)
|
||||||
if (props.formfield.provider && props.formfield.method) {
|
initTrigger(props.formfield, props.formfield.relation_trigger_field_dict)
|
||||||
props.trigger(props.formfield, loading)
|
initTrigger(props.formfield.label, props.formfield.label?.relation_trigger_field_dict)
|
||||||
}
|
isString(props.formfield.label)
|
||||||
// 监听字段变化
|
? undefined
|
||||||
const trigger_field_dict = props.formfield.relation_trigger_field_dict
|
: onTrigger(props.formfield.label, props.formfield.label.relation_trigger_field_dict)
|
||||||
|
onTrigger(props.formfield, props.formfield.relation_trigger_field_dict)
|
||||||
|
})
|
||||||
|
const onTrigger = (self: any, trigger_field_dict?: Dict<any>) => {
|
||||||
if (trigger_field_dict) {
|
if (trigger_field_dict) {
|
||||||
const keys = Object.keys(trigger_field_dict)
|
const keys = Object.keys(trigger_field_dict)
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
const value = trigger_field_dict[key]
|
const setting = trigger_field_dict[key]
|
||||||
|
const values: Array<any> = setting.values
|
||||||
// 添加关系
|
// 添加关系
|
||||||
bus.on(key, (v: any) => {
|
bus.on(key, (v: any) => {
|
||||||
if (value && value.length > 0) {
|
if (values && values.length > 0) {
|
||||||
if (value.includes(v)) {
|
if (values.includes(v)) {
|
||||||
props.trigger(props.formfield, loading)
|
props.trigger(key, v, setting, self, loading)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
props.trigger(props.formfield, loading)
|
props.trigger(key, v, setting, self, loading)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
if (props.formfield.trigger_type === 'CHILD_FORMS' && componentFormRef.value) {
|
if (props.formfield.trigger_type === 'CHILD_FORMS' && componentFormRef.value) {
|
||||||
return componentFormRef.value.validate()
|
return componentFormRef.value.validate()
|
||||||
|
|
@ -181,4 +218,10 @@ const validate = () => {
|
||||||
}
|
}
|
||||||
defineExpose({ validate })
|
defineExpose({ validate })
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.hide-asterisk {
|
||||||
|
::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import type { App } from 'vue'
|
||||||
import type { Dict } from '@/api/type/common'
|
import type { Dict } from '@/api/type/common'
|
||||||
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||||
let components: Dict<any> = import.meta.glob('@/components/dynamics-form/**/**.vue', {
|
let components: Dict<any> = import.meta.glob('@/components/dynamics-form/**/**.vue', {
|
||||||
eager: true
|
eager: true,
|
||||||
})
|
})
|
||||||
components = {
|
components = {
|
||||||
...components,
|
...components,
|
||||||
...import.meta.glob('@/components/dynamics-form/**/**/**.vue', {
|
...import.meta.glob('@/components/dynamics-form/**/**/**.vue', {
|
||||||
eager: true
|
eager: true,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
const install = (app: App) => {
|
const install = (app: App) => {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
label-suffix=":"
|
label-suffix=":"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
>
|
>
|
||||||
<slot :form_value="formValue"></slot>
|
<slot :form_value="formValue"></slot>
|
||||||
<template v-for="item in formFieldList" :key="item.field">
|
<template v-for="item in formFieldList" :key="item.field">
|
||||||
|
|
@ -14,6 +16,7 @@
|
||||||
:key="item.field"
|
:key="item.field"
|
||||||
v-if="show(item)"
|
v-if="show(item)"
|
||||||
@change="change(item, $event)"
|
@change="change(item, $event)"
|
||||||
|
@changeLabel="changeLabel(item, $event)"
|
||||||
v-bind:modelValue="formValue[item.field]"
|
v-bind:modelValue="formValue[item.field]"
|
||||||
:formfield="item"
|
:formfield="item"
|
||||||
:trigger="trigger"
|
:trigger="trigger"
|
||||||
|
|
@ -33,18 +36,27 @@
|
||||||
import type { Dict } from '@/api/type/common'
|
import type { Dict } from '@/api/type/common'
|
||||||
import FormItem from '@/components/dynamics-form/FormItem.vue'
|
import FormItem from '@/components/dynamics-form/FormItem.vue'
|
||||||
import type { FormField } from '@/components/dynamics-form/type'
|
import type { FormField } from '@/components/dynamics-form/type'
|
||||||
import { ref, onBeforeMount, watch, type Ref } from 'vue'
|
import { ref, onBeforeMount, watch, type Ref, computed } from 'vue'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
import { get } from '@/request/index'
|
|
||||||
import type Result from '@/request/Result'
|
import type Result from '@/request/Result'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { get, post, put, del } from '@/request/index'
|
||||||
|
const request = {
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
put,
|
||||||
|
del,
|
||||||
|
}
|
||||||
defineOptions({ name: 'dynamicsForm' })
|
defineOptions({ name: 'dynamicsForm' })
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
// 页面渲染数据
|
// 页面渲染数据
|
||||||
render_data: Promise<Result<Array<FormField>>> | string | Array<FormField>
|
render_data:
|
||||||
|
| Promise<Result<Array<FormField>>>
|
||||||
|
| string
|
||||||
|
| Array<FormField>
|
||||||
|
| (() => Promise<Result<Array<FormField>>>)
|
||||||
// 调用接口所需要的其他参数
|
// 调用接口所需要的其他参数
|
||||||
otherParams?: any
|
otherParams?: any
|
||||||
// 是否只读
|
// 是否只读
|
||||||
|
|
@ -103,6 +115,15 @@ const change = (field: FormField, value: any) => {
|
||||||
formValue.value[field.field] = value
|
formValue.value[field.field] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单字段修改
|
||||||
|
* @param field
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
const changeLabel = (field: FormField, value: any) => {
|
||||||
|
formValue.value[field.label.field] = value
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
formValue,
|
formValue,
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -110,14 +131,60 @@ watch(
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
function renderTemplate(template: string, data: any) {
|
||||||
|
return template.replace(/\$\{(\w+)\}/g, (match, key) => {
|
||||||
|
return data[key] !== undefined ? data[key] : match
|
||||||
|
})
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 触发器,用户获取子表单 或者 下拉选项
|
* 触发器,用户获取子表单 或者 下拉选项
|
||||||
* @param field
|
* @param field
|
||||||
* @param loading
|
* @param loading
|
||||||
*/
|
*/
|
||||||
const trigger = (field: FormField, loading: Ref<boolean>) => {
|
const trigger = (
|
||||||
return Promise.resolve([])
|
trigger_field: string,
|
||||||
|
trigger_value: any,
|
||||||
|
trigger_setting: any,
|
||||||
|
self: any,
|
||||||
|
loading: Ref<boolean>,
|
||||||
|
) => {
|
||||||
|
const request_call = new Function(
|
||||||
|
'self',
|
||||||
|
'trigger_setting',
|
||||||
|
'request',
|
||||||
|
'extra',
|
||||||
|
trigger_setting.request
|
||||||
|
? trigger_setting.request
|
||||||
|
: 'return request.get(extra.renderTemplate(trigger_setting.url));',
|
||||||
|
)(self, trigger_setting, request, {
|
||||||
|
renderTemplate: (url: string) =>
|
||||||
|
renderTemplate(url, {
|
||||||
|
trigger_value: trigger_value,
|
||||||
|
...props.otherParams,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!trigger_setting.change && !trigger_setting.change_field) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request_call.then((ok: any) => {
|
||||||
|
new Function(
|
||||||
|
'self',
|
||||||
|
'trigger_setting',
|
||||||
|
'response',
|
||||||
|
'extra',
|
||||||
|
trigger_setting.change
|
||||||
|
? trigger_setting.change
|
||||||
|
: `self[trigger_setting.change_field]=[
|
||||||
|
...response.data.shared_model.map((m) => {
|
||||||
|
return { ...m, type: 'share' }
|
||||||
|
}),
|
||||||
|
...response.data.model.map((m) => {
|
||||||
|
return { ...m, type: 'workspace' }
|
||||||
|
})
|
||||||
|
];`,
|
||||||
|
)(self, trigger_setting, ok, { form_data: formValue, getDefault: getFormDefaultValue })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 初始化默认数据
|
* 初始化默认数据
|
||||||
|
|
@ -141,7 +208,11 @@ onBeforeMount(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const render = (
|
const render = (
|
||||||
render_data: string | Array<FormField> | Promise<Result<Array<FormField>>>,
|
render_data:
|
||||||
|
| string
|
||||||
|
| Array<FormField>
|
||||||
|
| Promise<Result<Array<FormField>>>
|
||||||
|
| (() => Promise<Result<Array<FormField>>>),
|
||||||
data?: Dict<any>,
|
data?: Dict<any>,
|
||||||
) => {
|
) => {
|
||||||
if (typeof render_data == 'string') {
|
if (typeof render_data == 'string') {
|
||||||
|
|
@ -150,6 +221,15 @@ const render = (
|
||||||
})
|
})
|
||||||
} else if (render_data instanceof Array) {
|
} else if (render_data instanceof Array) {
|
||||||
formFieldList.value = render_data
|
formFieldList.value = render_data
|
||||||
|
} else if (typeof render_data === 'function') {
|
||||||
|
render_data().then((ok: any) => {
|
||||||
|
formFieldList.value = ok.data
|
||||||
|
const form_data = data ? data : {}
|
||||||
|
if (form_data) {
|
||||||
|
const value = getFormDefaultValue(formFieldList.value, form_data)
|
||||||
|
formValue.value = _.cloneDeep(value)
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
render_data.then((ok) => {
|
render_data.then((ok) => {
|
||||||
formFieldList.value = ok.data
|
formFieldList.value = ok.data
|
||||||
|
|
@ -157,37 +237,42 @@ const render = (
|
||||||
}
|
}
|
||||||
const form_data = data ? data : {}
|
const form_data = data ? data : {}
|
||||||
if (form_data) {
|
if (form_data) {
|
||||||
const value = formFieldList.value
|
const value = getFormDefaultValue(formFieldList.value, form_data)
|
||||||
.map((item) => {
|
|
||||||
if (form_data[item.field] !== undefined) {
|
|
||||||
if (item.value_field && item.option_list && item.option_list.length > 0) {
|
|
||||||
const value_field = item.value_field
|
|
||||||
const find = item.option_list?.find((i) => {
|
|
||||||
if (typeof form_data[item.field] === 'string') {
|
|
||||||
return i[value_field] === form_data[item.field]
|
|
||||||
} else {
|
|
||||||
return form_data[item.field].indexOf([value_field]) === -1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (find) {
|
|
||||||
return { [item.field]: form_data[item.field] }
|
|
||||||
}
|
|
||||||
if (item.show_default_value === true || item.show_default_value === undefined) {
|
|
||||||
return { [item.field]: item.default_value }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return { [item.field]: form_data[item.field] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (item.show_default_value === true || item.show_default_value === undefined) {
|
|
||||||
return { [item.field]: item.default_value }
|
|
||||||
}
|
|
||||||
return {}
|
|
||||||
})
|
|
||||||
.reduce((x, y) => ({ ...x, ...y }), {})
|
|
||||||
formValue.value = _.cloneDeep(value)
|
formValue.value = _.cloneDeep(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const getFormDefaultValue = (fieldList: Array<any>, form_data?: any) => {
|
||||||
|
form_data = form_data ? form_data : {}
|
||||||
|
const value = fieldList
|
||||||
|
.map((item) => {
|
||||||
|
if (form_data[item.field] !== undefined) {
|
||||||
|
if (item.value_field && item.option_list && item.option_list.length > 0) {
|
||||||
|
const value_field = item.value_field
|
||||||
|
const find = item.option_list?.find((i: any) => {
|
||||||
|
if (typeof form_data[item.field] === 'string') {
|
||||||
|
return i[value_field] === form_data[item.field]
|
||||||
|
} else {
|
||||||
|
return form_data[item.field].indexOf([value_field]) === -1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (find) {
|
||||||
|
return { [item.field]: form_data[item.field] }
|
||||||
|
}
|
||||||
|
if (item.show_default_value === true || item.show_default_value === undefined) {
|
||||||
|
return { [item.field]: item.default_value }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return { [item.field]: form_data[item.field] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.show_default_value === true || item.show_default_value === undefined) {
|
||||||
|
return { [item.field]: item.default_value }
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
})
|
||||||
|
.reduce((x, y) => ({ ...x, ...y }), {})
|
||||||
|
return value
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 校验函数
|
* 校验函数
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
<DynamicsForm
|
<DynamicsForm
|
||||||
:style="formStyle"
|
:style="formStyle"
|
||||||
:view="view"
|
:view="view"
|
||||||
label-position="top"
|
|
||||||
require-asterisk-position="right"
|
|
||||||
ref="ceFormRef"
|
ref="ceFormRef"
|
||||||
v-model="_data[index]"
|
v-model="_data[index]"
|
||||||
:model="_data[index]"
|
:model="_data[index]"
|
||||||
|
|
@ -13,6 +11,8 @@
|
||||||
:render_data="render_data()"
|
:render_data="render_data()"
|
||||||
v-bind="attr"
|
v-bind="attr"
|
||||||
:parent_field="formField.field + '.' + index"
|
:parent_field="formField.field + '.' + index"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
></DynamicsForm>
|
></DynamicsForm>
|
||||||
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||||
<el-button text @click.stop="deleteKnowledge(item)" class="delete-button">
|
<el-button text @click.stop="deleteKnowledge(item)" class="delete-button">
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
<DynamicsForm
|
<DynamicsForm
|
||||||
:read-only="view"
|
:read-only="view"
|
||||||
:style="formStyle"
|
:style="formStyle"
|
||||||
label-position="top"
|
|
||||||
require-asterisk-position="right"
|
|
||||||
ref="dynamicsFormRef"
|
ref="dynamicsFormRef"
|
||||||
v-model="data"
|
v-model="data"
|
||||||
:other-params="other"
|
:other-params="other"
|
||||||
:render_data="formField.children ? formField.children : []"
|
:render_data="formField.children ? formField.children : []"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:parent_field="formField.field"
|
:parent_field="formField.field"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
></DynamicsForm>
|
></DynamicsForm>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -38,7 +38,7 @@ const data = computed({
|
||||||
},
|
},
|
||||||
set: ($event) => {
|
set: ($event) => {
|
||||||
emit('update:modelValue', $event)
|
emit('update:modelValue', $event)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const other = computed(() => {
|
const other = computed(() => {
|
||||||
|
|
@ -69,7 +69,7 @@ function validate() {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate
|
validate,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
<DynamicsForm
|
<DynamicsForm
|
||||||
:style="formStyle"
|
:style="formStyle"
|
||||||
:view="view"
|
:view="view"
|
||||||
label-position="top"
|
|
||||||
require-asterisk-position="right"
|
|
||||||
ref="ceFormRef"
|
ref="ceFormRef"
|
||||||
v-model="_data[index]"
|
v-model="_data[index]"
|
||||||
:model="_data[index]"
|
:model="_data[index]"
|
||||||
|
|
@ -21,6 +19,8 @@
|
||||||
:render_data="render_data()"
|
:render_data="render_data()"
|
||||||
v-bind="attr"
|
v-bind="attr"
|
||||||
:parent_field="formField.field + '.' + index"
|
:parent_field="formField.field + '.' + index"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
></DynamicsForm>
|
></DynamicsForm>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -66,7 +66,7 @@ const _data = computed<Array<any>>({
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
emit('update:modelValue', value)
|
emit('update:modelValue', value)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const props_info = computed(() => {
|
const props_info = computed(() => {
|
||||||
|
|
@ -117,7 +117,7 @@ const handleTabsEdit = (targetName: TabPaneName | undefined, action: 'remove' |
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate,
|
validate,
|
||||||
field: props.field
|
field: props.field,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex-between w-full my-required">
|
||||||
|
<div>
|
||||||
|
<span> {{ label.label }}<span class="color-danger">*</span></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-tooltip v-if="label.attrs?.tooltip" effect="dark" placement="right">
|
||||||
|
<template #content
|
||||||
|
><div style="max-width: 200px">{{ label.attrs.tooltip }}</div></template
|
||||||
|
>
|
||||||
|
<AppIcon iconName="app-warning" class="app-warning-icon" style="flex-shrink: 0"></AppIcon>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="show(label)" type="primary" link @click="open()">
|
||||||
|
<AppIcon iconName="app-setting"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
<el-dialog
|
||||||
|
destroy-on-close
|
||||||
|
v-model="dialogVisible"
|
||||||
|
title="Tips"
|
||||||
|
width="500"
|
||||||
|
:before-close="close"
|
||||||
|
>
|
||||||
|
<DynamicsForm
|
||||||
|
:read-only="view"
|
||||||
|
ref="dynamicsFormRef"
|
||||||
|
:render_data="label.children ? label.children : []"
|
||||||
|
label-position="top"
|
||||||
|
v-model="form_data"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
:model="form_data"
|
||||||
|
></DynamicsForm>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submit"> 确定 </el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { cloneDeep, get } from 'lodash'
|
||||||
|
const props = defineProps<{
|
||||||
|
label: any
|
||||||
|
modelValue?: any
|
||||||
|
formValue: any
|
||||||
|
view?: boolean
|
||||||
|
}>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
|
||||||
|
const form_data = ref<any>(undefined)
|
||||||
|
const open = () => {
|
||||||
|
if (props.modelValue) {
|
||||||
|
form_data.value = cloneDeep(props.modelValue)
|
||||||
|
}
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
const close = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
form_data.value = undefined
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 当前 field是否展示
|
||||||
|
* @param field
|
||||||
|
*/
|
||||||
|
const show = (field: any) => {
|
||||||
|
if (field.relation_show_field_dict) {
|
||||||
|
const keys = Object.keys(field.relation_show_field_dict)
|
||||||
|
for (const index in keys) {
|
||||||
|
const key = keys[index]
|
||||||
|
const v = get(props.formValue, key)
|
||||||
|
if (v && v !== undefined && v !== null) {
|
||||||
|
const values = field.relation_show_field_dict[key]
|
||||||
|
if (values && values.length > 0) {
|
||||||
|
return values.includes(v)
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const submit = () => {
|
||||||
|
dynamicsFormRef.value?.validate().then(() => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
emit('update:modelValue', form_data.value)
|
||||||
|
form_data.value = undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex align-center" style="display: inline-flex">
|
<div class="flex align-center" style="display: inline-flex">
|
||||||
<div class="flex-between mr-4">
|
<div class="flex-between mr-4">
|
||||||
<span>{{ label }}</span>
|
<span>{{ label.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<el-tooltip effect="dark" placement="right">
|
<el-tooltip v-if="label.attrs.tooltip" effect="dark" placement="right">
|
||||||
<template #content
|
<template #content
|
||||||
><div style="max-width: 200px">{{ tooltip }}</div></template
|
><div style="max-width: 200px">{{ label.attrs.tooltip }}</div></template
|
||||||
>
|
>
|
||||||
<AppIcon iconName="app-warning" class="app-warning-icon" style="flex-shrink: 0"></AppIcon>
|
<AppIcon iconName="app-warning" class="app-warning-icon" style="flex-shrink: 0"></AppIcon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
@ -13,8 +13,7 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{
|
defineProps<{
|
||||||
label: string
|
label: any
|
||||||
tooltip: string
|
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<template>
|
||||||
|
<el-row> </el-row>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import type { FormField } from '@/components/dynamics-form/type'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
formValue?: any
|
||||||
|
formfieldList?: Array<FormField>
|
||||||
|
field: string
|
||||||
|
otherParams: any
|
||||||
|
formField: FormField
|
||||||
|
view?: boolean
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -42,7 +42,7 @@ const _modelValue = computed({
|
||||||
set(value) {
|
set(value) {
|
||||||
emit('update:modelValue', value)
|
emit('update:modelValue', value)
|
||||||
emit('change', props.formField)
|
emit('change', props.formField)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const textField = computed(() => {
|
const textField = computed(() => {
|
||||||
return props.formField.text_field ? props.formField.text_field : 'key'
|
return props.formField.text_field ? props.formField.text_field : 'key'
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ interface FormField {
|
||||||
/**
|
/**
|
||||||
* {field:field_value_list} 表示在 field有值 ,并且值在field_value_list中才 执行函数获取 数据
|
* {field:field_value_list} 表示在 field有值 ,并且值在field_value_list中才 执行函数获取 数据
|
||||||
*/
|
*/
|
||||||
relation_trigger_field_dict?: Dict<Array<any>>
|
relation_trigger_field_dict?: Dict<any>
|
||||||
/**
|
/**
|
||||||
* 执行器类型 OPTION_LIST请求Option_list数据 CHILD_FORMS请求子表单
|
* 执行器类型 OPTION_LIST请求Option_list数据 CHILD_FORMS请求子表单
|
||||||
*/
|
*/
|
||||||
|
|
@ -172,5 +172,6 @@ interface FormField {
|
||||||
method?: string
|
method?: string
|
||||||
|
|
||||||
children?: Array<FormField>
|
children?: Array<FormField>
|
||||||
|
required_asterisk?: boolean
|
||||||
}
|
}
|
||||||
export type { FormField }
|
export type { FormField }
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ instance.interceptors.request.use(
|
||||||
if (config.headers === undefined) {
|
if (config.headers === undefined) {
|
||||||
config.headers = new AxiosHeaders()
|
config.headers = new AxiosHeaders()
|
||||||
}
|
}
|
||||||
|
if (config.url && config.url.startsWith('http')) {
|
||||||
|
return config
|
||||||
|
}
|
||||||
const { user, login } = useStore()
|
const { user, login } = useStore()
|
||||||
const token = login.getToken()
|
const token = login.getToken()
|
||||||
const language = user.getLanguage()
|
const language = user.getLanguage()
|
||||||
|
|
@ -250,32 +253,33 @@ export const exportExcel: (
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractFilename(contentDisposition: string) {
|
function extractFilename(contentDisposition: string) {
|
||||||
if (!contentDisposition) return null;
|
if (!contentDisposition) return null
|
||||||
|
|
||||||
// 处理 URL 编码的文件名
|
// 处理 URL 编码的文件名
|
||||||
const urlEncodedMatch = contentDisposition.match(/filename=([^;]*)/i) ||
|
const urlEncodedMatch =
|
||||||
contentDisposition.match(/filename\*=UTF-8''([^;]*)/i);
|
contentDisposition.match(/filename=([^;]*)/i) ||
|
||||||
|
contentDisposition.match(/filename\*=UTF-8''([^;]*)/i)
|
||||||
if (urlEncodedMatch && urlEncodedMatch[1]) {
|
if (urlEncodedMatch && urlEncodedMatch[1]) {
|
||||||
try {
|
try {
|
||||||
return decodeURIComponent(urlEncodedMatch[1].replace(/"/g, ''));
|
return decodeURIComponent(urlEncodedMatch[1].replace(/"/g, ''))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("解码URL编码文件名失败:", e);
|
console.error('解码URL编码文件名失败:', e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 Base64 编码的文件名
|
// 处理 Base64 编码的文件名
|
||||||
const base64Part = contentDisposition.match(/=\?utf-8\?b\?(.*?)\?=/i)?.[1];
|
const base64Part = contentDisposition.match(/=\?utf-8\?b\?(.*?)\?=/i)?.[1]
|
||||||
if (base64Part) {
|
if (base64Part) {
|
||||||
try {
|
try {
|
||||||
const decoded = decodeURIComponent(escape(atob(base64Part)));
|
const decoded = decodeURIComponent(escape(atob(base64Part)))
|
||||||
const filenameMatch = decoded.match(/filename="(.*?)"/i);
|
const filenameMatch = decoded.match(/filename="(.*?)"/i)
|
||||||
return filenameMatch ? filenameMatch[1] : null;
|
return filenameMatch ? filenameMatch[1] : null
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("解码Base64文件名失败:", e);
|
console.error('解码Base64文件名失败:', e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportFile: (
|
export const exportFile: (
|
||||||
|
|
@ -320,20 +324,22 @@ export const exportFile: (
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
loading,
|
loading,
|
||||||
).then((res: any) => {
|
)
|
||||||
if (res) {
|
.then((res: any) => {
|
||||||
const blob = new Blob([res], {
|
if (res) {
|
||||||
type: 'application/octet-stream',
|
const blob = new Blob([res], {
|
||||||
})
|
type: 'application/octet-stream',
|
||||||
const link = document.createElement('a')
|
})
|
||||||
link.href = window.URL.createObjectURL(blob)
|
const link = document.createElement('a')
|
||||||
link.download = fileName
|
link.href = window.URL.createObjectURL(blob)
|
||||||
link.click()
|
link.download = fileName
|
||||||
//释放内存
|
link.click()
|
||||||
window.URL.revokeObjectURL(link.href)
|
//释放内存
|
||||||
}
|
window.URL.revokeObjectURL(link.href)
|
||||||
return true
|
}
|
||||||
}).catch(()=>{})
|
return true
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportExcelPost: (
|
export const exportExcelPost: (
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type {RouteRecordRaw} from 'vue-router'
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
const modules: any = import.meta.glob('./modules/*.ts', {eager: true})
|
const modules: any = import.meta.glob('./modules/*.ts', { eager: true })
|
||||||
|
|
||||||
const rolesRoutes: RouteRecordRaw[] = [...Object.keys(modules).map((key) => modules[key].default)]
|
const rolesRoutes: RouteRecordRaw[] = [...Object.keys(modules).map((key) => modules[key].default)]
|
||||||
|
|
||||||
|
|
@ -33,7 +33,7 @@ export const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
path: '/application/:from/:id/workflow',
|
path: '/application/:from/:id/workflow',
|
||||||
name: 'ApplicationWorkflow',
|
name: 'ApplicationWorkflow',
|
||||||
meta: {activeMenu: '/application'},
|
meta: { activeMenu: '/application' },
|
||||||
component: () => import('@/views/application-workflow/index.vue'),
|
component: () => import('@/views/application-workflow/index.vue'),
|
||||||
},
|
},
|
||||||
// 对话
|
// 对话
|
||||||
|
|
@ -42,6 +42,11 @@ export const routes: Array<RouteRecordRaw> = [
|
||||||
name: 'Chat',
|
name: 'Chat',
|
||||||
component: () => import('@/views/chat/index.vue'),
|
component: () => import('@/views/chat/index.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/demo',
|
||||||
|
name: 'demo',
|
||||||
|
component: () => import('@/views/demo/index.vue'),
|
||||||
|
},
|
||||||
|
|
||||||
// 对话用户登录
|
// 对话用户登录
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<template>
|
||||||
|
<div style="height: 500px">
|
||||||
|
<DemoVue />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import DemoVue from '@/components/dynamics-form/Demo.vue'
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
Loading…
Reference in New Issue